Comprehensive guides and references for the OpenFrame platform
The Api Service Core Graphql Fetchers And Dataloaders module is the GraphQL execution layer of the OpenFrame API service. It exposes query and mutation endpoints using Netflix DGS and coordinates:
This module sits between the GraphQL schema and the domain/service layer, acting as a thin orchestration layer that:
flowchart TD
Client["Frontend / GraphQL Client"] -->|"GraphQL Query"| DGS["Netflix DGS Engine"]
DGS --> Fetchers["GraphQL DataFetchers"]
Fetchers --> Services["Domain Services"]
Services --> Repositories["Mongo / Pinot Repositories"]
Fetchers --> DataLoaders["DGS DataLoaders"]
DataLoaders --> Services
The module uses cursor-based pagination via:
CursorPaginationInputCursorPaginationCriteriaGenericConnection / CountedGenericConnectionGenericEdgeThis ensures:
Each DataFetcher follows a consistent pattern:
GraphQL Input
↓
GraphQL Mapper
↓
FilterOptions (domain DTO)
↓
Service Query
↓
GenericQueryResult / CountedGenericQueryResult
↓
GraphQL Connection Mapper
This enforces strict separation between:
Nested fields (e.g., tags, organization, installed agents) use DGS DataLoaders.
flowchart LR
MachineList["List<Machine>"] --> TagsField["tags() field resolver"]
MachineList --> OrgField["organization() field resolver"]
TagsField --> TagLoader["TagDataLoader"]
OrgField --> OrgLoader["OrganizationDataLoader"]
TagLoader --> TagService["TagService"]
OrgLoader --> OrgRepo["OrganizationRepository"]
Instead of executing one query per machine, the DataLoader batches all keys into a single service/repository call per request.
Machine type:flowchart TD
Query["devices() GraphQL Query"] --> MapFilter["GraphQLDeviceMapper"]
MapFilter --> DeviceService["DeviceService.queryDevices"]
DeviceService --> Result["CountedGenericQueryResult<Machine>"]
Result --> MapConnection["toDeviceConnection()"]
MapConnection --> Response["CountedGenericConnection"]
Each nested resolver retrieves a named DataLoader from the DGS context:
tagDataLoadertoolConnectionDataLoaderinstalledAgentDataLoaderorganizationDataLoaderAll return CompletableFuture to support async execution.
flowchart TD
EventsQuery["events()"] --> MapFilter["GraphQLEventMapper"]
MapFilter --> EventService["EventService.queryEvents"]
EventService --> QueryResult["GenericQueryResult<Event>"]
QueryResult --> MapConn["toEventConnection()"]
MapConn --> Conn["GenericConnection"]
createEventupdateEventEvents are built using a builder pattern and timestamped with Instant.now() when created.
logDetails requires:
This indicates logs are stored in a time-partitioned and tool-partitioned structure.
Uses:
OrganizationQueryService for complex paginated queriesOrganizationService for direct lookupReturns a ToolList abstraction instead of a generic connection, indicating a simpler result model.
All DataLoaders implement DGS BatchLoader and are registered via @DgsDataLoader.
InstalledAgentService.getInstalledAgentsForMachinesList<List<InstalledAgent>>flowchart TD
InputIds["List<String> orgIds"] --> FilterNulls["Remove null + dedupe"]
FilterNulls --> RepoCall["OrganizationRepository.findByOrganizationIdIn"]
RepoCall --> MapBuild["Build Map<organizationId, Organization>"]
MapBuild --> OrderedResult["Return in original order"]
This ensures GraphQL contract compliance while preventing redundant database calls.
TagService.getTagsForMachinesToolConnectionService.getToolConnectionsForMachinessequenceDiagram
participant Client
participant DGS as "DGS Engine"
participant DeviceFetcher
participant DeviceService
participant OrgLoader as "OrganizationDataLoader"
Client->>DGS: devices query
DGS->>DeviceFetcher: devices()
DeviceFetcher->>DeviceService: queryDevices()
DeviceService-->>DeviceFetcher: Machines
DeviceFetcher-->>DGS: Connection<Machine>
DGS->>OrgLoader: load(orgIds batch)
OrgLoader-->>DGS: Organizations
DGS-->>Client: GraphQL response
DataFetchers contain no business logic. They:
All logic resides in domain services.
GraphQL inputs are converted into:
DeviceFilterOptionsEventFilterOptionsLogFilterOptionsOrganizationFilterOptionsToolFilterOptionsThis prevents GraphQL-specific concerns from leaking into the domain layer.
CompletableFutureAll designed to minimize:
The Api Service Core Graphql Fetchers And Dataloaders module provides the GraphQL orchestration layer for OpenFrame’s API service. It:
It is a performance-conscious, schema-driven adapter between the frontend GraphQL contract and the backend domain model.