@hotmeshio/hotmesh 0.0.22 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/build/package.json +2 -1
  2. package/build/services/durable/connection.js +0 -39
  3. package/build/services/durable/factory.d.ts +6 -4
  4. package/build/services/durable/factory.js +6 -4
  5. package/build/services/durable/handle.d.ts +3 -0
  6. package/build/services/durable/handle.js +14 -2
  7. package/build/services/durable/index.d.ts +2 -45
  8. package/build/services/durable/index.js +2 -45
  9. package/build/services/durable/meshdb.d.ts +113 -0
  10. package/build/services/durable/meshdb.js +211 -0
  11. package/build/services/durable/search.d.ts +9 -0
  12. package/build/services/durable/search.js +35 -2
  13. package/build/services/durable/worker.d.ts +1 -9
  14. package/build/services/durable/worker.js +2 -35
  15. package/build/services/durable/workflow.d.ts +8 -1
  16. package/build/services/durable/workflow.js +11 -7
  17. package/build/services/engine/index.d.ts +2 -0
  18. package/build/services/engine/index.js +3 -0
  19. package/build/services/hotmesh/index.d.ts +3 -1
  20. package/build/services/hotmesh/index.js +5 -2
  21. package/build/services/store/index.d.ts +5 -0
  22. package/build/services/store/index.js +14 -0
  23. package/build/types/durable.d.ts +18 -2
  24. package/build/types/index.d.ts +1 -1
  25. package/package.json +2 -1
  26. package/services/durable/connection.ts +0 -40
  27. package/services/durable/factory.ts +6 -4
  28. package/services/durable/handle.ts +17 -2
  29. package/services/durable/index.ts +2 -46
  30. package/services/durable/meshdb.ts +254 -0
  31. package/services/durable/search.ts +36 -2
  32. package/services/durable/worker.ts +3 -37
  33. package/services/durable/workflow.ts +11 -7
  34. package/services/engine/index.ts +4 -1
  35. package/services/hotmesh/index.ts +6 -2
  36. package/services/store/index.ts +15 -0
  37. package/types/durable.ts +18 -2
  38. package/types/index.ts +2 -1
  39. package/build/services/durable/native.d.ts +0 -4
  40. package/build/services/durable/native.js +0 -46
  41. package/services/durable/native.ts +0 -45
@@ -0,0 +1,254 @@
1
+ import { nanoid } from 'nanoid';
2
+
3
+ import { ClientService as Client } from './client';
4
+ import { WorkflowHandleService } from './handle';
5
+ import { Search } from './search';
6
+ import { WorkerService as Worker } from './worker';
7
+ import { WorkflowSearchOptions } from '../../types/durable';
8
+ import { RedisOptions, RedisClass } from '../../types/redis';
9
+
10
+ /**
11
+ * A base class for configuration and setup of
12
+ * a reentrant process database. Entities modeled as
13
+ * subclasses of this class will execute as reentrant
14
+ * processes with a 'main' execution thread and 'n'
15
+ * parallel hook threads.
16
+ *
17
+ * @example
18
+ * //RUN (start a workflow)
19
+ * const myInstance = new MeshDB('someIdempotentGuid');
20
+ * const handle = await myInstance.create(100);
21
+ * await handle.result(); //100
22
+ *
23
+ * //UPDATE (update a workflow)
24
+ * const result = await myInstance.decrement(11);
25
+ */
26
+
27
+ export class MeshDBService {
28
+
29
+ /**
30
+ * The name of the main method. When this method
31
+ * is invoked/proxied, it is assumed that a new
32
+ * workflow instance is being created. In all other
33
+ * cases, the call is assumed to be a hook/update
34
+ */
35
+ main = 'create';
36
+
37
+ /**
38
+ * The GUID for the workflow (assigned when created). This
39
+ * value should be idempotent and will be rejected if an
40
+ * instance is already running with the same id.
41
+ */
42
+ id: string;
43
+
44
+ /**
45
+ * test value
46
+ */
47
+ value: number;
48
+
49
+ /**
50
+ * The top-level Redis isolation. All workflow data is
51
+ * isolated within this namespace. Values should be
52
+ * lower-case with no spaces (e.g, 'staging', 'prod', 'test',
53
+ * 'routing-stagig', 'reporting-prod', etc.).
54
+ * 1) only url-safe values are allowed;
55
+ * 2) the 'a' symbol is reserved by HotMesh for indexing apps
56
+ */
57
+ namespace = 'durable';
58
+
59
+ /**
60
+ * The second-level isolation. Data is routed to workers
61
+ * that specify this task queue. Setting the task queue
62
+ * when the worker is created will ensure that the worker
63
+ * only receives messages destined for the queue. This
64
+ * allows callers to specify specific workers/containers
65
+ * for specific tasks. Only url-safe values are allowed.
66
+ */
67
+ taskQueue = 'default';
68
+
69
+ /**
70
+ * The Redis connection options. NOTE: Redis and IORedis
71
+ * use different formats for their connection config.
72
+ */
73
+ redisOptions: RedisOptions = {
74
+ host: 'localhost',
75
+ port: 6379,
76
+ password: '',
77
+ db: 0,
78
+ };
79
+
80
+ /**
81
+ * The Redis connection class. Import as follows
82
+ * within the base subclass as follows:
83
+ *
84
+ * @example
85
+ * import Redis from 'ioredis';
86
+ * import * as Redis from 'redis';
87
+ */
88
+ redisClass: RedisClass | null = null;
89
+
90
+ /**
91
+ * Configuration for the the Redis FT search index.
92
+ */
93
+ search: WorkflowSearchOptions;
94
+
95
+ static async getHotMeshClient (redisClass: RedisClass, redisOptions: RedisOptions, namespace: string, taskQueue: string) {
96
+ const client = new Client({
97
+ connection: {
98
+ class: redisClass,
99
+ options: redisOptions,
100
+ }
101
+ });
102
+ return await client.getHotMeshClient(taskQueue, namespace);
103
+ }
104
+
105
+ /**
106
+ * mints a new key, using the provided search prefix, ensuring
107
+ * new workflows are properly indexed
108
+ * @returns {string}
109
+ */
110
+ static mintGuid(): string {
111
+ const my = new this();
112
+ return `${my.search?.prefix?.[0]}${nanoid()}}`;
113
+ }
114
+
115
+ /**
116
+ * Creates an FT search index
117
+ */
118
+ static async createIndex() {
119
+ const my = new this();
120
+ const hmClient = await MeshDBService.getHotMeshClient(my.redisClass, my.redisOptions, my.namespace, my.taskQueue);
121
+ Search.configureSearchIndex(hmClient, my.search)
122
+ }
123
+
124
+ /**
125
+ * Initialize the worker(s) for the entity. This is a static
126
+ * method that allows for optional task Queue targeting.
127
+ * NOTE: Allow List may be optionally used
128
+ * @param {string} taskQueue
129
+ * @param {string[]} allowList
130
+ */
131
+ static async doWork(taskQueue?: string, allowList?: string[]) {
132
+ const my = new this();
133
+ let prototype = Object.getPrototypeOf(my);
134
+ const durablePromises = [];
135
+ const found = [];
136
+
137
+ while (prototype !== null && !Object.getOwnPropertyNames(prototype).includes('__proto__')) {
138
+ const promises = Object.getOwnPropertyNames(prototype).map((prop) => {
139
+ if (found.includes(prop) || ['constructor'].includes(prop) || (allowList && !allowList.includes(prop))) {
140
+ return;
141
+ }
142
+ const originalMethod = my[prop];
143
+ if (typeof originalMethod === 'function') {
144
+ found.push(prop);
145
+ return Worker.create({
146
+ namespace: my.namespace,
147
+ connection: {
148
+ class: my.redisClass,
149
+ options: my.redisOptions,
150
+ },
151
+ taskQueue: taskQueue ?? my.taskQueue,
152
+ workflow: originalMethod,
153
+ });
154
+ }
155
+ }).filter(p => p !== undefined); // filter out undefined values
156
+ durablePromises.push(...promises);
157
+ prototype = Object.getPrototypeOf(prototype);
158
+ }
159
+ await Promise.all(durablePromises);
160
+ }
161
+
162
+ /**
163
+ * executes the redis FT search query
164
+ * @example '@_quantity:[89 89]'
165
+ * @param {any[]} args
166
+ * @returns {string}
167
+ */
168
+ static async find(...args: string[]): Promise<string[] | [number]> {
169
+ const my = new this();
170
+ const client = new Client({ connection: {
171
+ class: my.redisClass,
172
+ options: my.redisOptions
173
+ }});
174
+ return await client.workflow.search(
175
+ my.taskQueue,
176
+ my.main,
177
+ my.namespace,
178
+ my.search.index,
179
+ ...args,
180
+ );
181
+ //[count, [id, fields[], id, fields[], id, fields[], ...]]
182
+ }
183
+
184
+ /**
185
+ * returns the workflow handle (use the handle to call:
186
+ * `state`, `status`, `queryStatus`, and `result`)
187
+ * @param {string} id
188
+ * @returns {Promise<WorkflowHandleService>}
189
+ */
190
+ static async get(id: string): Promise<WorkflowHandleService> {
191
+ const my = new this();
192
+ const client = new Client({ connection: {
193
+ class: my.redisClass,
194
+ options: my.redisOptions
195
+ }});
196
+ return await client.workflow.getHandle(
197
+ my.taskQueue,
198
+ my.main,
199
+ id,
200
+ my.namespace,
201
+ );
202
+ }
203
+
204
+ /**
205
+ * Initialize with an idempotent workflow identifier.
206
+ * Optionally include a target taskQueue to send
207
+ * events to a specific worker.
208
+ */
209
+ constructor(id?: string, taskQueue?: string) {
210
+ this.id = id;
211
+ if (taskQueue) {
212
+ this.taskQueue = taskQueue;
213
+ } else if (!id && !taskQueue) {
214
+ return this;
215
+ }
216
+
217
+ return new Proxy(this, {
218
+ get: (target, prop, receiver) => {
219
+ if (typeof target[prop] === 'function') {
220
+ return (...args: any[]) => {
221
+
222
+ return new Promise(async (resolve, reject) => {
223
+ const client = new Client({ connection: {
224
+ class: this.redisClass,
225
+ options: this.redisOptions
226
+ }});
227
+ if (prop === this.main) {
228
+ //start a new workflow (main method was called)
229
+ return client.workflow.start({
230
+ namespace: this.namespace,
231
+ args,
232
+ taskQueue: this.taskQueue,
233
+ workflowName: prop,
234
+ workflowId: this.id,
235
+ }).then(resolve).catch(reject);
236
+ } else if (prop !== 'constructor') {
237
+ //update an existing workflow (hook/signal-in)
238
+ return client.workflow.hook({
239
+ namespace: this.namespace,
240
+ taskQueue: this.taskQueue,
241
+ workflowName: prop as string,
242
+ workflowId: this.id,
243
+ args,
244
+ }).then(resolve).catch(reject);
245
+ }
246
+ target[prop].apply(this, args).then(resolve).catch(reject);
247
+ });
248
+ };
249
+ }
250
+ return Reflect.get(target, prop, receiver);
251
+ },
252
+ });
253
+ }
254
+ }
@@ -2,6 +2,7 @@ import { HotMeshService as HotMesh } from '../hotmesh'
2
2
  import { RedisClient, RedisMulti } from '../../types/redis';
3
3
  import { StoreService } from '../store';
4
4
  import { KeyService, KeyType } from '../../modules/key';
5
+ import { WorkflowSearchOptions } from '../../types/durable';
5
6
 
6
7
  export class Search {
7
8
  jobId: string;
@@ -11,11 +12,44 @@ export class Search {
11
12
  store: StoreService<RedisClient, RedisMulti> | null;
12
13
 
13
14
  safeKey(key:string): string {
14
- //note: protect the execution namespace with a prefix,
15
- //so its design never conflicts with the hotmesh keyspace
15
+ //note: protect the execution namespace with a prefix
16
16
  return `_${key}`;
17
17
  }
18
18
 
19
+ /**
20
+ * For those deployments with a redis stack backend (with the FT module),
21
+ * this method will configure the search index for the workflow. For all
22
+ * others, this method will exit/fail gracefully and not index
23
+ * the fields in the HASH. However, all values are still available
24
+ * in the HASH.
25
+ */
26
+ static async configureSearchIndex(hotMeshClient: HotMesh, search?: WorkflowSearchOptions): Promise<void> {
27
+ if (search?.schema) {
28
+ const store = hotMeshClient.engine.store;
29
+ const schema: string[] = [];
30
+ for (const [key, value] of Object.entries(search.schema)) {
31
+ //prefix with a comma (avoids collisions with hotmesh reserved words)
32
+ schema.push(`_${key}`);
33
+ schema.push(value.type);
34
+ if (value.sortable) {
35
+ schema.push('SORTABLE');
36
+ }
37
+ }
38
+ try {
39
+ const keyParams = {
40
+ appId: hotMeshClient.appId,
41
+ jobId: ''
42
+ }
43
+ const hotMeshPrefix = KeyService.mintKey(hotMeshClient.namespace, KeyType.JOB_STATE, keyParams);
44
+ const prefixes = search.prefix.map((prefix) => `${hotMeshPrefix}${prefix}`);
45
+ await store.exec('FT.CREATE', `${search.index}`, 'ON', 'HASH', 'PREFIX', prefixes.length.toString(), ...prefixes, 'SCHEMA', ...schema);
46
+ } catch (err) {
47
+ console.error(err);
48
+ hotMeshClient.engine.logger.info('durable-client-search-err', { err });
49
+ }
50
+ }
51
+ }
52
+
19
53
  constructor(workflowId: string, hotMeshClient: HotMesh, searchSessionId: string) {
20
54
  const keyParams = {
21
55
  appId: hotMeshClient.appId,
@@ -6,7 +6,6 @@ import {
6
6
  DurableSleepError,
7
7
  DurableTimeoutError,
8
8
  DurableWaitForSignalError} from '../../modules/errors';
9
- import { KeyService, KeyType } from '../../modules/key';
10
9
  import { asyncLocalStorage } from './asyncLocalStorage';
11
10
  import { APP_ID, APP_VERSION, getWorkflowYAML } from './factory';
12
11
  import { HotMeshService as HotMesh } from '../hotmesh';
@@ -16,9 +15,9 @@ import {
16
15
  Registry,
17
16
  WorkerConfig,
18
17
  WorkerOptions,
19
- WorkflowDataType,
20
- WorkflowSearchOptions} from '../../types/durable';
18
+ WorkflowDataType } from '../../types/durable';
21
19
  import { RedisClass, RedisOptions } from '../../types/redis';
20
+ import { Search } from './search';
22
21
  import {
23
22
  StreamData,
24
23
  StreamDataResponse,
@@ -79,39 +78,6 @@ export class WorkerService {
79
78
  return WorkerService.activityRegistry;
80
79
  }
81
80
 
82
- /**
83
- * For those deployments with a redis stack backend (with the FT module),
84
- * this method will configure the search index for the workflow. For all
85
- * others, this method will fail gracefully. In all cases, the values
86
- * will be stored in the workflow's central HASH data structure, allowing
87
- * for manual traversal and inspection as well.
88
- */
89
- static async configureSearchIndex(hotMeshClient: HotMesh, search?: WorkflowSearchOptions): Promise<void> {
90
- if (search?.schema) {
91
- const store = hotMeshClient.engine.store;
92
- const schema: string[] = [];
93
- for (const [key, value] of Object.entries(search.schema)) {
94
- //prefix with a comma (avoids collisions with hotmesh reserved words)
95
- schema.push(`_${key}`);
96
- schema.push(value.type);
97
- if (value.sortable) {
98
- schema.push('SORTABLE');
99
- }
100
- }
101
- try {
102
- const keyParams = {
103
- appId: hotMeshClient.appId,
104
- jobId: ''
105
- }
106
- const hotMeshPrefix = KeyService.mintKey(hotMeshClient.namespace, KeyType.JOB_STATE, keyParams);
107
- const prefixes = search.prefix.map((prefix) => `${hotMeshPrefix}${prefix}`);
108
- await store.exec('FT.CREATE', `${search.index}`, 'ON', 'HASH', 'PREFIX', prefixes.length, ...prefixes, 'SCHEMA', ...schema);
109
- } catch (err) {
110
- hotMeshClient.engine.logger.info('durable-client-search-err', { err });
111
- }
112
- }
113
- }
114
-
115
81
  static async create(config: WorkerConfig) {
116
82
  WorkerService.connection = config.connection;
117
83
  const workflow = config.workflow;
@@ -124,7 +90,7 @@ export class WorkerService {
124
90
  const worker = new WorkerService();
125
91
  worker.activityRunner = await worker.initActivityWorker(config, activityTopic);
126
92
  worker.workflowRunner = await worker.initWorkflowWorker(config, workflowTopic, workflowFunction);
127
- WorkerService.configureSearchIndex(worker.workflowRunner, config.search)
93
+ Search.configureSearchIndex(worker.workflowRunner, config.search)
128
94
  await WorkerService.activateWorkflow(worker.workflowRunner);
129
95
  return worker;
130
96
  }
@@ -106,6 +106,9 @@ export class WorkflowService {
106
106
  }
107
107
  }
108
108
 
109
+ /**
110
+ * wrap all activities in a proxy that will durably run them
111
+ */
109
112
  static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT> {
110
113
  if (options.activities) {
111
114
  WorkerService.registerActivities(options.activities)
@@ -122,6 +125,9 @@ export class WorkflowService {
122
125
  return proxy;
123
126
  }
124
127
 
128
+ /**
129
+ * return a search session for use when reading/writing to the workflow HASH
130
+ */
125
131
  static async search(): Promise<Search> {
126
132
  const store = asyncLocalStorage.getStore();
127
133
  const workflowId = store.get('workflowId');
@@ -130,15 +136,16 @@ export class WorkflowService {
130
136
  const namespace = store.get('namespace');
131
137
  const COUNTER = store.get('counter');
132
138
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
133
- //this ID is used as a item key with a hash (dash prefix ensures no collision)
134
139
  const hotMeshClient = await WorkerService.getHotMesh(workflowTopic, { namespace });
140
+ //this ID is used as a item key with a hash (dash prefix ensures no collision)
135
141
  const searchSessionId = `-search${workflowDimension}-${execIndex}`;
136
142
  return new Search(workflowId, hotMeshClient, searchSessionId);
137
143
  }
138
144
 
139
145
  /**
140
146
  * those methods that may only be called once must be protected by flagging
141
- * their execution with a unique key (the key is stored in the workflow state)
147
+ * their execution with a unique key (the key is stored in the HASH alongside
148
+ * process state and job state)
142
149
  */
143
150
  static async isSideEffectAllowed(hotMeshClient: HotMesh, prefix:string): Promise<boolean> {
144
151
  const store = asyncLocalStorage.getStore();
@@ -146,15 +153,12 @@ export class WorkflowService {
146
153
  const workflowDimension = store.get('workflowDimension') ?? '';
147
154
  const COUNTER = store.get('counter');
148
155
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
149
- //this ID is used as a item key with a hash (dash prefix ensures no collision)
150
156
  const sessionId = `-${prefix}${workflowDimension}-${execIndex}-`;
151
- //this ID is used as a item key with a hash (dash prefix ensures no collision)
152
157
  const keyParams = {
153
158
  appId: hotMeshClient.appId,
154
- jobId: ''
159
+ jobId: workflowId
155
160
  }
156
- const hotMeshPrefix = KeyService.mintKey(hotMeshClient.namespace, KeyType.JOB_STATE, keyParams);
157
- const workflowGuid = `${hotMeshPrefix}${workflowId}`;
161
+ const workflowGuid = KeyService.mintKey(hotMeshClient.namespace, KeyType.JOB_STATE, keyParams);
158
162
  const guidValue = Number(await hotMeshClient.engine.store.exec('HINCRBYFLOAT', workflowGuid, sessionId, '1') as string);
159
163
  return guidValue === 1;
160
164
  }
@@ -53,6 +53,7 @@ import {
53
53
  SubscriptionCallback } from '../../types/quorum';
54
54
  import { RedisClient, RedisMulti } from '../../types/redis';
55
55
  import { RedisClientType } from '../../types/redisclient';
56
+ import { StringAnyType, StringStringType } from '../../types/serializer';
56
57
  import {
57
58
  GetStatsOptions,
58
59
  IdsResponse,
@@ -67,7 +68,6 @@ import {
67
68
  StreamError,
68
69
  StreamRole,
69
70
  StreamStatus } from '../../types/stream';
70
- import { StringStringType } from '../../types';
71
71
 
72
72
  //wait time to see if a job is complete
73
73
  const OTT_WAIT_TIME = 1000;
@@ -629,6 +629,9 @@ class EngineService {
629
629
  }
630
630
  return stateTree;
631
631
  }
632
+ async getQueryState(jobId: string, fields: string[]): Promise<StringAnyType> {
633
+ return await this.store.getQueryState(jobId, fields);
634
+ }
632
635
 
633
636
  async compress(terms: string[]): Promise<boolean> {
634
637
  const existingSymbols = await this.store.getSymbolValues();
@@ -21,6 +21,7 @@ import {
21
21
  StatsResponse } from '../../types/stats';
22
22
  import { ConnectorService } from '../connector';
23
23
  import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../types/stream';
24
+ import { StringAnyType } from '../../types/serializer';
24
25
 
25
26
  class HotMeshService {
26
27
  namespace: string;
@@ -59,7 +60,7 @@ class HotMeshService {
59
60
  instance.logger = new LoggerService(config.appId, instance.guid, config.name || '', config.logLevel);
60
61
  await instance.initEngine(config, instance.logger);
61
62
  await instance.initQuorum(config, instance.engine, instance.logger);
62
- await instance.initWorkers(config, instance.logger);
63
+ await instance.doWork(config, instance.logger);
63
64
  return instance;
64
65
  }
65
66
 
@@ -97,7 +98,7 @@ class HotMeshService {
97
98
  }
98
99
  }
99
100
 
100
- async initWorkers(config: HotMeshConfig, logger: ILogger) {
101
+ async doWork(config: HotMeshConfig, logger: ILogger) {
101
102
  this.workers = await WorkerService.init(
102
103
  this.namespace,
103
104
  this.appId,
@@ -152,6 +153,9 @@ class HotMeshService {
152
153
  async getState(topic: string, jobId: string): Promise<JobOutput> {
153
154
  return this.engine?.getState(topic, jobId);
154
155
  }
156
+ async getQueryState(jobId: string, fields: string[]): Promise<StringAnyType> {
157
+ return await this.engine?.getQueryState(jobId, fields);
158
+ }
155
159
  async getIds(topic: string, query: JobStatsInput, queryFacets = []): Promise<IdsResponse> {
156
160
  return await this.engine?.getIds(topic, query, queryFacets);
157
161
  }
@@ -476,6 +476,21 @@ abstract class StoreService<T, U extends AbstractRedisClient> {
476
476
  return jobId;
477
477
  }
478
478
 
479
+ /**
480
+ * returns custom search fields and values. The fields param
481
+ * should not prefix items with an underscore.
482
+ */
483
+ async getQueryState(jobId: string, fields: string[]): Promise<StringAnyType> {
484
+ const key = this.mintKey(KeyType.JOB_STATE, { appId: this.appId, jobId });
485
+ const _fields = fields.map(field => `_${field}`);
486
+ const jobDataArray = await this.redisClient[this.commands.hmget](key, _fields);
487
+ const jobData: StringAnyType = {};
488
+ fields.forEach((field, index) => {
489
+ jobData[field] = jobDataArray[index];
490
+ });
491
+ return jobData;
492
+ }
493
+
479
494
  async getState(jobId: string, consumes: Consumes, dIds: StringStringType): Promise<[StringAnyType, number] | undefined> {
480
495
  //get abbreviated field list (the symbols for the paths)
481
496
  const key = this.mintKey(KeyType.JOB_STATE, { appId: this.appId, jobId });
package/types/durable.ts CHANGED
@@ -57,12 +57,27 @@ type WorkflowDataType = {
57
57
  workflowTopic: string;
58
58
  }
59
59
 
60
+ type MeshDBClassConfig = {
61
+ namespace: string;
62
+ taskQueue: string;
63
+ redisOptions: RedisOptions;
64
+ redisClass: RedisClass;
65
+ }
66
+
67
+ type MeshDBConfig = {
68
+ taskQueue?: string;
69
+ index?: {
70
+ index: string;
71
+ prefix: string[];
72
+ schema: Record<string, {type: 'TEXT' | 'NUMERIC' | 'TAG', sortable: boolean}>;
73
+ };
74
+ }
75
+
60
76
  type ConnectionConfig = {
61
77
  class: RedisClass;
62
78
  options: RedisOptions;
63
79
  }
64
80
  type Connection = ConnectionConfig;
65
- type NativeConnection = ConnectionConfig;
66
81
 
67
82
  type ClientConfig = {
68
83
  connection: Connection;
@@ -115,11 +130,12 @@ export {
115
130
  ContextType,
116
131
  ConnectionConfig,
117
132
  Connection,
118
- NativeConnection,
119
133
  ProxyType,
120
134
  Registry,
121
135
  SignalOptions,
122
136
  HookOptions,
137
+ MeshDBClassConfig,
138
+ MeshDBConfig,
123
139
  WorkerConfig,
124
140
  WorkflowConfig,
125
141
  WorkerOptions,
package/types/index.ts CHANGED
@@ -34,10 +34,11 @@ export {
34
34
  ContextType,
35
35
  ConnectionConfig,
36
36
  Connection,
37
- NativeConnection,
38
37
  ProxyType,
39
38
  Registry,
40
39
  HookOptions,
40
+ MeshDBClassConfig,
41
+ MeshDBConfig,
41
42
  WorkflowConfig,
42
43
  WorkerConfig,
43
44
  WorkerOptions,
@@ -1,4 +0,0 @@
1
- import { Connection, ConnectionConfig } from "../../types/durable";
2
- export declare class NativeConnectionService {
3
- static connect(config: ConnectionConfig): Promise<Connection>;
4
- }
@@ -1,46 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NativeConnectionService = void 0;
4
- /*
5
-
6
- Here is an example of how the methods in this file are used:
7
-
8
- ./worker.ts
9
-
10
- import { Durable: { NativeConnection, Worker } } from '@hotmeshio/hotmesh';
11
- import Redis from 'ioredis'; //OR `import * as Redis from 'redis';`
12
-
13
- import * as workflows from './workflows';
14
-
15
- async function run() {
16
- const connection = await NativeConnection.connect({
17
- class: Redis,
18
- options: {
19
- host: 'localhost',
20
- port: 6379,
21
- },
22
- });
23
- const worker = await Worker.create({
24
- connection,
25
- taskQueue: 'hello-world',
26
- workflow: workflows.example,
27
- activities,
28
- });
29
- await worker.run();
30
- }
31
-
32
- run().catch((err) => {
33
- console.error(err);
34
- process.exit(1);
35
- });
36
-
37
- */
38
- class NativeConnectionService {
39
- static async connect(config) {
40
- return {
41
- class: config.class,
42
- options: { ...config.options },
43
- };
44
- }
45
- }
46
- exports.NativeConnectionService = NativeConnectionService;
@@ -1,45 +0,0 @@
1
- import { Connection, ConnectionConfig } from "../../types/durable";
2
-
3
- /*
4
-
5
- Here is an example of how the methods in this file are used:
6
-
7
- ./worker.ts
8
-
9
- import { Durable: { NativeConnection, Worker } } from '@hotmeshio/hotmesh';
10
- import Redis from 'ioredis'; //OR `import * as Redis from 'redis';`
11
-
12
- import * as workflows from './workflows';
13
-
14
- async function run() {
15
- const connection = await NativeConnection.connect({
16
- class: Redis,
17
- options: {
18
- host: 'localhost',
19
- port: 6379,
20
- },
21
- });
22
- const worker = await Worker.create({
23
- connection,
24
- taskQueue: 'hello-world',
25
- workflow: workflows.example,
26
- activities,
27
- });
28
- await worker.run();
29
- }
30
-
31
- run().catch((err) => {
32
- console.error(err);
33
- process.exit(1);
34
- });
35
-
36
- */
37
-
38
- export class NativeConnectionService {
39
- static async connect(config: ConnectionConfig): Promise<Connection> {
40
- return {
41
- class: config.class,
42
- options: { ...config.options },
43
- } as Connection;
44
- }
45
- }