Skip to main content

DBOS Contexts

Background

DBOS automatically supplies a context to each registered function. A function can use its context to call other DBOS functions, interact with the runtime or the database, and access the logger. Each DBOS function has a specific context:


DBOSContext

Many contexts inherit from DBOSContext and share its properties and methods. (InitContext and MiddlewareContext are exceptions, as these are applied outside the context of DBOS functions.)

Properties

Methods

ctxt.request

readonly request: HTTPRequest

An object with information about the originating HTTP request that triggered this function (directly or indirectly).

interface HTTPRequest {
readonly headers?: IncomingHttpHeaders; // A node's http.IncomingHttpHeaders object.
readonly rawHeaders?: string[]; // Raw headers.
readonly params?: unknown; // Parsed path parameters from the URL.
readonly body?: unknown; // parsed HTTP body as an object.
readonly rawBody?: string; // Unparsed raw HTTP body string.
readonly query?: ParsedUrlQuery; // Parsed query string.
readonly querystring?: string; // Unparsed raw query string.
readonly url?: string; // Request URL.
readonly ip?: string; // Request remote address.
}

ctxt.workflowUUID

readonly workflowUUID: string

The current workflow's identity UUID, a string uniquely identifying a workflow execution. In a transaction or communicator, this field is set to the identity UUID of the calling workflow. In a handler, this field is empty.

ctxt.authenticatedUser

readonly authenticatedUser: string

The identity of the authenticated user who ran this function. Authenticated users are set by authentication middleware and inherited through the calling chain.

ctxt.authenticatedRoles

readonly authenticatedRoles: string[];

A list of roles the authenticated user has, if any. Authenticated roles are set by authentication middleware and inherited through the calling chain.

ctxt.assumedRole

readonly assumedRole: string;

The role used to run this function. Empty string if authorization is not required. DBOS's authorization sets the assumed role right before executing a function and this property is not inherited through the calling chain.

ctxt.logger

readonly logger: DBOSLogger

A reference to DBOS's logger. Please see our logging tutorial for more information.

ctxt.span

readonly span: Span

An OpenTelemetry Span associated with this context. You can assign custom trace attributes to this span. Please see the Span API for more information.

ctxt.getConfig

getConfig<T>(key: string): T | undefined;
getConfig<T>(key: string, defaultValue: T): T;

Retrieves an application property specified in the application section of the configuration. Optionally accepts a default value, returned when the key cannot be found in the configuration.


HandlerContext

Handlers use HandlerContext to invoke other functions, interact with active workflows, and interact directly with HTTP requests and responses.

Properties

Methods

handlerCtxt.koaContext

koaContext: Koa.Context;

The Koa Context of the current request, giving handlers access to the raw HTTP request and response.

handlerCtxt.invoke

invoke<T>(target: T, workflowUUID?: string): InvokeFuncs<T>

Invoke a transaction or communicator on the target class or configured instance. To invoke workflows, use invokeWorkflow or startWorkflow instead. The syntax for invoking function fn in class Cls with argument arg is:

const output = await handlerCtxt.invoke(Cls).fn(arg);

You don't supply a context to the invoked function—the DBOS Transact runtime does this for you. You can optionally provide an idempotency key to the invoked function. For more information, see our idempotency tutorial.

handlerCtxt.invokeWorkflow

invokeWorkflow<T>(target: T, workflowUUID?: string): InvokeFuncs<T>

Invoke a workflow and wait for it to complete, returning its result. To start a workflow without waiting for it to complete, use startWorkflow. The syntax for invoking workflow wf in class Cls with argument arg is:

const output = await handlerCtxt.invokeWorkflow(Cls).wf(arg);

You don't supply a context to the invoked workflow—the DBOS Transact runtime does this for you.

handlerCtxt.startWorkflow

startWorkflow<T>(target: T, workflowUUID?: string): InvokeFuncs<T>

Start a workflow and return a handle to it. This does not wait for the workflow to complete, though the resulting handle can be used to wait for the workflow result. To start a workflow and wait for the result, see invokeWorkflow. The startWorkflow method resolves after the handle is durably created; at this point the workflow is guaranteed to run to completion even if the handler is interrupted.

The syntax for starting workflow wf in class Cls with argument arg is:

const workflowHandle = await handlerCtxt.startWorkflow(Cls).wf(arg);

You don't supply a context to the newly started workflow—the DBOS Transact runtime does this for you.

handlerCtxt.retrieveWorkflow

retrieveWorkflow<R>(workflowUUID: string): WorkflowHandle<R>

Returns a workflow handle to the workflow with identity workflowUUID. R is the return type of the target workflow.

handlerCtxt.send

send<T extends NonNullable<any>>(destinationUUID: string, message: T, topic?: string, idempotencyKey?: string): Promise<void>

Sends a message to workflow destinationUUID. Messages can optionally be associated with a topic. You can provide an optional idempotency key to guarantee only a single message is sent even if send is called more than once. For more information, see our messages API tutorial.

handlerCtxt.getEvent

getEvent<T extends NonNullable<any>>(workflowUUID: string, key: string, timeoutSeconds?: number): Promise<T | null>

Retrieves an event published by workflowUUID for a given key using the events API. Awaiting on the promise returned by getEvent() waits for the workflow to publish the key, returning null if the wait times out.


handlerCtxt.getWorkflows

getWorkflows(input: GetWorkflowsInput): Promise<GetWorkflowsOutput>

This function allows querying workflow execution history. Its input is an object describing which workflows to retrieve (by default, retrieve all workflows):

export interface GetWorkflowsInput {
workflowName?: string; // The name of the workflow function
authenticatedUser?: string; // The user who ran the workflow.
startTime?: string; // Timestamp in RFC 3339 format
endTime?: string; // Timestamp in RFC 3339 format
status?: "PENDING" | "SUCCESS" | "ERROR" | "RETRIES_EXCEEDED" | "CANCELLED" ; // The status of the workflow.
applicationVersion?: string; // The application version that ran this workflow.
limit?: number; // Return up to this many workflows IDs. IDs are ordered by workflow creation time.
}

It returns as output an object containing a list of the UUIDs of all retrieved workflows, ordered by workflow creation time:

export interface GetWorkflowsOutput {
workflowUUIDs: string[];
}

To obtain further information about a particular workflow, call retrieveWorkflow on its UUID to obtain its handle.


WorkflowContext

Workflows use WorkflowContext to invoke other functions and interact with other workflows.

Methods

workflowCtxt.invoke

invoke<T>(target: T, workflowUUID?: string): InvokeFuncs<T>

Invoke transactions and communicators. To invoke other workflows, use invokeWorkflow or startWorkflow.

The syntax for invoking function fn in class Cls with argument arg is:

const output = await workflowCtxt.invoke(Cls).fn(arg);

You don't supply a context to the invoked function—the DBOS Transact runtime does this for you.

workflowCtxt.invokeWorkflow

invokeWorkflow<T>(target: T)

Invoke a child workflow and wait for it to complete, returning its result. To start a workflow without waiting it to complete, use startWorkflow. The syntax for invoking workflow wf in class Cls with argument arg is:

const output = await ctxt.invokeWorkflow(Cls).wf(arg);

You don't supply a context to the invoked child workflow—the DBOS Transact runtime does this for you.

workflowCtxt.startWorkflow

startWorkflow<T>(target: T).workflowFunction(args)

Start a child workflow and return a handle to it but do not wait for the workflow to complete. This method resolves after the handle is durably created; at this point the workflow is guaranteed to run to completion. The syntax for starting workflow wf in class Cls with argument arg is:

const workflowHandle = await ctxt.startWorkflow(Cls).wf(arg);

You don't supply a context to the newly started child workflow—the DBOS Transact runtime does this for you.

workflowCtxt.invokeChildWorkflow

Deprecated in favor of workflowCtxt.invokeWorkflow, which is equivalent but syntactically simpler.

workflowCtxt.startChildWorkflow

Deprecated in favor of workflowCtxt.startWorkflow, which is equivalent but syntactically simpler.

workflowCtxt.send

send<T extends NonNullable<any>>(destinationUUID: string, message: T, topic?: string): Promise<void>

Sends a message to destinationUUID. Messages can optionally be associated with a topic. For more information, see our messages API tutorial.

workflowCtxt.recv

recv<T extends NonNullable<any>>(topic?: string, timeoutSeconds?: number): Promise<T | null>

Receive messages sent to the workflow, optionally for a particular topic. Messages are dequeued first-in, first-out, from a queue associated with the topic. Calls to recv() wait for the next message in the queue, returning null if the wait times out. If no topic is specified, recv can only access messages sent without a topic. For more information, see our messages API tutorial.

workflowCtxt.setEvent

setEvent<T extends NonNullable<any>>(key: string, value: T): Promise<void>

Creates an immutable event named key with value value. Workflows and HTTP handlers can read events by calling getEvent with the workflow's UUID. Events are immutable and attempting to emit an event twice from a given workflow instance will result in an error. For more information, see our events API tutorial.

workflowCtxt.getEvent

getEvent<T extends NonNullable<any>>(workflowUUID: string, key: string, timeoutSeconds?: number): Promise<T | null>

Retrieves an event published by workflowUUID for a given key using the events API. Awaiting on the promise returned by getEvent() waits for the workflow to publish the key, returning null if the wait times out.

workflowCtxt.retrieveWorkflow

retrieveWorkflow<R>(workflowUUID: string): WorkflowHandle<R>

Returns a workflow handle to the workflow with identity workflowUUID. R is the return type of the target workflow.

WorkflowContext.sleep

sleep(durationSec: number): Promise<void>

Sleep for durationSec seconds. The wakeup time is set in the database when the function is first called, so if the workflow is re-executed, it will not oversleep.

Alternatively, sleepms is more precise.

WorkflowContext.sleepms

sleepms(durationMS: number): Promise<void>

Sleep for durationMS milliseconds. The wakeup time is set in the database when the function is first called, so if the workflow is re-executed, it will not oversleep.


TransactionContext<T>

Transactions use TransactionContext to interact with the database.

Generic Type Parameter

TransactionContext is typed generically based on the application database client in use. The application database client is configurable in a project's configuration file (app_db_client). DBOS currently supports the following clients:

Knex

import { Knex } from "knex";
static async exampleTransaction(ctxt: TransactionContext<Knex>, ...)

TypeORM

import { EntityManager } from "typeorm";
static async exampleTransaction(ctxt: TransactionContext<EntityManager>, ...)

Prisma

import { PrismaClient } from "@prisma/client";
static async exampleTransaction(ctxt: TransactionContext<PrismaClient>, ...)

Properties

transactionCtxt.client

client: T; // One of [Knex, EntityManager]

Provides access to the chosen application database client. A transaction function should only interact with the application database using this client.


StoredProcedureContext

Stored procedures use StoredProcedureContext to interact with the database.

warning

While StoredProcedureContext supports most of the DBOSContext methods, it does not support either the span property or the getConfig<T> method.

Methods

storedProcCtxt.query

type QueryResult<TRow> = {
rowCount: number;
rows?: TRow[];
}

query<TRow>(sql: string, ...params: unknown[]): Promise<QueryResult<TRow>>;

Execute a query against the database. Returns an object with query result rows (if any) and the number of rows affected by the query.


CommunicatorContext

Communicators use CommunicatorContext to retrieve information on communicator configuration.

Properties

communicatorCtxt.retriesAllowed

readonly retriesAllowed: boolean;

Whether the communicator is automatically retried on failure. Configurable through the @Communicator decorator.

communicatorCtxt.maxAttempts

readonly maxAttempts: number;

Maximum number of retries for the communicator. Configurable through the @Communicator decorator.


InitContext

Class initialization functions and instance initialize() methods are provided with an InitContext, which provides access to configuration information, database access, and a logging facility.

Properties and Methods

InitContext.logger

readonly logger: Logger;

logger is available to record any interesting successes, failures, or diagnostic information that occur during initialization.

InitContext.queryUserDB

queryUserDB<R>(sql: string, ...params: unknown[]): Promise<R[]>;

Accesses the user database directly with SQL. This approach is to be used with caution, as using a string to represent SQL is not fully database independent and careless formation of the string can lead to SQL injection vulnerabilities.

InitContext.getConfig

getConfig<T>(key: string, defaultValue?: T): T | undefined;

getConfig retrieves configuration information (from .yaml config file / environment). If key is not present in the configuration, defaultValue is returned.


MiddlewareContext

MiddlewareContext is provided to functions that execute against a request before entry into handler, transaction, and workflow functions. These middleware functions are generally executed before, or in the process of, user authentication, request validation, etc. The context is intended to provide read-only database access, logging services, and configuration information.

Properties and Methods

MiddlewareContext.logger

readonly logger: DBOSLogger;

logger is available to record any interesting successes, failures, or diagnostic information that occur during middleware processing.

MiddlewareContext.span

readonly span: Span;

span is the tracing span in which the middleware is being executed.

MiddlewareContext.koaContext

readonly koaContext: Koa.Context;

koaContext is the Koa context, which contains the inbound HTTP request associated with the middleware invocation.

MiddlewareContext.name

readonly name: string;

name contains the name of the function (handler, transaction, workflow) to be invoked after successful middleware processing.

MiddlewareContext.requiredRole

readonly requiredRole: string[];

requiredRole contains the list of roles required for the invoked operation. Access to the function will granted if the user has any role on the list. If the list is empty, it means there are no authorization requirements and may indicate that authentication is not required.

MiddlewareContext.getConfig

getConfig<T>(key: string, deflt: T | undefined) : T | undefined

getConfig retrieves configuration information (from .yaml config file / environment). If key is not present in the configuration, defaultValue is returned.

MiddlewareContext.query

  query<C extends UserDatabaseClient, R, T extends unknown[]>(qry: (dbclient: C, ...args: T) => Promise<R>, ...args: T): Promise<R>;

The query function provides read access to the database. To provide a scoped database connection and to ensure cleanup, the query API works via a callback function. The application is to pass in a qry function that will be executed in a context with access to the database client dbclient. The provided dbClient will be a Knex or TypeORM EntityManager or PrismaClient depending on the application's choice of SQL access library. This callback function may take arguments, and return a value.

Example, for Knex:

  const u = await ctx.query(
// The qry function that takes in a dbClient and a list of arguments (uname in this case)
(dbClient: Knex, uname: string) => {
return dbClient<UserTable>(userTableName).select("username").where({ username: uname })
},
userName // Input value for the uname argument
);