353 lines
15 KiB
TypeScript
353 lines
15 KiB
TypeScript
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
import * as grpc from '@grpc/grpc-js';
|
|
import type * as proto from 'protobufjs';
|
|
import { TLSConfig } from '@temporalio/common/lib/internal-non-workflow';
|
|
import { Duration } from '@temporalio/common/lib/time';
|
|
import { CallContext, HealthService, Metadata, OperatorService, TestService, WorkflowService } from './types';
|
|
/**
|
|
* gRPC and Temporal Server connection options
|
|
*/
|
|
export interface ConnectionOptions {
|
|
/**
|
|
* The address of the Temporal server to connect to, in `hostname:port` format.
|
|
*
|
|
* Port defaults to 7233. Raw IPv6 addresses must be wrapped in square brackets (e.g. `[ipv6]:port`).
|
|
*
|
|
* @default localhost:7233
|
|
*/
|
|
address?: string;
|
|
/**
|
|
* TLS configuration. Pass a falsy value to use a non-encrypted connection,
|
|
* or `true` or `{}` to connect with TLS without any customization.
|
|
*
|
|
* For advanced scenario, a prebuilt {@link grpc.ChannelCredentials} object
|
|
* may instead be specified using the {@link credentials} property.
|
|
*
|
|
* Either {@link credentials} or this may be specified for configuring TLS
|
|
*
|
|
* @default TLS is disabled
|
|
*/
|
|
tls?: TLSConfig | boolean | null;
|
|
/**
|
|
* gRPC channel credentials.
|
|
*
|
|
* `ChannelCredentials` are things like SSL credentials that can be used to secure a connection.
|
|
* There may be only one `ChannelCredentials`. They can be created using some of the factory
|
|
* methods defined {@link https://grpc.github.io/grpc/node/grpc.credentials.html | here}
|
|
*
|
|
* Specifying a prebuilt `ChannelCredentials` should only be required for advanced use cases.
|
|
* For simple TLS use cases, using the {@link tls} property is recommended. To register
|
|
* `CallCredentials` (eg. metadata-based authentication), use the {@link callCredentials} property.
|
|
*
|
|
* Either {@link tls} or this may be specified for configuring TLS
|
|
*/
|
|
credentials?: grpc.ChannelCredentials;
|
|
/**
|
|
* gRPC call credentials.
|
|
*
|
|
* `CallCredentials` generaly modify metadata; they can be attached to a connection to affect all method
|
|
* calls made using that connection. They can be created using some of the factory methods defined
|
|
* {@link https://grpc.github.io/grpc/node/grpc.credentials.html | here}
|
|
*
|
|
* If `callCredentials` are specified, they will be composed with channel credentials
|
|
* (either the one created implicitely by using the {@link tls} option, or the one specified
|
|
* explicitly through {@link credentials}). Notice that gRPC doesn't allow registering
|
|
* `callCredentials` on insecure connections.
|
|
*/
|
|
callCredentials?: grpc.CallCredentials[];
|
|
/**
|
|
* GRPC Channel arguments
|
|
*
|
|
* @see option descriptions {@link https://grpc.github.io/grpc/core/group__grpc__arg__keys.html | here}
|
|
*
|
|
* By default the SDK sets the following keepalive arguments:
|
|
*
|
|
* ```
|
|
* grpc.keepalive_permit_without_calls: 1
|
|
* grpc.keepalive_time_ms: 30_000
|
|
* grpc.keepalive_timeout_ms: 15_000
|
|
* ```
|
|
*
|
|
* To opt-out of keepalive, override these keys with `undefined`.
|
|
*/
|
|
channelArgs?: grpc.ChannelOptions;
|
|
/**
|
|
* {@link https://grpc.github.io/grpc/node/module-src_client_interceptors.html | gRPC interceptors} which will be
|
|
* applied to every RPC call performed by this connection. By default, an interceptor will be included which
|
|
* automatically retries retryable errors. If you do not wish to perform automatic retries, set this to an empty list
|
|
* (or a list with your own interceptors). If you want to add your own interceptors while keeping the default retry
|
|
* behavior, add this to your list of interceptors: `makeGrpcRetryInterceptor(defaultGrpcRetryOptions())`. See:
|
|
*
|
|
* - {@link makeGrpcRetryInterceptor}
|
|
* - {@link defaultGrpcRetryOptions}
|
|
*/
|
|
interceptors?: grpc.Interceptor[];
|
|
/**
|
|
* Optional mapping of gRPC metadata (HTTP headers) to send with each request to the server.
|
|
* Setting the `Authorization` header is mutually exclusive with the {@link apiKey} option.
|
|
*
|
|
* In order to dynamically set metadata, use {@link Connection.withMetadata}
|
|
*/
|
|
metadata?: Metadata;
|
|
/**
|
|
* API key for Temporal. This becomes the "Authorization" HTTP header with "Bearer " prepended.
|
|
* This is mutually exclusive with the `Authorization` header in {@link ConnectionOptions.metadata}.
|
|
*
|
|
* You may provide a static string or a callback. Also see {@link Connection.withApiKey} or
|
|
* {@link Connection.setApiKey}
|
|
*/
|
|
apiKey?: string | (() => string);
|
|
/**
|
|
* Milliseconds to wait until establishing a connection with the server.
|
|
*
|
|
* Used either when connecting eagerly with {@link Connection.connect} or
|
|
* calling {@link Connection.ensureConnected}.
|
|
*
|
|
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
* @default 10 seconds
|
|
*/
|
|
connectTimeout?: Duration;
|
|
/**
|
|
* List of plugins to register with the connection.
|
|
*
|
|
* Plugins allow you to configure the connection options.
|
|
* Any plugins provided will also be passed to any client built from this connection.
|
|
*
|
|
* @experimental Plugins is an experimental feature; APIs may change without notice.
|
|
*/
|
|
plugins?: ConnectionPlugin[];
|
|
}
|
|
export type ConnectionOptionsWithDefaults = Required<Omit<ConnectionOptions, 'tls' | 'connectTimeout' | 'callCredentials' | 'apiKey'>> & {
|
|
connectTimeoutMs: number;
|
|
};
|
|
/**
|
|
* A symbol used to attach extra, SDK-internal connection options.
|
|
*
|
|
* @internal
|
|
* @hidden
|
|
*/
|
|
export declare const InternalConnectionOptionsSymbol: unique symbol;
|
|
export type InternalConnectionOptions = ConnectionOptions & {
|
|
[InternalConnectionOptionsSymbol]?: {
|
|
/**
|
|
* Indicate whether the `TestService` should be enabled on this connection. This is set to true
|
|
* on connections created internally by `TestWorkflowEnvironment.createTimeSkipping()`.
|
|
*/
|
|
supportsTestService?: boolean;
|
|
};
|
|
};
|
|
export declare const LOCAL_TARGET = "localhost:7233";
|
|
export interface RPCImplOptions {
|
|
serviceName: string;
|
|
client: grpc.Client;
|
|
callContextStorage: AsyncLocalStorage<CallContext>;
|
|
interceptors?: grpc.Interceptor[];
|
|
staticMetadata: Metadata;
|
|
apiKeyFnRef: {
|
|
fn?: () => string;
|
|
};
|
|
}
|
|
export interface ConnectionCtorOptions {
|
|
readonly options: ConnectionOptionsWithDefaults;
|
|
readonly client: grpc.Client;
|
|
/**
|
|
* Raw gRPC access to the Temporal service.
|
|
*
|
|
* **NOTE**: The namespace provided in {@link options} is **not** automatically set on requests made to the service.
|
|
*/
|
|
readonly workflowService: WorkflowService;
|
|
/**
|
|
* Raw gRPC access to the Temporal {@link https://github.com/temporalio/api/blob/ddf07ab9933e8230309850e3c579e1ff34b03f53/temporal/api/operatorservice/v1/service.proto | operator service}.
|
|
*/
|
|
readonly operatorService: OperatorService;
|
|
/**
|
|
* Raw gRPC access to the Temporal test service.
|
|
*
|
|
* Will be `undefined` if connected to a server that does not support the test service.
|
|
*/
|
|
readonly testService: TestService | undefined;
|
|
/**
|
|
* Raw gRPC access to the standard gRPC {@link https://github.com/grpc/grpc/blob/92f58c18a8da2728f571138c37760a721c8915a2/doc/health-checking.md | health service}.
|
|
*/
|
|
readonly healthService: HealthService;
|
|
readonly callContextStorage: AsyncLocalStorage<CallContext>;
|
|
readonly apiKeyFnRef: {
|
|
fn?: () => string;
|
|
};
|
|
}
|
|
/**
|
|
* Client connection to the Temporal Server
|
|
*
|
|
* ⚠️ Connections are expensive to construct and should be reused.
|
|
* Make sure to {@link close} any unused connections to avoid leaking resources.
|
|
*/
|
|
export declare class Connection {
|
|
/**
|
|
* @internal
|
|
*/
|
|
static readonly Client: grpc.ServiceClientConstructor;
|
|
readonly options: ConnectionOptionsWithDefaults;
|
|
protected readonly client: grpc.Client;
|
|
/**
|
|
* Used to ensure `ensureConnected` is called once.
|
|
*/
|
|
protected connectPromise?: Promise<void>;
|
|
/**
|
|
* Raw gRPC access to Temporal Server's {@link
|
|
* https://github.com/temporalio/api/blob/master/temporal/api/workflowservice/v1/service.proto | Workflow service}
|
|
*/
|
|
readonly workflowService: WorkflowService;
|
|
/**
|
|
* Raw gRPC access to Temporal Server's
|
|
* {@link https://github.com/temporalio/api/blob/master/temporal/api/operatorservice/v1/service.proto | Operator service}
|
|
*
|
|
* The Operator Service API defines how Temporal SDKs and other clients interact with the Temporal
|
|
* server to perform administrative functions like registering a search attribute or a namespace.
|
|
*
|
|
* This Service API is NOT compatible with Temporal Cloud. Attempt to use it against a Temporal
|
|
* Cloud namespace will result in gRPC `unauthorized` error.
|
|
*/
|
|
readonly operatorService: OperatorService;
|
|
/**
|
|
* Raw gRPC access to the Temporal test service.
|
|
*
|
|
* Will be `undefined` if connected to a server that does not support the test service.
|
|
*/
|
|
readonly testService: TestService | undefined;
|
|
/**
|
|
* Raw gRPC access to the standard gRPC {@link https://github.com/grpc/grpc/blob/92f58c18a8da2728f571138c37760a721c8915a2/doc/health-checking.md | health service}.
|
|
*/
|
|
readonly healthService: HealthService;
|
|
readonly plugins: ConnectionPlugin[];
|
|
readonly callContextStorage: AsyncLocalStorage<CallContext>;
|
|
private readonly apiKeyFnRef;
|
|
protected static createCtorOptions(options: ConnectionOptions): ConnectionCtorOptions;
|
|
/**
|
|
* Ensure connection can be established.
|
|
*
|
|
* Does not need to be called if you use {@link connect}.
|
|
*
|
|
* This method's result is memoized to ensure it runs only once.
|
|
*
|
|
* Calls {@link proto.temporal.api.workflowservice.v1.WorkflowService.getSystemInfo} internally.
|
|
*/
|
|
ensureConnected(): Promise<void>;
|
|
/**
|
|
* Create a lazy `Connection` instance.
|
|
*
|
|
* This method does not verify connectivity with the server. We recommend using {@link connect} instead.
|
|
*/
|
|
static lazy(options?: ConnectionOptions): Connection;
|
|
/**
|
|
* Establish a connection with the server and return a `Connection` instance.
|
|
*
|
|
* This is the preferred method of creating connections as it verifies connectivity by calling
|
|
* {@link ensureConnected}.
|
|
*/
|
|
static connect(options?: ConnectionOptions): Promise<Connection>;
|
|
protected constructor({ options, client, workflowService, operatorService, testService, healthService, callContextStorage, apiKeyFnRef, }: ConnectionCtorOptions);
|
|
protected static generateRPCImplementation({ serviceName, client, callContextStorage, interceptors, staticMetadata, apiKeyFnRef, }: RPCImplOptions): proto.RPCImpl;
|
|
/**
|
|
* Set a deadline for any service requests executed in `fn`'s scope.
|
|
*
|
|
* The deadline is a point in time after which any pending gRPC request will be considered as failed;
|
|
* this will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
|
|
* with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}; see {@link isGrpcDeadlineError}.
|
|
*
|
|
* It is strongly recommended to explicitly set deadlines. If no deadline is set, then it is
|
|
* possible for the client to end up waiting forever for a response.
|
|
*
|
|
* @param deadline a point in time after which the request will be considered as failed; either a
|
|
* Date object, or a number of milliseconds since the Unix epoch (UTC).
|
|
* @returns the value returned from `fn`
|
|
*
|
|
* @see https://grpc.io/docs/guides/deadlines/
|
|
*/
|
|
withDeadline<ReturnType>(deadline: number | Date, fn: () => Promise<ReturnType>): Promise<ReturnType>;
|
|
/**
|
|
* Set an {@link AbortSignal} that, when aborted, cancels any ongoing service requests executed in
|
|
* `fn`'s scope. This will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
|
|
* with code {@link grpc.status.CANCELLED|CANCELLED}; see {@link isGrpcCancelledError}.
|
|
*
|
|
* This method is only a convenience wrapper around {@link Connection.withAbortSignal}.
|
|
*
|
|
* @example
|
|
*
|
|
* ```ts
|
|
* const ctrl = new AbortController();
|
|
* setTimeout(() => ctrl.abort(), 10_000);
|
|
* // 👇 throws if incomplete by the timeout.
|
|
* await conn.withAbortSignal(ctrl.signal, () => client.workflow.execute(myWorkflow, options));
|
|
* ```
|
|
*
|
|
* @returns value returned from `fn`
|
|
*
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
|
|
*/
|
|
withAbortSignal<ReturnType>(abortSignal: AbortSignal, fn: () => Promise<ReturnType>): Promise<ReturnType>;
|
|
/**
|
|
* Set metadata for any service requests executed in `fn`'s scope.
|
|
*
|
|
* The provided metadata is merged on top of any existing metadata in current scope, including metadata provided in
|
|
* {@link ConnectionOptions.metadata}.
|
|
*
|
|
* @returns value returned from `fn`
|
|
*
|
|
* @example
|
|
*
|
|
* ```ts
|
|
* const workflowHandle = await conn.withMetadata({ apiKey: 'secret' }, () =>
|
|
* conn.withMetadata({ otherKey: 'set' }, () => client.start(options)))
|
|
* );
|
|
* ```
|
|
*/
|
|
withMetadata<ReturnType>(metadata: Metadata, fn: () => Promise<ReturnType>): Promise<ReturnType>;
|
|
/**
|
|
* Set the apiKey for any service requests executed in `fn`'s scope (thus changing the `Authorization` header).
|
|
*
|
|
* @returns value returned from `fn`
|
|
*
|
|
* @example
|
|
*
|
|
* ```ts
|
|
* const workflowHandle = await conn.withApiKey('secret', () =>
|
|
* conn.withMetadata({ otherKey: 'set' }, () => client.start(options)))
|
|
* );
|
|
* ```
|
|
*/
|
|
withApiKey<ReturnType>(apiKey: string, fn: () => Promise<ReturnType>): Promise<ReturnType>;
|
|
/**
|
|
* Set the {@link ConnectionOptions.apiKey} for all subsequent requests. A static string or a
|
|
* callback function may be provided.
|
|
*/
|
|
setApiKey(apiKey: string | (() => string)): void;
|
|
/**
|
|
* Wait for successful connection to the server.
|
|
*
|
|
* @see https://grpc.github.io/grpc/node/grpc.Client.html#waitForReady__anchor
|
|
*/
|
|
protected untilReady(deadline: number): Promise<void>;
|
|
/**
|
|
* Close the underlying gRPC client.
|
|
*
|
|
* Make sure to call this method to ensure proper resource cleanup.
|
|
*/
|
|
close(): Promise<void>;
|
|
private withNamespaceHeaderInjector;
|
|
}
|
|
/**
|
|
* Plugin to control the configuration of a connection.
|
|
*
|
|
* @experimental Plugins is an experimental feature; APIs may change without notice.
|
|
*/
|
|
export interface ConnectionPlugin {
|
|
/**
|
|
* Gets the name of this plugin.
|
|
*/
|
|
get name(): string;
|
|
/**
|
|
* Hook called when creating a connection to allow modification of configuration.
|
|
*/
|
|
configureConnection?(options: ConnectionOptions): ConnectionOptions;
|
|
}
|