gRPC Realtime API
This guide is exclusively for the gRPC realtime interface.
Glossary
- Inbound adapter — accepts external protocol calls and translates them into use-case calls.
Responsibility in context
- Stack layer: adapter / realtime
- Owns: framework-specific wiring for this technology
- Used with: backend-template composition, persistence/SDK packages as needed, matching delivery guide
- Not responsible for: domain rules, OpenAPI authoring, or browser offline storage
Why it exists
Framework choice should stay at the edge. This adapter keeps Express/Fastify/DB/realtime details replaceable.
What it is
Grpc Api adapter for Jumentix realtime interfaces — mounts application use-cases without leaking framework types into the domain.
Scope
- Transport: gRPC
- Server implementation:
apps/backend-template/src/interface/gRPC/gRPCAPI.ts - Canonical proto contract:
spec/asyncapi/async-api.proto - SDK client:
sdk-clients/grpc/GrpcApiClient.ts - AsyncAPI source:
spec/asyncapi/1.0.0.grpc.yml
Contract References
- gRPC Realtime Contracts
- Error Contracts and Responses
- Events and Messages Map
Service Contract
- Service name:
realtime.AsyncApiGateway - RPC methods:
Request(AsyncApiRequest) returns (AsyncApiResponse)(unary)Exchange(stream AsyncApiRequest) returns (stream AsyncApiResponse)(bi-directional stream)
Runtime Flow
Deep Example: Unary Request
import { GrpcApiClient } from '../sdk-clients/grpc/GrpcApiClient';
const client = new GrpcApiClient('localhost:3002');
const response = await client.request({
version: '1.0.0',
operationId: 'createOrganization',
authorization: 'Bearer <jwt>',
input: {
name: 'Acme Group',
address: [],
phone: [],
email: []
},
metadata: {
requestId: 'req-grpc-001',
correlationId: 'corr-tenant-42'
}
});
if (!response.ok) {
console.error(response.error);
} else {
console.log(response.result);
}Deep Example: Native gRPC Bi-directional Stream
import grpc from '@grpc/grpc-js';
import protoLoader from '@grpc/proto-loader';
import { resolveGrpcProtoPath } from '@jumentix/sdk-grpc-client';
const protoPath = resolveGrpcProtoPath();
const packageDefinition = protoLoader.loadSync(protoPath, {
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const grpcObject = grpc.loadPackageDefinition(packageDefinition) as any;
const client = new grpcObject.realtime.AsyncApiGateway(
'localhost:3002',
grpc.credentials.createInsecure()
);
const stream = client.exchange();
stream.on('data', (msg: any) => {
const result = msg.resultJson ? JSON.parse(msg.resultJson) : null;
console.log('stream response', msg.operationId, result, msg.errorMessage);
});
stream.on('error', (err: Error) => {
console.error('stream error', err);
});
stream.write({
version: '1.0.0',
operationId: 'getAllOrganizations',
authorization: 'Bearer <jwt>',
inputJson: JSON.stringify({}),
paramsJson: JSON.stringify({}),
queryStringJson: JSON.stringify({ page: 1, size: 20 }),
metadataJson: JSON.stringify({ requestId: 'stream-1' })
});
stream.end();Payload Serialization Rules
- Transport fields
inputJson,paramsJson,queryStringJson,metadataJsonare JSON strings. - Server maps transport payload into the internal async request envelope.
resultJsonin response must be parsed by client consumers.errorNameanderrorMessageprovide normalized failure metadata.
Operational Guidance
- Keep one client per service host/port for connection reuse.
- Prefer unary RPC for independent operations.
- Use stream exchange for high-frequency operation batches.
- Enforce per-request correlation with
metadataJson.requestId.
Junior checklist (“I can …”)
- I know when to pick this adapter
- I can start it from the documented script
- I know the next guide/package to read
Next step
Return to Getting started or the matching delivery guide.