UNPKG

@hotmeshio/hotmesh

Version:

Serverless Workflow

796 lines (795 loc) 33.6 kB
import { HotMesh } from '../hotmesh'; import { WorkflowOptions, WorkflowSearchOptions, FindJobsOptions, FindOptions, FindWhereOptions, SearchResults, FindWhereQuery } from '../../types/meshflow'; import { CallOptions, ConnectionInput, ExecInput, HookInput } from '../../types/meshdata'; import { StringAnyType, StringStringType } from '../../types/serializer'; import { JobInterruptOptions, JobOutput } from '../../types/job'; import { QuorumMessage, QuorumMessageCallback, QuorumProfile, RollCallOptions, SubscriptionOptions, ThrottleOptions } from '../../types/quorum'; import { MeshFlowJobExport, ExportOptions } from '../../types/exporter'; import { ProviderConfig, ProvidersConfig } from '../../types/provider'; /** * The `MeshData` service extends the `MeshFlow` service. * It serves to unify both data record and * transactional workflow principles into a single * *Operational Data Layer*. Deployments with a 'search' * provider configured (e.g.,Redis FT.SEARCH) can deliver * both OLTP (transactions) and OLAP (analytics) * with no additional infrastructure. * * The following example depicts the full end-to-end * lifecycle of a `MeshData` app, including the * connection of a worker function, the execution of * a remote function, the retrieval of data, * the creation of a search index, and the execution * of a full-text search query. * * @example * ```typescript * import { MeshData, Types } from '@hotmeshio/hotmesh'; * import * as Redis from 'redis'; * * //1) Define a search schema * const schema = { * schema: { * id: { type: 'TAG', sortable: true }, * plan: { type: 'TAG', sortable: true }, * active: { type: 'TEXT', sortable: false }, * }, * index: 'user', * prefix: ['user'], //index items with keys starting with 'user' * } as unknown as Types.WorkflowSearchOptions; * * //2) Initialize MeshData and Redis * const meshData = new MeshData( * { * class: Redis, * options: { url: 'redis://:key_admin@redis:6379' }, * }, * schema, * ); * * //3) Connect a 'user' worker function * await meshData.connect({ * entity: 'user', * target: async function(userID: string): Promise<string> { * //used the `search` extension to add searchable data * const search = await MeshData.workflow.search(); * await search.set('active', 'yes'); * return `Welcome, ${userID}.`; * }, * options: { namespace: 'meshdata' }, * }); * * const userID = 'someTestUser123'; * * //4) Call the 'user' worker function; include search data * const response = await meshData.exec({ * entity: 'user', * args: [userID], * options: { * ttl: 'infinity', * id: userID, * search: { * data: { id: userID, plan: 'pro' } * }, * namespace: 'meshdata', * }, * }); * * //5) Read data by field name * const data = await meshData.get( * 'user', * userID, * { * fields: ['plan', 'id', 'active'], * namespace: 'meshdata' * }, * ); * * //6) Create a search index * await meshData.createSearchIndex('user', { namespace: 'meshdata' }, schema); * * //7) Perform Full Text Search on the indexed dataset * const results = await meshData.findWhere('user', { * query: [{ field: 'id', is: '=', value: userID }], * limit: { start: 0, size: 100 }, * return: ['plan', 'id', 'active'] * }); * * //8) Shutdown MeshData * await MeshData.shutdown(); * ``` * */ declare class MeshData { /** * unused; allows wrapped functions to be stringified * so their source can be shared on the network for * remote analysis. this is useful for targeting which * version of a function is being executed. * @private */ connectionSignatures: StringStringType; /** * The provider configuration for the MeshData service. * @private * @example * // Example 1) Instantiate MeshData with `ioredis` * import Redis from 'ioredis'; * * const meshData = new MeshData({ * class: Redis, * options: { * host: 'localhost', * port: 6379, * password: 'shhh123', * db: 0, * }}); * * // Example 2) Instantiate MeshData with `redis` * import * as Redis from 'redis'; * * const meshData = new MeshData({ * class: Redis, * options: { * url: 'redis://:shhh123@localhost:6379' * }}); * * // Example 3) Instantiate MeshData with `postgres` * import { Client as PostgresClient } from 'pg'; * * const meshData = new MeshData({ * class: PostgresClient, * options: { * connectionString: 'postgresql://usr:pwd@localhost:5432/db', * }}); * * // Example 4) Instantiate MeshData with `postgres` and `nats` * import { connect as NATS } from 'nats'; * * const meshData = new MeshData({ * store:{ * class: PostgresClient, * options: { * connectionString: 'postgresql://usr:pwd@localhost:5432/db', * } * }, * stream:{ * class: PostgresClient, * options: { * connectionString: 'postgresql://usr:pwd@localhost:5432/db', * } * }, * sub :{ * class: NATS, * options: { * server: ['nats://localhost:4222'], * } * }, * }); */ connection: ProviderConfig | ProvidersConfig; /** * Cached local instances (map) of HotMesh organized by namespace * @private */ instances: Map<string, Promise<HotMesh> | HotMesh>; /** * Search backend configuration (indexed/searchable fields and types) */ search: WorkflowSearchOptions; /** * Provides a set of static extensions that can be invoked by * your linked workflow functions during their execution. * @example * * function greet (email: string, user: { first: string}) { * //persist the user's email and newsletter preferences * const search = await MeshData.workflow.search(); * await search.set('email', email, 'newsletter', 'yes'); * * //hook a function to send a newsletter * await MeshData.workflow.hook({ * entity: 'user.newsletter', * args: [email] * }); * * return `Hello, ${user.first}. Your email is [${email}].`; * } */ static workflow: { sleep: typeof import("../meshflow/workflow/sleepFor").sleepFor; sleepFor: typeof import("../meshflow/workflow/sleepFor").sleepFor; signal: typeof import("../meshflow/workflow/signal").signal; hook: typeof import("../meshflow/workflow/hook").hook; waitForSignal: typeof import("../meshflow/workflow/waitFor").waitFor; waitFor: typeof import("../meshflow/workflow/waitFor").waitFor; getHotMesh: typeof import("../..").workflow.getHotMesh; random: typeof import("../meshflow/workflow/random").random; search: typeof import("../meshflow/workflow/searchMethods").search; getContext: typeof import("../meshflow/workflow/context").getContext; /** * Interrupts a job by its entity and id. */ interrupt: (entity: string, id: string, options?: JobInterruptOptions) => Promise<void>; /** * Starts a new, subordinated workflow/job execution. NOTE: The child workflow's * lifecycle is bound to the parent workflow, and it will be terminated/scrubbed * when the parent workflow is terminated/scrubbed. * * @template T The expected return type of the target function. */ execChild: <T>(options?: Partial<WorkflowOptions>) => Promise<T>; /** * Starts a new, subordinated workflow/job execution. NOTE: The child workflow's * lifecycle is bound to the parent workflow, and it will be terminated/scrubbed * when the parent workflow is terminated/scrubbed. * * @template T The expected return type of the target function. */ executeChild: <T_1>(options?: Partial<WorkflowOptions>) => Promise<T_1>; /** * Starts a new, subordinated workflow/job execution, awaiting only the jobId, namely, * the confirmation that the suboridinated job has begun. NOTE: The child workflow's * lifecycle is bound to the parent workflow, and it will be terminated/scrubbed * when the parent workflow is terminated/scrubbed. */ startChild: (options?: Partial<WorkflowOptions>) => Promise<string>; }; /** * Instances a new `MeshData` service. * @param {ProviderConfig|ProvidersConfig} connection - the connection class and options * @param {WorkflowSearchOptions} search - the search options for JSON-based configuration of the backend search module (e.g., Redis FT.Search) * @example * // Example 1) Instantiate MeshData with `ioredis` * import Redis from 'ioredis'; * * const meshData = new MeshData({ * class: Redis, * options: { * host: 'localhost', * port: 6379, * password: 'shhh123', * db: 0, * }}); * * // Example 2) Instantiate MeshData with `redis` * import * as Redis from 'redis'; * * const meshData = new MeshData({ * class: Redis, * options: { * url: 'redis://:shhh123@localhost:6379' * }}); * * // Instantiate MeshData with `postgres` * //... */ constructor(connection: ProviderConfig | ProvidersConfig, search?: WorkflowSearchOptions); /** * @private */ validate(entity: string): void; /** * @private */ getConnection(): Promise<ProviderConfig | ProvidersConfig>; /** * Return a MeshFlow client * @private */ getClient(): import("../..").Client; /** * @private */ safeKey(key: string): string; /** * @private * todo: move to `utils` (might already be there); * also might be better as specialized provider utils */ arrayToHash(input: [number, ...Array<string | string[]>]): StringStringType[]; /** * serialize using the HotMesh `toString` format * @private */ toString(value: unknown): string | undefined; /** * returns an entity-namespaced guid * @param {string|null} entity - entity namespace * @param {string} [id] - workflow id (allowed to be namespaced) * @returns {string} * @private */ static mintGuid(entity: string, id?: string): string; /** * Returns a HotMesh client * @param {string} [namespace='meshflow'] - the namespace for the client * @returns {Promise<HotMesh>} */ getHotMesh(namespace?: string): Promise<HotMesh>; /** * Returns the HASH key given an `entity` name and workflow/job. The * item identified by this key is a HASH record with multidimensional process * data interleaved with the function state data. * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} workflowId - the workflow/job id * @param {string} [namespace='meshflow'] - the namespace for the client * @returns {Promise<string>} * @example * // mint a key * const key = await meshData.mintKey('greeting', 'jsmith123'); * * // returns 'hmsh:meshflow:j:greeting-jsmith123' */ mintKey(entity: string, workflowId: string, namespace?: string): Promise<string>; /** * Exposes the the service mesh control plane through the * mesh 'events' (pub/sub) system. This is useful for * monitoring and managing the operational data layer. */ mesh: { /** * subscribes to the mesh control plane * @param {QuorumMessageCallback} callback - the callback function * @param {SubscriptionOptions} options - connection options * @returns {Promise<void>} */ sub: (callback: QuorumMessageCallback, options?: SubscriptionOptions) => Promise<void>; /** * publishes a message to the mesh control plane * @param {QuorumMessage} message - the message payload * @param {SubscriptionOptions} options - connection options * @returns {Promise<void>} */ pub: (message: QuorumMessage, options?: SubscriptionOptions) => Promise<void>; /** * unsubscribes from the mesh control plane * @param {QuorumMessageCallback} callback - the callback function * @param {SubscriptionOptions} options - connection options * @returns {Promise<void>} */ unsub: (callback: QuorumMessageCallback, options?: SubscriptionOptions) => Promise<void>; }; /** * Connects a function to the operational data layer. * * @template T The expected return type of the target function. * * @param {object} connection - The options for connecting a function. * @param {string} connection.entity - The global entity identifier for the function (e.g, 'user', 'order', 'product'). * @param {(...args: any[]) => T} connection.target - Function to connect, returns type T. * @param {ConnectOptions} connection.options={} - Extended connection options (e.g., ttl, taskQueue). A * ttl of 'infinity' will cache the function indefinitely. * * @returns {Promise<boolean>} True if connection is successfully established. * * @example * // Instantiate MeshData with Redis configuration. * const meshData = new MeshData({ * class: Redis, * options: { host: 'localhost', port: 6379 } * }); * * // Define and connect a function with the 'greeting' entity. * // The function will be cached indefinitely (infinite TTL). * await meshData.connect({ * entity: 'greeting', * target: (email, user) => `Hello, ${user.first}.`, * options: { ttl: 'infinity' } * }); */ connect<T>({ entity, target, options, }: ConnectionInput<T>): Promise<boolean>; /** * During remote execution, an argument is injected (the last argument) * this is then used by the 'connect' function to determine if the call * is a hook or a exec call. If it is an exec, the connected function has * precedence and can say that all calls are cached indefinitely. * * @param {any[]} args * @param {StringAnyType} callOptions * @returns {StringAnyType} * @private */ bindCallOptions(args: any[], callOptions?: CallOptions): StringAnyType; /** * Sleeps/WaitsForSignal to keep the function open * and remain part of the operational data layer * * @template T The expected return type of the remote function * * @param {string} result - the result to emit before going to sleep * @param {CallOptions} options - call options * @private */ pauseForTTL<T>(result: T, options: CallOptions): Promise<void>; /** * Publishes the job result, because pausing the job (in support of * the 'ttl' option) interrupts the response. * * @template T The expected return type of the remote function * * @param {string} result - the result to emit before going to sleep * @param {HotMesh} hotMesh - call options * @param {CallOptions} options - call options * * @returns {Promise<void>} * @private */ publishDone<T>(result: T, hotMesh: HotMesh, options: CallOptions): Promise<void>; /** * Flushes a function with a `ttl` of 'infinity'. These entities were * created by a connect method that was configured with a * `ttl` of 'infinity'. It can take several seconds for the function * to be removed from the cache as it might be actively orchestrating * sub-workflows. * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - The workflow/job id * @param {string} [namespace='meshflow'] - the namespace for the client * * @example * // Flush a function * await meshData.flush('greeting', 'jsmith123'); */ flush(entity: string, id: string, namespace?: string): Promise<string | void>; /** * Interrupts a job by its entity and id. It is best not to call this * method directly for entries with a ttl of `infinity` (call `flush` instead). * For those entities that are cached for a specified duration (e.g., '15 minutes'), * this method will interrupt the job and start the cascaded cleanup/expire/delete. * As jobs are asynchronous, there is no way to stop descendant flows immediately. * Use an `expire` option to keep the interrupted job in the cache for a specified * duration before it is fully removed. * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - The workflow/job id * @param {JobInterruptOptions} [options={}] - call options * @param {string} [namespace='meshflow'] - the namespace for the client * * @example * // Interrupt a function * await meshData.interrupt('greeting', 'jsmith123'); */ interrupt(entity: string, id: string, options?: JobInterruptOptions, namespace?: string): Promise<void>; /** * Signals a Hook Function or Main Function to awaken that * is paused and registered to awaken upon receiving the signal * matching @guid. * * @param {string} guid - The global identifier for the signal * @param {StringAnyType} payload - The payload to send with the signal * @param {string} [namespace='meshflow'] - the namespace for the client * @returns {Promise<string>} - the signal id * @example * // Signal a function with a payload * await meshData.signal('signal123', { message: 'hi!' }); * * // returns '123456732345-0' (stream message receipt) */ signal(guid: string, payload: StringAnyType, namespace?: string): Promise<string>; /** * Sends a signal to the backend Service Mesh (workers and engines) * to announce their presence, including message counts, target * functions, topics, etc. This is useful for establishing * the network profile and overall message throughput * of the operational data layer as a unified quorum. * @param {RollCallOptions} options * @returns {Promise<QuorumProfile[]>} */ rollCall(options?: RollCallOptions): Promise<QuorumProfile[]>; /** * Throttles a worker or engine in the backend Service Mesh, using either * a 'guid' to target a specific worker or engine, or a 'topic' to target * a group of worker(s) connected to that topic. The throttle value is * specified in milliseconds and will cause the target(s) to delay consuming * the next message by this amount. By default, the value is set to `0`. * @param {ThrottleOptions} options * @returns {Promise<boolean>} * * @example * // Throttle a worker or engine * await meshData.throttle({ guid: '1234567890', throttle: 10_000 }); */ throttle(options: ThrottleOptions): Promise<boolean>; /** * Similar to `exec`, except it augments the workflow state without creating a new job. * * @param {object} input - The input parameters for hooking a function. * @param {string} input.entity - The target entity name (e.g., 'user', 'order', 'product'). * @param {string} input.id - The target execution/workflow/job id. * @param {string} input.hookEntity - The hook entity name (e.g, 'user.notification'). * @param {any[]} input.hookArgs - The arguments for the hook function; must be JSON serializable. * @param {HookOptions} input.options={} - Extended hook options (taskQueue, namespace, etc). * @returns {Promise<string>} The signal id. * * @example * // Hook a function * const signalId = await meshData.hook({ * entity: 'greeting', * id: 'jsmith123', * hookEntity: 'greeting.newsletter', * hookArgs: ['xxxx@xxxxx'], * options: {} * }); */ hook({ entity, id, hookEntity, hookArgs, options, }: HookInput): Promise<string>; /** * Executes a remote function by its global entity identifier with specified arguments. * If options.ttl is infinity, the function will be cached indefinitely and can only be * removed by calling `flush`. During this time, the function will remain active and * its state can be augmented by calling `set`, `incr`, `del`, etc OR by calling a * transactional 'hook' function. * * @template T The expected return type of the remote function. * * @param {object} input - The execution parameters. * @param {string} input.entity - The function entity name (e.g., 'user', 'order', 'user.bill'). * @param {any[]} input.args - The arguments for the remote function. * @param {CallOptions} input.options={} - Extended configuration options for execution (e.g, taskQueue). * * @returns {Promise<T>} A promise that resolves with the result of the remote function execution. If * the input options include `await: false`, the promise will resolve with the * workflow ID (string) instead of the result. Make sure to pass string as the * return type if you are using `await: false`. * * @example * // Invoke a remote function with arguments and options * const response = await meshData.exec({ * entity: 'greeting', * args: ['jsmith@hotmesh', { first: 'Jan' }], * options: { ttl: '15 minutes', id: 'jsmith123' } * }); */ exec<T>({ entity, args, options }: ExecInput): Promise<T>; /** * Retrieves the job profile for the function execution, including metadata such as * execution status and result. * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - identifier for the job * @param {CallOptions} [options={}] - Configuration options for the execution, * including custom IDs, time-to-live (TTL) settings, etc. * Defaults to an empty object if not provided. * * @returns {Promise<JobOutput>} A promise that resolves with the job's output, which * includes metadata about the job's execution status. The * structure of `JobOutput` should contain all relevant * information such as execution result, status, and any * error messages if the job failed. * * @example * // Retrieve information about a remote function's execution by job ID * const jobInfoById = await meshData.info('greeting', 'job-12345'); * * // Response: JobOutput * { * metadata: { * tpc: 'meshflow.execute', * app: 'meshflow', * vrs: '1', * jid: 'greeting-jsmith123', * aid: 't1', * ts: '0', * jc: '20240208014803.980', * ju: '20240208065017.762', * js: 0 * }, * data: { * done: true, * response: 'Hello, Jan. Your email is [jsmith@hotmesh.com].', * workflowId: 'greeting-jsmith123' * } * } */ info(entity: string, id: string, options?: CallOptions): Promise<JobOutput>; /** * Exports the job profile for the function execution, including * all state, process, and timeline data. The information in the export * is sufficient to capture the full state of the function in the moment * and over time. * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - The workflow/job id * @param {ExportOptions} [options={}] - Configuration options for the export * @param {string} [namespace='meshflow'] - the namespace for the client * * @example * // Export a function * await meshData.export('greeting', 'jsmith123'); */ export(entity: string, id: string, options?: ExportOptions, namespace?: string): Promise<MeshFlowJobExport>; /** * Returns the remote function state. this is different than the function response * returned by the `exec` method which represents the return value from the * function at the moment it completed. Instead, function state represents * mutable shared state that can be set: * 1) when the record is first created (provide `options.search.data` to `exec`) * 2) during function execution ((await MeshData.workflow.search()).set(...)) * 3) during hook execution ((await MeshData.workflow.search()).set(...)) * 4) via the meshData SDK (`meshData.set(...)`) * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - the job id * @param {CallOptions} [options={}] - call options * * @returns {Promise<StringAnyType>} - the function state * * @example * // get the state of a function * const state = await meshData.get('greeting', 'jsmith123', { fields: ['fred', 'barney'] }); * * // returns { fred: 'flintstone', barney: 'rubble' } */ get(entity: string, id: string, options?: CallOptions): Promise<StringAnyType>; /** * Returns the remote function state for all fields. NOTE: * `all` can be less efficient than calling `get` as it returns all * fields (HGETALL), not just the ones requested (HMGET). Depending * upon the duration of the workflow, this could represent a large * amount of process/history data. * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - the workflow/job id * @param {CallOptions} [options={}] - call options * * @returns {Promise<StringAnyType>} - the function state * * @example * // get the state of the job (this is not the response...this is job state) * const state = await meshData.all('greeting', 'jsmith123'); * * // returns { fred: 'flintstone', barney: 'rubble', ... } */ all(entity: string, id: string, options?: CallOptions): Promise<StringAnyType>; /** * Returns all fields in the HASH record: * * 1) `:`: workflow status (a semaphore where `0` is complete) * 2) `_*`: function state (name/value pairs are prefixed with `_`) * 3) `-*`: workflow cycle state (cycles are prefixed with `-`) * 4) `[a-zA-Z]{3}`: mutable workflow job state * 5) `[a-zA-Z]{3}[,\d]+`: immutable workflow activity state * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - the workflow/job id * @param {CallOptions} [options={}] - call options * * @returns {Promise<StringAnyType>} - the function state * * @example * // get the state of a function * const state = await meshData.raw('greeting', 'jsmith123'); * * // returns { : '0', _barney: 'rubble', aBa: 'Hello, John Doe. Your email is [jsmith@hotmesh].', ... } */ raw(entity: string, id: string, options?: CallOptions): Promise<StringAnyType>; /** * Sets the remote function state. this is different than the function response * returned by the exec method which represents the return value from the * function at the moment it completed. Instead, function state represents * mutable shared state that can be set * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - the job id * @param {CallOptions} [options={}] - call options * * @returns {Promise<number>} - count. The number inserted (Postgres) / updated(Redis) * @example * // set the state of a function * const count = await meshData.set('greeting', 'jsmith123', { search: { data: { fred: 'flintstone', barney: 'rubble' } } }); */ set(entity: string, id: string, options?: CallOptions): Promise<number>; /** * Increments a field in the remote function state. * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - the job id * @param {string} field - the field name * @param {number} amount - the amount to increment * @param {CallOptions} [options={}] - call options * * @returns {Promise<number>} - the new value * @example * // increment a field in the function state * const count = await meshData.incr('greeting', 'jsmith123', 'counter', 1); */ incr(entity: string, id: string, field: string, amount: number, options?: CallOptions): Promise<number>; /** * Deletes one or more fields from the remote function state. * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {string} id - the job id * @param {CallOptions} [options={}] - call options * * @returns {Promise<number>} - the count of fields deleted * @example * // remove two hash fields from the function state * const count = await meshData.del('greeting', 'jsmith123', { fields: ['fred', 'barney'] }); */ del(entity: string, id: string, options: CallOptions): Promise<number>; /** * For those implementations without a search backend, this quasi-equivalent * method is provided with a cursor for rudimentary pagination. * @param {FindJobsOptions} [options] * @returns {Promise<[string, string[]]>} * @example * // find jobs * const [cursor, jobs] = await meshData.findJobs({ match: 'greeting*' }); * * // returns [ '0', [ 'hmsh:meshflow:j:greeting-jsmith123', 'hmsh:meshflow:j:greeting-jdoe456' ] ] */ findJobs(options?: FindJobsOptions): Promise<[string, string[]]>; /** * Executes the search query; optionally specify other commands * @example '@_quantity:[89 89]' * @example '@_quantity:[89 89] @_name:"John"' * @example 'FT.search my-index @_quantity:[89 89]' * @param {FindOptions} options * @param {any[]} args * @returns {Promise<string[] | [number] | Array<number, string | number | string[]>>} */ find(entity: string, options: FindOptions, ...args: string[]): Promise<string[] | [number] | Array<string | number | string[]>>; /** * Provides a JSON abstraction for the backend search engine * (e.g, `count`, `query`, `return`, `limit`) * NOTE: If the type is TAG for an entity, `.`, `@`, and `-` must be escaped. * * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {FindWhereOptions} options - find options (the query). A custom search schema may be provided. * @returns {Promise<SearchResults | number>} Returns a number if `count` is true, otherwise a SearchResults object. * @example * const results = await meshData.findWhere('greeting', { * query: [ * { field: 'name', is: '=', value: 'John' }, * { field: 'age', is: '>', value: 2 }, * { field: 'quantity', is: '[]', value: [89, 89] } * ], * count: false, * limit: { start: 0, size: 10 }, * return: ['name', 'quantity'] * }); * * // returns { count: 1, query: 'FT.SEARCH my-index @_name:"John" @_age:[2 +inf] @_quantity:[89 89] LIMIT 0 10', data: [ { name: 'John', quantity: '89' } ] } */ findWhere(entity: string, options: FindWhereOptions): Promise<SearchResults | number>; /** * Generates a search query from a FindWhereQuery array * @param {FindWhereQuery[] | string} [query] * @param {WorkflowSearchOptions} [search] * @returns {string} * @private */ generateSearchQuery(query: FindWhereQuery[] | string, search?: WorkflowSearchOptions): string; /** * Creates a search index for the specified search backend (e.g., FT.search). * @param {string} entity - the entity name (e.g, 'user', 'order', 'product') * @param {CallOptions} [options={}] - call options * @param {WorkflowSearchOptions} [searchOptions] - search options * @returns {Promise<string>} - the search index name * @example * // create a search index for the 'greeting' entity. pass in search options. * const index = await meshData.createSearchIndex('greeting', {}, { prefix: 'greeting', ... }); * * // creates a search index for the 'greeting' entity, using the default search options. * const index = await meshData.createSearchIndex('greeting'); */ createSearchIndex(entity: string, options?: CallOptions, searchOptions?: WorkflowSearchOptions): Promise<void>; /** * Lists all search indexes in the operational data layer when the * targeted search backend is configured/enabled. * @returns {Promise<string[]>} * @example * // list all search indexes * const indexes = await meshData.listSearchIndexes(); * * // returns ['greeting', 'user', 'order', 'product'] */ listSearchIndexes(): Promise<string[]>; /** * Wrap activities in a proxy that will durably run them, once. */ static proxyActivities: typeof import("../..").proxyActivities; /** * shut down MeshData (typically on sigint or sigterm) */ static shutdown(): Promise<void>; } export { MeshData };