GraphQL API Implementation Status¶
This document tracks the implementation progress of the GraphQL API adapter for the Essert MES system.
Overview¶
The GraphQL API is built using HotChocolate v15.1.3 and follows the hexagonal architecture pattern, consuming the same Application layer services as the REST API.
Project Structure¶
Essert.MF.API.GraphQL/
├── Program.cs # Application entry point & GraphQL configuration
├── Queries/ # GraphQL query resolvers
│ ├── ProductQueries.cs
│ ├── ManufacturingQueries.cs
│ ├── RobotQueries.cs
│ ├── StatisticsQueries.cs
│ ├── WorkPieceCarrierQueries.cs
│ └── SystemQueries.cs
├── Mutations/ # GraphQL mutation resolvers
│ ├── ProductMutations.cs
│ ├── ManufacturingMutations.cs
│ ├── RobotMutations.cs
│ ├── StatisticsMutations.cs
│ ├── WorkPieceCarrierMutations.cs
│ └── SystemMutations.cs
├── Subscriptions/ # GraphQL subscription resolvers
│ └── StatisticsSubscriptions.cs
├── appsettings.json
└── appsettings.Development.json
Essert.MF.Application/
├── Ports/
│ └── ICurrentMessageEventService.cs # Event service interface (cross-API)
Essert.MF.Infrastructure/
├── Services/
│ └── CurrentMessageEventService.cs # Event service implementation (singleton)
Essert.MF.API.GraphQL.Tests/
├── Infrastructure/
│ ├── TestWebApplicationFactory.cs
│ └── IntegrationTestBase.cs
├── Queries/
│ ├── ProductQueriesTests.cs
│ ├── ManufacturingQueriesTests.cs
│ ├── RobotQueriesTests.cs
│ ├── StatisticsQueriesTests.cs
│ ├── WorkPieceCarrierQueriesTests.cs
│ └── SystemQueriesTests.cs
├── Mutations/
│ ├── ProductMutationsTests.cs
│ ├── ManufacturingMutationsTests.cs
│ ├── RobotMutationsTests.cs
│ ├── StatisticsMutationsTests.cs
│ ├── WorkPieceCarrierMutationsTests.cs
│ └── SystemMutationsTests.cs
├── Subscriptions/
│ └── StatisticsSubscriptionsTests.cs
├── Services/
│ └── CurrentMessageEventServiceTests.cs
└── HealthCheckTests.cs
Implementation Status¶
Queries (24 total)¶
| Domain | Query | Status | Description |
|---|---|---|---|
| Products | searchProducts |
Done | Search products and versions by name |
productById |
Done | Get product by UID | |
versionsForProduct |
Done | Get all versions for a product | |
| Manufacturing | activeProcesses |
Done | Get active manufacturing processes (paginated) |
processById |
Done | Get process by UID | |
processByOrderNumber |
Done | Get process by order number | |
processesByWpcId |
Done | Get processes by WPC ID | |
| Robots | availableRobots |
Done | Get all available robots |
robotById |
Done | Get robot by UID | |
robotsByPositionDataId |
Done | Get robots by position data ID | |
calculatedPosition |
Done | Get calculated robot position | |
| Statistics | processStatistics |
Done | Get process statistics by order UID and process ID |
processStatisticsByVersion |
Done | Get statistics by version, process, and date range | |
recentCycleTimes |
Done | Get recent cycle times | |
cycleTimeStatistics |
Done | Get cycle time statistics | |
| WorkPieceCarriers | availableWorkPieceCarriers |
Done | Get all available WPCs |
workPieceCarriersByType |
Done | Get WPCs by carrier type | |
| System | allVariables |
Done | Get all system variables |
allBatteryStatuses |
Done | Get all battery statuses | |
systemHealth |
Done | Get system health status | |
systemSummary |
Done | Get system summary | |
versionHistory |
Done | Get database version history | |
downtimeRecords |
Done | Get downtime records by date range | |
recentDowntimeRecords |
Done | Get recent downtime records |
Mutations (26 total)¶
| Domain | Mutation | Status | Description |
|---|---|---|---|
| Products | createProduct |
Done | Create product with CRC |
createProductWithParameters |
Done | Create product with version and parameter mappings | |
updateProduct |
Done | Update product information | |
deleteProduct |
Done | Delete product with all versions | |
createVersion |
Done | Create new version for product | |
updateVersion |
Done | Update version information | |
setFactorySetup |
Done | Set factory setup flag | |
deleteVersion |
Done | Delete a version | |
| Manufacturing | createManufacturingProcess |
Done | Create new manufacturing process |
completeManufacturingProcess |
Done | Complete a manufacturing process | |
deleteManufacturingProcess |
Done | Delete a manufacturing process | |
| Robots | executeRobotMasterTeach |
Done | Execute robot master teaching |
storeMasterData |
Done | Store master position data | |
storePositionData |
Done | Store position data with offsets | |
| Statistics | addCurrentMessage |
Done | Add a current message |
removeCurrentMessage |
Done | Remove a current message | |
archiveMessage |
Done | Archive a message | |
recordValveMeasurement |
Done | Record valve measurement | |
recordEgpMeasurement |
Done | Record EGP measurement | |
recordKannMeasurement |
Done | Record Kann measurement | |
recordLengthMeasurement |
Done | Record length measurement | |
| WorkPieceCarriers | deleteWorkPieceCarrier |
Done | Delete a WPC |
| System | setVariable |
Done | Set/update system variable |
addVersion |
Done | Add database version entry | |
recordDowntime |
Done | Record system downtime | |
updateBatteryStatus |
Done | Update battery status |
Test Coverage (62 tests total)¶
| Test File | Tests | Status |
|---|---|---|
HealthCheckTests.cs |
2 | Done |
ProductQueriesTests.cs |
3 | Done |
ManufacturingQueriesTests.cs |
4 | Done |
RobotQueriesTests.cs |
3 | Done |
StatisticsQueriesTests.cs |
4 | Done |
WorkPieceCarrierQueriesTests.cs |
2 | Done |
SystemQueriesTests.cs |
6 | Done |
ProductMutationsTests.cs |
6 | Done |
ManufacturingMutationsTests.cs |
3 | Done |
RobotMutationsTests.cs |
3 | Done |
StatisticsMutationsTests.cs |
7 | Done |
WorkPieceCarrierMutationsTests.cs |
1 | Done |
SystemMutationsTests.cs |
4 | Done |
StatisticsSubscriptionsTests.cs |
7 | Done |
CurrentMessageEventServiceTests.cs |
9 | Done |
Solution Integration¶
- Add
Essert.MF.API.GraphQLtoEssert.MF.sln - Add
Essert.MF.API.GraphQL.TeststoEssert.MF.sln
Subscriptions (4 total)¶
| Domain | Subscription | Status | Description |
|---|---|---|---|
| Statistics | onCurrentMessageChanged |
Done | Subscribe to all current message changes (added/removed) |
onCurrentMessageAdded |
Done | Subscribe to message added events only | |
onCurrentMessageRemoved |
Done | Subscribe to message removed events only | |
onAllCurrentMessages |
Done | Subscribe to periodic snapshots of all current messages |
Subscription Architecture¶
The subscription system follows the hexagonal architecture pattern, ensuring that all API adapters (REST, GraphQL, OPC UA) can trigger real-time notifications to GraphQL subscribers.
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Event Flow Architecture │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ REST API │ │ GraphQL API │ │ OPC UA API │ API Adapters │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────────┐ │
│ │ Application Layer (Command Handlers) │ │
│ │ │ │
│ │ AddCurrentMessageHandler ──► ICurrentMessageEventService.PublishAdded() │ │
│ │ RemoveCurrentMessageHandler ► ICurrentMessageEventService.PublishRemoved()│ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────────┐ │
│ │ Infrastructure Layer (Singleton Service) │ │
│ │ │ │
│ │ CurrentMessageEventService (using System.Reactive) │ │
│ │ ├── Subject<CurrentMessageChangeEvent> │ │
│ │ ├── OnCurrentMessageChanged() → IObservable<event> │ │
│ │ ├── OnCurrentMessageAdded() → IObservable<event> (filtered) │ │
│ │ └── OnCurrentMessageRemoved() → IObservable<event> (filtered) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────────┐ │
│ │ GraphQL Subscriptions (WebSocket) │ │
│ │ │ │
│ │ StatisticsSubscriptions │ │
│ │ ├── onCurrentMessageChanged │ │
│ │ ├── onCurrentMessageAdded │ │
│ │ ├── onCurrentMessageRemoved │ │
│ │ └── onAllCurrentMessages (periodic refresh + change trigger) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────────┐ │
│ │ GraphQL Clients (Browser, Mobile, etc.) │ │
│ └───────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Key Design Decisions:
-
Event Service in Infrastructure Layer: The
ICurrentMessageEventServiceinterface is defined inApplication.Ports, with the implementation inInfrastructure.Services. This ensures all APIs share the same event stream. -
Singleton Registration: The service is registered as a singleton to maintain a single event stream across all API requests.
-
Application-Layer Publishing: Events are published from command handlers (not API adapters), ensuring consistency regardless of which API triggers the operation.
-
Reactive Extensions: Uses
System.Reactivefor pub/sub pattern with type-safe event filtering.
Future Enhancements (Low Priority)¶
Additional Subscriptions (Real-time updates)¶
-
onProcessCompleted- Subscribe to process completion events -
onMeasurementRecorded- Subscribe to new measurements -
onWpcStateChanged- Subscribe to WPC state changes
Performance Optimizations¶
- Implement DataLoaders to prevent N+1 queries
- Add response caching for frequently accessed data
- Configure query complexity analysis
Security¶
- Add authentication middleware
- Implement authorization policies
- Configure rate limiting
- Disable introspection in production
Configuration¶
GraphQL Endpoint¶
- Development:
http://localhost:5000/graphql - Banana Cake Pop IDE: Available at
/graphqlin browser (Development mode)
Key Configuration in Program.cs¶
builder.Services
.AddGraphQLServer()
.BindRuntimeType<sbyte, HotChocolate.Types.ShortType>() // sbyte mapping
.AddType(new ObjectType<Robot>(d => d.Ignore(r => r.DomainEvents))) // Hide domain events
.AddQueryType()
.AddTypeExtension<ProductQueries>()
// ... other query extensions
.AddMutationType()
.AddTypeExtension<ProductMutations>()
// ... other mutation extensions
.AddSubscriptionType()
.AddTypeExtension<StatisticsSubscriptions>()
.AddInMemorySubscriptions()
.AddFiltering()
.AddSorting()
.AddProjections()
.ModifyRequestOptions(opt => opt.IncludeExceptionDetails = builder.Environment.IsDevelopment())
.DisableIntrospection(!builder.Environment.IsDevelopment() && !builder.Environment.IsEnvironment("Test"));
// WebSocket support for subscriptions
app.UseWebSockets();
app.MapGraphQL();
Example Queries¶
Search Products¶
Get Product with Versions¶
query {
productById(uid: 1) {
id { value }
name
isActive
}
versionsForProduct(productUid: 1) {
uid
versionName
favorite
released
}
}
Get Active Manufacturing Processes¶
Create Product with Parameters¶
mutation {
createProductWithParameters(input: {
productName: "NewProduct"
displayName: "New Product"
articleNumber: "ART-001"
versionName: "V1.0"
creator: "System"
parameterSetups: [
{ systemType: "TH", mapping: "TH_Main", setupUid: 1 }
]
}) {
productUid
versionUid
success
message
parameterMappings {
systemType
mappingUid
success
}
}
}
Example Subscriptions¶
Subscribe to Current Message Changes¶
subscription {
onCurrentMessageChanged {
changeType
messageId
timestamp
message {
messageId
messageDE
messageEN
classId
}
}
}
Subscribe to All Current Messages (with periodic refresh)¶
subscription {
onAllCurrentMessages {
timestamp
messages {
messageId
messageDE
messageEN
classNameDE
classNameEN
}
}
}
Running the API¶
# Build
cd Essert.MF.API.GraphQL
dotnet build
# Run
dotnet run
# Run tests
cd Essert.MF.API.GraphQL.Tests
dotnet test
Related Documentation¶
Last updated: 2025-12-03