UNPKG

@hotmeshio/hotmesh

Version:

Serverless Workflow

341 lines (340 loc) 11.7 kB
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 };