Application (StrataService)
The StrataService class is the top-level object for a Strata service. It holds configuration, manages the backend connection, coordinates contexts, runs global middleware, and listens for incoming requests.
For conceptual background, see Architecture.
import { StrataService } from '@strata-js/strata';Constructor
new StrataService(config : StrataServiceConfig)Creates a new service instance. The config is the only argument.
const service = new StrataService({
service: {
serviceGroup: 'UserService',
concurrency: 32,
},
backend: {
type: 'redis-streams',
redis: { host: 'localhost', port: 6379 },
},
});See StrataServiceConfig for the full configuration shape.
Properties
| Property | Type | Description |
|---|---|---|
id | string | Auto-generated unique ID for this service instance. |
name | string | Application name (from package.json or APP_NAME env). |
displayName | string | Human-friendly version of name (via lodash startCase). |
serviceGroup | string | The service group this instance belongs to. |
version | string | Application version (from package.json or APP_VERSION). |
concurrency | number | Max concurrent requests this instance will process. |
initialized | boolean | true after start() has been called. |
config | StrataServiceConfig | The config object passed to the constructor. |
info | ServiceInfo | Snapshot of the service's current state. See below. |
contexts | Record<string, string[]> | Map of registered context names to their operation names. |
backends | string[] | List of registered backend names. |
middleware | Set<OperationMiddleware> | Set of globally registered middleware. |
outstandingRequests | Map<string, StrataRequest> | Currently in-flight requests. |
lastBusy | { time: Date, lag: number } | Last time node-toobusy detected event loop lag. |
Methods
start()
service.start() : Promise<void>Initializes the backend, enables service discovery (unless disabled in config), and starts listening for incoming requests and commands. Call this after registering all contexts and middleware.
Throws AlreadyInitializedError if called more than once.
// Register everything first
service.registerContext(usersContext);
service.useMiddleware(authMiddleware);
// Then start
await service.start();registerContext()
Registers a context with the service. Has two overloads:
// Use the context's own name (set in constructor)
service.registerContext(context : StrataContext) : void
// Override the name
service.registerContext(name : string, context : StrataContext) : voidIf the context doesn't have a name and none is provided, it throws. If the name is already registered, it throws AlreadyRegisteredError.
import { StrataContext } from '@strata-js/strata';
const users = new StrataContext('users');
users.registerOperation('get', async (request) =>
{
return { user: await db.findUser(request.payload.userId) };
});
// These are equivalent:
service.registerContext(users);
service.registerContext('users', users);getContext()
service.getContext(contextName : string) : StrataContextRetrieves a registered context by name. Throws UnknownContextError if not found.
useMiddleware()
service.useMiddleware(middleware : OperationMiddleware | OperationMiddleware[]) : voidRegisters global middleware that runs on every request across all contexts. Accepts a single middleware or an array.
For details on how middleware ordering works, see Middleware Model.
service.useMiddleware(new AuthMiddleware());
service.useMiddleware([ new LoggingMiddleware(), new TimingMiddleware() ]);registerBackend()
service.registerBackend(name : string, backendClass : BackendConstructor) : voidRegisters a custom backend constructor under the given name. Once registered, the name can be used as the type in the backend config. Throws if the name is already registered. See Using a Custom Backend for a full walkthrough.
import { MyCustomBackend } from './backends/custom.js';
service.registerBackend('custom', MyCustomBackend);getBackend()
service.getBackend<T extends BaseStrataBackend>(name : string) : TReturns the backend instance registered under the given name.
setConcurrency()
service.setConcurrency(concurrency : number) : voidUpdates the max concurrent requests at runtime.
setTooBusy()
service.setTooBusy(options : TooBusyConfig) : voidUpdates node-toobusy options at runtime. See TooBusyConfig.
registerTeardown()
service.registerTeardown(fn : () => Promise<void>) : voidRegisters a cleanup function that will be called during service shutdown. Use this for closing database connections, flushing buffers, or any other teardown logic.
service.registerTeardown(async () =>
{
await database.disconnect();
});Built-in service Context
Every StrataService automatically registers a service context with a single info operation. This is useful for health checks, debugging, and service discovery.
info Operation
Send a request to service/info with an empty payload. The response is a ServiceInfo object:
// From a client
const response = await client.request('UserService', 'service', 'info', {});Example response payload:
{
"id": "l7aNdfrRDZW8nt0FBaSS",
"serviceName": "User Service",
"serviceGroup": "UserService",
"version": "1.2.0",
"strataVersion": "2.0.0",
"environment": "production",
"concurrency": 32,
"outstanding": 3,
"hostname": "worker-01",
"lastBusy": {
"time": "2024-06-25T16:16:40.794Z",
"lag": 0
},
"contexts": {
"service": [ "info" ],
"users": [ "get", "create", "delete" ]
},
"backend": {
"type": "redis-streams"
}
}INFO
The info operation responds from whichever service instance picks up the request. If you need info from a specific instance, use the info command via client.command() instead.
Configuration Reference
StrataServiceConfig
interface StrataServiceConfig
{
service : ServiceConfig;
backend : BackendConfig;
logging ?: LoggerConfig;
client ?: ClientConfig;
aliases ?: Record<string, string>;
interruptsToForceShutdown ?: number;
shutdownTimeout ?: number;
}ServiceConfig
interface ServiceConfig
{
serviceGroup : string;
concurrency ?: number; // Default: 32
defaultRequestTimeout ?: number;
toobusy ?: TooBusyConfig;
}TooBusyConfig
Options for node-toobusy dynamic concurrency control:
interface TooBusyConfig
{
maxLag ?: number;
interval ?: number;
smoothingFactorOnRise ?: number;
smoothingFactorOnFall ?: number;
}BackendConfig
interface BackendConfig
{
type : string;
discovery ?: DiscoveryConfig;
validateEnvelopes ?: boolean;
[key : string] : unknown;
}ServiceInfo
The shape returned by the info operation and info command:
interface ServiceInfo
{
id : string;
serviceName : string;
serviceGroup : string;
version : string;
strataVersion : string;
environment : string;
concurrency : number;
outstanding : number;
hostname : string;
lastBusy : { time : Date, lag : number };
contexts : Record<string, string[]>;
backend : BackendInfo;
}