reinhardt-graphql
GraphQL integration (facade crate)
Overview
GraphQL API support with schema generation from models, query and mutation resolvers, and integration with the authentication and permission system. Provides a flexible alternative to REST APIs.
This is a facade crate that re-exports functionality from the following modules:
- core: Core GraphQL implementation
- macros: Procedural macros for GraphQL (when features enabled)
Crate Structure
reinhardt-graphql/ (facade crate - public API)
└── macros/ (procedural macros)
Users should depend on `reinhardt-graphql` (this facade crate) for all GraphQL functionality.
Features
Implemented ✓
Core Type System
- GraphQL Type Markers:
GraphQLTypeandGraphQLFieldtraits for type-safe GraphQL type definitions - Error Handling: Custom
GraphQLErrorenum with Schema, Resolver, and NotFound variants - Base Resolver Trait: Async
Resolvertrait with generic output types for flexible resolver implementation
Schema & Data Types
- User Type: Complete GraphQL object implementation with id, name, email, and active fields
- User Storage: Thread-safe in-memory storage using
Arc<RwLock<HashMap>>for user datanew(): Create new storage instanceadd_user(): Add or update user in storageget_user(): Retrieve user by IDlist_users(): List all stored users
- Input Types:
CreateUserInputfor user creation mutations - Schema Builder:
create_schema()function to build GraphQL schema with data context
Query Operations
- User Queries:
user(id: ID): Retrieve single user by IDusers(): List all usershello(name: Option<String>): Simple greeting query for testing
- Context Integration: Queries access UserStorage through GraphQL context
Mutation Operations
- User Mutations:
createUser(input: CreateUserInput): Create new user with auto-generated UUIDupdateUserStatus(id: ID, active: bool): Update user active status
- State Management: Mutations persist changes to UserStorage
Subscription System
- Event Types:
UserEventenum supporting Created, Updated, and Deleted events - Event Broadcasting:
EventBroadcasterwith tokio broadcast channel (capacity: 100)new(): Create new broadcaster instancebroadcast(): Send events to all subscriberssubscribe(): Subscribe to event stream
- Subscription Root:
SubscriptionRootwith filtered subscription streamsuserCreated(): Stream of user creation eventsuserUpdated(): Stream of user update eventsuserDeleted(): Stream of user deletion events (returns ID only)
- Async Streams: Real-time event filtering using async-stream
Integration
- async-graphql Integration: Built on async-graphql framework for production-ready GraphQL server
- Type Safety: Full Rust type system integration with compile-time guarantees
- Async/Await: Complete async support with tokio runtime
- Documentation: Comprehensive doc comments with examples for all public APIs
gRPC Transport (Optional - graphql-grpc feature)
- GraphQL over gRPC Service:
GraphQLGrpcServiceimplementing gRPC protocol for GraphQLexecute_query(): Execute GraphQL queries via unary RPCexecute_mutation(): Execute GraphQL mutations via unary RPCexecute_subscription(): Execute GraphQL subscriptions via server streaming RPC
- Operation-Class Enforcement: Each RPC validates the selected operation before
execution. Malformed documents, invalid or ambiguous operation selections, and
operation-class mismatches return gRPC
INVALID_ARGUMENTbefore any resolver runs. Subscription failures are reported as stream errors. Multiple operations require an exactoperation_name; a single operation may omit it or use an empty name. - Protocol Buffers: Complete proto definitions in
reinhardt-grpccrateGraphQLRequest: query, variables, operation_nameGraphQLResponse: data, errors, extensionsSubscriptionEvent: id, event_type, payload, timestamp
- Request/Response Conversion: Automatic conversion between gRPC and async-graphql types
- Error Handling: Full error information propagation (message, locations, path, extensions)
- Performance: Minimal overhead (5-21%, or 0.2-0.8 µs) compared to direct execution
- Network Communication: Full TCP/HTTP2 support via tonic
- Streaming: Efficient server-side streaming for real-time subscriptions
Dependency Injection (Optional - di feature)
#[graphql_handler]macro: Attribute macro for resolvers with automatic dependency injectionGraphQLContextExttrait: Extension trait for extracting DI context from GraphQL contextSchemaBuilderExttrait: Convenience methods for adding DI context to schema- Cache Control: Per-parameter cache control with
#[inject(cache = false)] - Type Safety: Full compile-time type checking for injected dependencies
- REST Consistency: Same DI patterns as REST handlers for unified developer experience
Installation
Add reinhardt to your Cargo.toml:
[]
= { = "0.3.19", = ["graphql"] }
# Or use a preset:
# reinhardt = { version = "0.3.19", features = ["standard"] } # Recommended
# reinhardt = { version = "0.3.19", features = ["full"] } # All features
Then import GraphQL features:
use ;
use ;
Note: GraphQL features are included in the standard and full feature presets.
Optional Features
# With dependency injection
= { = "0.3.19", = ["graphql", "di"] }
# With gRPC transport
= { = "0.3.19", = ["graphql", "grpc"] }
Examples
Basic GraphQL Usage
use ;
use ;
async
Dependency Injection
Enable the di feature to use dependency injection in GraphQL resolvers:
use ;
use ;
use InjectionContext;
use Arc;
// Define your resolvers
;
// Use #[graphql_handler] for DI
async
async
// Build schema with DI context
async
Cache Control
Control dependency caching per parameter:
async
GraphQL over gRPC Server
0.3.17 security release: Custom schema construction and subscription error delivery change in this release under a scoped patch compatibility exception. Read the 0.3.17 migration guide before upgrading.
Migration: Replace Schema::build(...) or Schema::new(...) with
GraphQLGrpcService::schema_builder(...).finish() (keep existing builder calls
before finish). GraphQLGrpcService::new rejects schemas without the guard at
construction time. The built-in create_schema helpers install it automatically
when graphql-grpc is enabled.
The guard runs after all prepare_request and parse_query extensions. Request
rewrites, persisted documents, and parsing limits therefore retain their normal
order, while the final selected operation must match the RPC. Schema validation
and resolver authorization still apply. The finished schema can also serve HTTP
requests without a gRPC operation restriction.
use EmptySubscription;
use GraphQLGrpcService;
use ;
use GraphQlServiceServer;
use Server;
async
GraphQL over gRPC Client
use ;
async
Running Examples
# Start gRPC server
# In another terminal, run client
Testing
# All tests
# Integration tests
# Subscription streaming tests
# E2E tests with real network
# Performance benchmarks
Performance
See PERFORMANCE.md for detailed benchmarks.
Summary:
- Direct GraphQL: ~3-4 µs per query
- gRPC GraphQL: ~4-5 µs per query
- Overhead: 5-21% (+0.2-0.8 µs) for gRPC serialization
- Both approaches are highly performant for real-world applications