Skip to content

Client (StrataClient)

The StrataClient class sends requests to services and receives responses. It also supports fire-and-forget posts, service commands, and service discovery.

For conceptual background, see Architecture.

typescript
import { StrataClient } from '@strata-js/strata';

Constructor

typescript
new StrataClient(config : StrataClientConfig)

Creates a new client instance.

typescript
const client = new StrataClient({
    client: { name: 'MyApp' },
    backend: {
        type: 'redis-streams',
        redis: { host: 'localhost', port: 6379 },
    },
});

The client name defaults to Client:<serviceGroup> if service.serviceGroup is set in config, or StrataClient.<hostname> otherwise.

Properties

PropertyTypeDescription
idstringAuto-generated unique ID (or override via config.client.id).
namestringClient name for identification on the wire.
versionstringApplication version (from package.json or APP_VERSION).
configStrataClientConfigThe config object passed to the constructor.
initializedbooleantrue after start() has been called.
outstandingRequestsMap<string, StrataRequest>Currently in-flight requests waiting for responses.

Methods

start()

typescript
client.start() : Promise<void>

Initializes the backend and starts listening for responses. You must call this before making any requests or sending commands.

Throws AlreadyInitializedError if called more than once.

typescript
const client = new StrataClient(config);
await client.start();

request()

typescript
client.request<ReturnPayloadType, MetadataType>(
    queueOrService : string,
    context : string,
    operation : string,
    payload : Record<string, unknown>,
    metadata ?: MetadataType,
    auth ?: string,
    timeout ?: number
) : Promise<ResponseEnvelope<ReturnPayloadType>>

Sends a request and waits for a response. This is the primary way to call operations on a service.

Parameters:

ParameterTypeRequiredDescription
queueOrServicestringyesService group name or queue name. The Requests: prefix is added automatically if missing.
contextstringyesTarget context name.
operationstringyesTarget operation name.
payloadRecord<string, unknown>yesRequest payload.
metadataRecord<string, unknown>noRequest metadata (tracking, stats, etc.).
authstringnoAuthentication token (typically a JWT).
timeoutnumbernoRequest timeout in milliseconds. 0 or omitted uses the service default.

Returns: Promise<ResponseEnvelope<ReturnPayloadType>> -- the full response envelope.

typescript
const response = await client.request('UserService', 'users', 'get', {
    userId: '12345',
});

console.log(response.status);  // 'succeeded'
console.log(response.payload); // { user: { ... } }

Throws UninitializedError if the client hasn't been started.

post()

typescript
client.post<MetadataType>(
    queueOrService : string,
    context : string,
    operation : string,
    payload : Record<string, unknown>,
    metadata ?: MetadataType,
    auth ?: string
) : Promise<void>

Sends a fire-and-forget message. The service processes it but sends no response. Useful for events, notifications, or any case where the sender doesn't need confirmation.

typescript
await client.post('NotificationService', 'email', 'send', {
    to: 'user@example.com',
    subject: 'Welcome!',
    body: 'Thanks for signing up.',
});

Throws UninitializedError if the client hasn't been started.

command()

typescript
client.command(
    command : ValidCommandName,
    target ?: string,
    payload ?: Record<string, unknown>
) : Promise<ServiceCommandResponse | undefined>

Sends a command to one or more running services. Commands control service behavior at runtime (shutdown, concurrency changes, etc.).

Parameters:

ParameterTypeDefaultDescription
commandValidCommandName--One of 'info', 'concurrency', 'shutdown', 'toobusy'.
targetstring'Services'Target scope for the command.
payloadobject--Command-specific payload.

Target format:

TargetScope
'Services'All running services (all groups).
'Services:<serviceGroup>'All instances in a specific service group.
'Services:<serviceGroup>:<id>'A specific service instance by ID.

Returns: A ServiceCommandResponse for commands that have replies (currently only info), or undefined.

typescript
// Get info from all services
const info = await client.command('info');

// Shut down a specific service group
await client.command('shutdown', 'Services:UserService', {
    graceful: true,
});

// Update concurrency for all services
await client.command('concurrency', 'Services', {
    concurrency: 64,
});

Built-in Commands

CommandPayloadHas ResponseDescription
info--yesReturns ServiceInfo for each instance.
shutdown{ graceful?, exitCode? }noInitiates service shutdown.
concurrency{ concurrency }noUpdates max concurrent requests.
toobusyTooBusyConfignoUpdates node-toobusy options.

discoverServices()

typescript
client.discoverServices() : Promise<DiscoveredServices>

Returns all discovered service groups, their instances, and what contexts/operations each supports. The return type is a nested record: service group name -> service instance ID -> DiscoveredService.

typescript
const services = await client.discoverServices();

for(const [ group, instances ] of Object.entries(services))
{
    console.log(`Service group: ${ group }`);
    for(const [ id, info ] of Object.entries(instances))
    {
        console.log(`  Instance ${ id }: v${ info.version }, ${ info.outstanding } outstanding`);
        console.log(`  Contexts:`, Object.keys(info.contexts));
    }
}

INFO

Service discovery requires the backend to support it and discovery to be enabled in the service config (enabled by default).

registerBackend()

typescript
client.registerBackend(name : string, backendClass : BackendConstructor) : void

Registers a custom backend constructor, just like service.registerBackend(). Use this when the client needs a backend that isn't built in.

getBackend()

typescript
client.getBackend<T extends BaseStrataBackend>(name : string) : T

Returns the backend instance registered under the given name.

Configuration Reference

StrataClientConfig

typescript
type StrataClientConfig = Omit<StrataConfig, 'service'> & {
    service ?: Partial<ServiceConfig>;
};

In practice, a client config looks like:

typescript
{
    client: {
        name: 'MyApp',      // Optional. Defaults based on serviceGroup or hostname.
        id: 'custom-id',    // Optional. Auto-generated if omitted.
    },
    backend: {
        type: 'redis-streams',
        redis: { host: 'localhost', port: 6379 },
    },
    aliases: {               // Optional. Map friendly names to queue names.
        'users': 'UserService',
    },
}

ClientConfig

typescript
interface ClientConfig
{
    name ?: string;
    id ?: string;
}