UsePersistedOperations

Fluent extension on TraxGraphQLBuilder that wires the persisted-operation pipeline: storage, optional cache, optional cross-node invalidation, allowlist, introspection bypass, and shadow-mode logging.

Signature

public static TraxGraphQLBuilder UsePersistedOperations(
    this TraxGraphQLBuilder builder,
    Action<PersistedOperationsBuilder> configure
);

Usage

Minimal (DB hit per request, no cache, no broadcaster):

services.AddTraxGraphQL(graphql => graphql
    .UsePersistedOperations(opts => opts
        .UseDatabase(connectionString)
        .RequirePersisted(true)
    )
);

With cache + multi-node invalidation:

services.AddTraxGraphQL(graphql => graphql
    .UsePersistedOperations(opts => opts
        .UseDatabase(connectionString)
        .RequirePersisted(true)
        .WithInMemoryCache(c => c.WithTtl(TimeSpan.FromMinutes(15)))
        .UseRabbitMqInvalidation(rabbitConnectionString)
    )
);

See PersistedOperationsBuilder for every method.

What gets registered

ServiceLifetimePurpose
PersistedOperationsOptionsSingletonResolved configuration.
IDbContextFactory<PersistedOperationsDbContext>Singleton (factory)EF Core context factory. Postgres-backed.
IPersistedOperationCache -> NoOp or InMemorySingletonCache layer. No-op unless WithInMemoryCache() was called.
IPersistedOperationBroadcaster -> NoOp or RabbitMqSingletonMulti-node invalidation. No-op unless UseRabbitMqInvalidation() was called.
PersistedOperationReceiverServiceHosted (when broadcaster is RabbitMQ)Subscribes to the fanout exchange and clears local cache on broadcast.
IPersistedOperationStore -> DbPersistedOperationStorageSingletonProgrammatic CRUD.
IOperationDocumentStorage -> DbPersistedOperationStorageSingletonHotChocolate hot-path lookup.
IPersistedOperationValidator -> HotChocolateSchemaValidatorSingleton (Replace)Runs HotChocolate validation against the live schema before every upsert. Overrides the no-op default from AddPersistedOperationStore.
IPersistedOperationsCapabilitySingletonMarker probed by the dashboard to gate the management UI.
AllowlistMatcherSingletonUsed by the enforcement middleware.
TimeProviderSingleton (TryAdd)Default TimeProvider.System; override for tests.

Also extends the GraphQL schema with the management mutations and queries, and calls ExposeOperationQueries() / ExposeOperationMutations() on the builder so RootQuery and RootMutation are emitted even when the host has not registered any train-backed queries or mutations.

Validation

Configuration errors throw InvalidOperationException at startup. Each message names the misconfigured method and suggests a fix:

MisconfigBehavior
UseDatabase not calledThrows: "UseDatabase(connectionString) is required."
RequirePersisted(false) and LogNonPersistedRequests(false)Throws: configuration does nothing.
UseRabbitMqInvalidation without WithInMemoryCacheThrows: broadcasts have nothing to invalidate.
WithInMemoryCache called twiceThrows.
AllowOperations contains an empty entryThrows.