DBOS Client
DBOSClient
provides a programmatic way to interact with your DBOS application from external code.
DBOSClient
includes methods similar to DBOS
that make sense to be used outside of a DBOS workflow or step, such as enqueueWorkflow
or getEvent
.
DBOSClient
is included in the @dbos-inc/dbos-sdk
package, the same package that used by DBOS applications.
Where DBOS applications use the static DBOS
class,
external applications use the DBOSClient
class instead.
class DBOSClient
interface EnqueueOptions {
workflowName: string;
workflowClassName: string;
queueName: string;
workflowID?: string;
appVersion?: string;
}
class DBOSClient {
static create(databaseUrl: string, systemDatabase?: string): Promise<DBOSClient>;
destroy(): Promise<void>;
async enqueue<T extends (...args: any[]) => Promise<any>>(
options: EnqueueOptions,
...args: Parameters<T>
): Promise<WorkflowHandle<Awaited<ReturnType<T>>>>;
retrieveWorkflow<T = unknown>(workflowID: string): WorkflowHandle<Awaited<T>>;
send<T>(destinationID: string, message: T, topic?: string, idempotencyKey?: string): Promise<void>;
getEvent<T>(workflowID: string, key: string, timeoutSeconds?: number): Promise<T | null>;
}
create
You construct a DBOSClient
with the static create
function.
The databaseUrl
parameter is a standard PostgreSQL connection URI
for the DBOS application database. Please see Configuring DBOS for more info.
DBOS Client needs to connect to the system database of your DBOS application.
The system database is stored on the same database server as the application database and typically has the same name as your application database, but suffixed with _dbos_sys
.
If you are using a non-standard system database name in your DBOS application, you must also provide the name to DBOSClient.create
.
Example:
import { DBOSClient } from "@dbos-inc/dbos-sdk";
const client = await DBOSClient.create(process.env.DBOS_DATABASE_URL);
destroy
Asynchronously destroys a DBOSClient
instance.
enqueue
Enqueues a workflow, similar to passing a queue name to startWorkflow
or using DBOS.withWorkflowQueue
.
Like startWorkflow
, the enqueue
method returns a WorkflowHandle
that you can use to retrieve the workflow results
asynchronously from an external application.
When enqueuing a workflow from within a DBOS application, the workflow and queue metadata can be retrieved automatically.
However, since DBOSClient
runs outside the DBOS application, the metadata must be specified explicitly.
Required metadata includes:
workflowName
: The name of the workflow method being enqueued.workflowClassName
: The name of the class the workflow method is a member of.queueName
: The name of the WorkflowQueue to enqueue the workflow on.
Additional but optional metadata includes:
workflowID
: The unique ID for the enqueued workflow. If left undefined, DBOS Client will generate a UUID. Please see Workflow IDs and Idempotency for more information.appVersion
: The version of your application that should process this workflow. If left undefined, it will be updated to the current version when the workflow is first dequeued. Please see Managing Application Versions for more information.
In addition to the EnqueueOptions
described above, you must also provide the workflow arguments to enqueue
.
These are passed to enqueue
after the initial EnqueueOptions
parameter.
Since DBOS Client works independently of your DBOS application code, enqueue
accepts whatever arguments you provide it without verifying if they match the workflow's expected argument types.
However, you can get type safety by providing a function declaration type parameter to enqueue
.
This enables TypeScript to verify that the provided arguments match the provided declaration and to infer the returned WorkflowHandle
result type.
Untyped Example:
// Because we did not provide a function type declaration to enqueue,
// there is no way to verify the workflow arguments are of the correct type.
const handle = await client.enqueue(
{
workflowName: 'indexDocument',
workflowClassName: 'DocumentDetective',
queueName: 'indexingQueue',
},
"https://arxiv.org/pdf/2208.13068");
// Explicitly specify the result type since we did not provide a
// function type declaration to enqueue.
const result: number = await handle.getResult();
Typed Example:
// TypeScript type declaration for our sample app workflow
declare class DocumentDetective {
static indexDocument(url: string): Promise<number>
}
// Because we provided the function type declaration to enqueue, TypeScript
// can validate the workflow parameters and infer the workflow return type.
const handle = await client.enqueue<typeof DocumentDetective.indexDocument>(
{
workflowName: 'indexDocument',
workflowClassName: 'DocumentDetective',
queueName: 'indexingQueue',
},
"https://arxiv.org/pdf/2208.13068");
// TypeScript can also infer the result type because
// we provided the function type declaration to enqueue
const result = await handle.getResult();
TypeScript automatically generates type declarations during compilation of your DBOS application. You can copy or import the function type declaration from your application's generated declaration file (aka.d.ts file).
retrieveWorkflow
Retrieves a workflow by ID, similar to DBOS.retrieveWorkflow
.
Returns a WorkflowHandle that can be used to retrieve information about the workflow,
including its current state and its eventual result.
Similar to enqueue, retrieveWorkflow
can be made type safe by use of a class declaration
and the ReturnType Utility Class.
Example:
const handle = client.retrieveWorkflow<ReturnType<IndexDocument>>(documentWFID);
const pageCount = await handle.getResult();
send
Sends a message to a specified workflow. Identical to DBOS.send
.
Since DBOS Client is running outside of a DBOS application,
it is highly recommended that you use the idempotencyKey
parameter in order to get exactly-once behavior.
getEvent
Retrieves an event published by workflowID for a given key using the events API. Identical to DBOS.getEvent