@hotmeshio/hotmesh
Version:
Serverless Workflow
341 lines (340 loc) • 11.7 kB
TypeScript
import { EngineService } from '../engine';
import { ILogger } from '../logger';
import { QuorumService } from '../quorum';
import { WorkerService } from '../worker';
import { JobState, JobData, JobOutput, JobStatus, JobInterruptOptions, ExtensionType } from '../../types/job';
import { HotMeshConfig, HotMeshManifest } from '../../types/hotmesh';
import { JobExport } from '../../types/exporter';
import { JobMessageCallback, QuorumMessage, QuorumMessageCallback, QuorumProfile, ThrottleOptions } from '../../types/quorum';
import { StringAnyType, StringStringType } from '../../types/serializer';
import { JobStatsInput, GetStatsOptions, IdsResponse, StatsResponse } from '../../types/stats';
import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../types/stream';
/**
* This example shows the full lifecycle of a HotMesh engine instance,
* including: initialization, deployment, activation and execution.
*
* Engine routers are self-managing, but subscribe to the 'quorum' channel
* to establish consensus as necessary for distributed processing.
* Completed workflows are always soft-deleted with a configurable
* retention period.
*
* @example
* ```typescript
* import { Client as Postgres } from 'pg';
* import { HotMesh } from '@hotmeshio/hotmesh';
*
* const hotMesh = await HotMesh.init({
* appId: 'abc',
* engine: {
* connection: {
* class: Postgres,
* options: {
* connectionString: 'postgresql://usr:pwd@localhost:5432/db',
* }
* }
* }
* });
*
* await hotMesh.deploy(`
* app:
* id: abc
* version: '1'
* graphs:
* - subscribes: abc.test
* activities:
* t1:
* type: trigger
* `);
*
* await hotMesh.activate('1');
*
* await hotMesh.pubsub('abc.test');
*
* await HotMesh.stop();
* ```
*/
declare class HotMesh {
namespace: string;
appId: string;
guid: string;
/**
* @private
*/
engine: EngineService | null;
/**
* @private
*/
quorum: QuorumService | null;
/**
* @private
*/
workers: WorkerService[];
logger: ILogger;
static disconnecting: boolean;
/**
* @private
*/
verifyAndSetNamespace(namespace?: string): void;
/**
* @private
*/
verifyAndSetAppId(appId: string): void;
/**
* Instance initializer. Workers are configured
* similarly to the engine, but as an array with
* multiple worker objects.
*
* @example
* ```typescript
* const config: HotMeshConfig = {
* appId: 'myapp',
* engine: {
* connection: {
* class: Postgres,
* options: {
* connectionString: 'postgresql://usr:pwd@localhost:5432/db',
* }
* }
* },
* workers [...]
* };
* const hotMesh = await HotMesh.init(config);
* ```
*/
static init(config: HotMeshConfig): Promise<HotMesh>;
/**
* returns a guid using the same core guid
* generator used by the HotMesh (nanoid)
*/
static guid(): string;
/**
* @private
*/
initEngine(config: HotMeshConfig, logger: ILogger): Promise<void>;
/**
* @private
*/
initQuorum(config: HotMeshConfig, engine: EngineService, logger: ILogger): Promise<void>;
/**
* @private
*/
constructor();
/**
* @private
*/
doWork(config: HotMeshConfig, logger: ILogger): Promise<void>;
/**
* Starts a workflow
* @example
* ```typescript
* await hotMesh.pub('a.b.c', { key: 'value' });
* ```
*/
pub(topic: string, data?: JobData, context?: JobState, extended?: ExtensionType): Promise<string>;
/**
* Subscribe (listen) to all output and interim emissions of a single
* workflow topic. NOTE: Postgres does not support patterned
* unsubscription, so this method is not supported for Postgres.
*
* @example
* ```typescript
* await hotMesh.psub('a.b.c', (topic, message) => {
* console.log(message);
* });
* ```
*/
sub(topic: string, callback: JobMessageCallback): Promise<void>;
/**
* Stop listening in on a single workflow topic
*/
unsub(topic: string): Promise<void>;
/**
* Listen to all output and interim emissions of a workflow topic
* matching a wildcard pattern.
* @example
* ```typescript
* await hotMesh.psub('a.b.c*', (topic, message) => {
* console.log(message);
* });
* ```
*/
psub(wild: string, callback: JobMessageCallback): Promise<void>;
/**
* Patterned unsubscribe. NOTE: Postgres does not support patterned
* unsubscription, so this method is not supported for Postgres.
*/
punsub(wild: string): Promise<void>;
/**
* Starts a workflow and awaits the response
* @example
* ```typescript
* await hotMesh.pubsub('a.b.c', { key: 'value' });
* ```
*/
pubsub(topic: string, data?: JobData, context?: JobState | null, timeout?: number): Promise<JobOutput>;
/**
* Add a transition message to the workstream, resuming leg 2 of a paused
* reentrant activity (e.g., await, worker, hook)
*/
add(streamData: StreamData | StreamDataResponse): Promise<string>;
/**
* Request a roll call from the quorum (engine and workers)
*/
rollCall(delay?: number): Promise<QuorumProfile[]>;
/**
* Sends a throttle message to the quorum (engine and/or workers)
* to limit the rate of processing. Pass `-1` to throttle indefinitely.
* The value must be a non-negative integer and not exceed `MAX_DELAY` ms.
*
* When throttling is set, the quorum will pause for the specified time
* before processing the next message. Target specific engines and
* workers by passing a `guid` and/or `topic`. Pass no arguments to
* throttle the entire quorum.
*
* In this example, all processing has been paused indefinitely for
* the entire quorum. This is equivalent to an emergency stop.
*
* HotMesh is a stateless sequence engine, so the throttle can be adjusted up
* and down with no loss of data.
*
*
* @example
* ```typescript
* await hotMesh.throttle({ throttle: -1 });
* ```
*/
throttle(options: ThrottleOptions): Promise<boolean>;
/**
* Publish a message to the quorum (engine and/or workers)
*/
pubQuorum(quorumMessage: QuorumMessage): Promise<boolean>;
/**
* Subscribe to quorum events (engine and workers)
*/
subQuorum(callback: QuorumMessageCallback): Promise<void>;
/**
* Unsubscribe from quorum events (engine and workers)
*/
unsubQuorum(callback: QuorumMessageCallback): Promise<void>;
/**
* Preview changes and provide an analysis of risk
* prior to deployment
* @private
*/
plan(path: string): Promise<HotMeshManifest>;
/**
* When the app YAML descriptor file is ready, the `deploy` function can be called.
* This function is responsible for merging all referenced YAML source
* files and writing the JSON output to the file system and to the provider backend. It
* is also possible to embed the YAML in-line as a string.
*
* *The version will not be active until activation is explicitly called.*
*/
deploy(pathOrYAML: string): Promise<HotMeshManifest>;
/**
* Once the app YAML file is deployed to the provider backend, the `activate` function can be
* called to enable it for the entire quorum at the same moment.
*
* The approach is to establish the coordinated health of the system through series
* of call/response exchanges. Once it is established that the quorum is healthy,
* the quorum is instructed to run their engine in `no-cache` mode, ensuring
* that the provider backend is consulted for the active app version each time a
* call is processed. This ensures that all engines are running the same version
* of the app, switching over at the same moment and then enabling `cache` mode
* to improve performance.
*
* *Add a delay for the quorum to reach consensus if traffic is busy, but
* also consider throttling traffic flow to an acceptable level.*
*/
activate(version: string, delay?: number): Promise<boolean>;
/**
* Returns the job state as a JSON object, useful
* for understanding dependency chains
*/
export(jobId: string): Promise<JobExport>;
/**
* Returns all data (HGETALL) for a job.
*/
getRaw(jobId: string): Promise<StringStringType>;
/**
* Reporter-related method to get the status of a job
* @private
*/
getStats(topic: string, query: JobStatsInput): Promise<StatsResponse>;
/**
* Returns the status of a job. This is a numeric
* semaphore value that indicates the job's state.
* Any non-positive value indicates a completed job.
* Jobs with a value of `-1` are pending and will
* automatically be scrubbed after a set period.
* Jobs a value around -1billion have been interrupted
* and will be scrubbed after a set period. Jobs with
* a value of 0 completed normally. Jobs with a
* positive value are still running.
*/
getStatus(jobId: string): Promise<JobStatus>;
/**
* Returns the job state (data and metadata) for a job.
*/
getState(topic: string, jobId: string): Promise<JobOutput>;
/**
* Returns searchable/queryable data for a job. In this
* example a literal field is also searched (the colon
* is used to track job status and is a reserved field;
* it can be read but not written).
*
* @example
* ```typescript
* const fields = ['fred', 'barney', '":"'];
* const queryState = await hotMesh.getQueryState('123', fields);
* //returns { fred: 'flintstone', barney: 'rubble', ':': '1' }
* ```
*/
getQueryState(jobId: string, fields: string[]): Promise<StringAnyType>;
/**
* @private
*/
getIds(topic: string, query: JobStatsInput, queryFacets?: any[]): Promise<IdsResponse>;
/**
* @private
*/
resolveQuery(topic: string, query: JobStatsInput): Promise<GetStatsOptions>;
/**
* Interrupt an active job
*/
interrupt(topic: string, jobId: string, options?: JobInterruptOptions): Promise<string>;
/**
* Immediately deletes (DEL) a completed job from the system.
*
* *Scrubbed jobs must be complete with a non-positive `status` value*
*/
scrub(jobId: string): Promise<void>;
/**
* Re/entry point for an active job. This is used to resume a paused job
* and close the reentry point or leave it open for subsequent reentry.
* Because `hooks` are public entry points, they include a `topic`
* which is established in the app YAML file.
*
* When this method is called, a hook rule will be located to establish
* the exact activity and activity dimension for reentry.
*/
hook(topic: string, data: JobData, status?: StreamStatus, code?: StreamCode): Promise<string>;
/**
* @private
*/
hookAll(hookTopic: string, data: JobData, query: JobStatsInput, queryFacets?: string[]): Promise<string[]>;
/**
* Stop all points of presence, workers and engines
*/
static stop(): Promise<void>;
/**
* Stop this point of presence, workers and engines
*/
stop(): void;
/**
* @private
* @deprecated
*/
compress(terms: string[]): Promise<boolean>;
}
export { HotMesh };