@hotmeshio/hotmesh 0.0.22 → 0.0.24

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 (51) hide show
  1. package/README.md +66 -67
  2. package/build/index.d.ts +2 -1
  3. package/build/index.js +3 -1
  4. package/build/package.json +2 -1
  5. package/build/services/durable/connection.js +0 -39
  6. package/build/services/durable/factory.d.ts +6 -4
  7. package/build/services/durable/factory.js +12 -10
  8. package/build/services/durable/handle.d.ts +3 -0
  9. package/build/services/durable/handle.js +15 -5
  10. package/build/services/durable/index.d.ts +2 -45
  11. package/build/services/durable/index.js +2 -45
  12. package/build/services/durable/meshos.d.ts +108 -0
  13. package/build/services/durable/meshos.js +289 -0
  14. package/build/services/durable/search.d.ts +9 -0
  15. package/build/services/durable/search.js +34 -2
  16. package/build/services/durable/worker.d.ts +2 -10
  17. package/build/services/durable/worker.js +10 -39
  18. package/build/services/durable/workflow.d.ts +12 -1
  19. package/build/services/durable/workflow.js +32 -16
  20. package/build/services/engine/index.d.ts +2 -0
  21. package/build/services/engine/index.js +3 -0
  22. package/build/services/hotmesh/index.d.ts +3 -1
  23. package/build/services/hotmesh/index.js +5 -2
  24. package/build/services/signaler/stream.js +1 -2
  25. package/build/services/store/clients/ioredis.js +2 -2
  26. package/build/services/store/clients/redis.js +1 -1
  27. package/build/services/store/index.d.ts +5 -0
  28. package/build/services/store/index.js +14 -0
  29. package/build/types/durable.d.ts +34 -4
  30. package/build/types/index.d.ts +1 -1
  31. package/index.ts +2 -1
  32. package/package.json +2 -1
  33. package/services/durable/connection.ts +0 -40
  34. package/services/durable/factory.ts +12 -10
  35. package/services/durable/handle.ts +18 -5
  36. package/services/durable/index.ts +2 -46
  37. package/services/durable/meshos.ts +344 -0
  38. package/services/durable/search.ts +35 -2
  39. package/services/durable/worker.ts +11 -42
  40. package/services/durable/workflow.ts +34 -17
  41. package/services/engine/index.ts +4 -1
  42. package/services/hotmesh/index.ts +6 -2
  43. package/services/signaler/stream.ts +1 -2
  44. package/services/store/clients/ioredis.ts +2 -3
  45. package/services/store/clients/redis.ts +1 -1
  46. package/services/store/index.ts +15 -0
  47. package/types/durable.ts +40 -4
  48. package/types/index.ts +6 -1
  49. package/build/services/durable/native.d.ts +0 -4
  50. package/build/services/durable/native.js +0 -46
  51. package/services/durable/native.ts +0 -45
@@ -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
  }
@@ -61,7 +61,7 @@ class StreamSignaler {
61
61
  try {
62
62
  await this.store.xgroup('CREATE', stream, group, '$', 'MKSTREAM');
63
63
  } catch (err) {
64
- this.logger.info('consumer-group-exists', { stream, group });
64
+ this.logger.debug('consumer-group-exists', { stream, group });
65
65
  }
66
66
  }
67
67
 
@@ -150,7 +150,6 @@ class StreamSignaler {
150
150
  try {
151
151
  output = await callback(input);
152
152
  } catch (error) {
153
- console.error(error);
154
153
  this.logger.error(`stream-call-function-error`, { error });
155
154
  output = this.structureUnhandledError(input, error);
156
155
  }
@@ -5,7 +5,6 @@ import { Cache } from '../cache';
5
5
  import { StoreService } from '../index';
6
6
  import { RedisClientType, RedisMultiType } from '../../../types/ioredisclient';
7
7
  import { ReclaimedMessageType } from '../../../types/stream';
8
- import { type } from 'os';
9
8
 
10
9
  class IORedisStoreService extends StoreService<RedisClientType, RedisMultiType> {
11
10
  redisClient: RedisClientType;
@@ -60,14 +59,14 @@ class IORedisStoreService extends StoreService<RedisClientType, RedisMultiType>
60
59
  try {
61
60
  return (await this.redisClient.xgroup(command, key, groupName, id, mkStream)) === 'OK';
62
61
  } catch (err) {
63
- this.logger.info(`Consumer group not created with MKSTREAM for key: ${key} and group: ${groupName}`);
62
+ this.logger.debug(`Consumer group not created with MKSTREAM for key: ${key} and group: ${groupName}`);
64
63
  throw err;
65
64
  }
66
65
  } else {
67
66
  try {
68
67
  return (await this.redisClient.xgroup(command, key, groupName, id)) === 'OK';
69
68
  } catch (err) {
70
- this.logger.info(`Consumer group not created for key: ${key} and group: ${groupName}`);
69
+ this.logger.debug(`Consumer group not created for key: ${key} and group: ${groupName}`);
71
70
  throw err;
72
71
  }
73
72
  }
@@ -86,7 +86,7 @@ class RedisStoreService extends StoreService<RedisClientType, RedisMultiType> {
86
86
  return (await this.redisClient.sendCommand(['XGROUP', 'CREATE', key, groupName, id, ...args])) === 1;
87
87
  } catch (error) {
88
88
  const streamType = mkStream === 'MKSTREAM' ? 'with MKSTREAM' : 'without MKSTREAM';
89
- this.logger.info(`x-group-error ${streamType} for key: ${key} and group: ${groupName}`, { error });
89
+ this.logger.debug(`x-group-error ${streamType} for key: ${key} and group: ${groupName}`, { error });
90
90
  throw error;
91
91
  }
92
92
  }
@@ -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
@@ -10,7 +10,7 @@ type WorkflowConfig = {
10
10
  type WorkflowSearchOptions = {
11
11
  index?: string; //FT index name (myapp:myindex)
12
12
  prefix?: string[]; //FT prefixes (['myapp:myindex:prefix1', 'myapp:myindex:prefix2'])
13
- schema?: Record<string, {type: 'TEXT' | 'NUMERIC' | 'TAG', sortable: boolean}>;
13
+ schema?: Record<string, {type: 'TEXT' | 'NUMERIC' | 'TAG', sortable?: boolean}>;
14
14
  data?: Record<string, string>;
15
15
  }
16
16
 
@@ -57,12 +57,27 @@ type WorkflowDataType = {
57
57
  workflowTopic: string;
58
58
  }
59
59
 
60
+ type MeshOSClassConfig = {
61
+ namespace: string;
62
+ taskQueue: string;
63
+ redisOptions: RedisOptions;
64
+ redisClass: RedisClass;
65
+ }
66
+
67
+ type MeshOSConfig = {
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;
@@ -76,11 +91,28 @@ type WorkerConfig = {
76
91
  connection: Connection;
77
92
  namespace?: string; //`appid` in the YAML (e.g, 'default')
78
93
  taskQueue: string; //`subscribes` in the YAML (e.g, 'hello-world')
79
- workflow: Function; //target function to run
94
+ workflow: Function | Record<string | symbol, Function>; //target function to run
80
95
  options?: WorkerOptions;
81
96
  search?: WorkflowSearchOptions;
82
97
  }
83
98
 
99
+ type FindOptions = {
100
+ workflowName?: string; //also the function name
101
+ taskQueue?: string;
102
+ namespace?: string;
103
+ index?: string; //the FT search index name
104
+ }
105
+
106
+ type MeshOSOptions = {
107
+ name: string;
108
+ options: WorkerOptions;
109
+ }
110
+
111
+ type MeshOSActivityOptions = {
112
+ name: string;
113
+ options: ActivityConfig;
114
+ }
115
+
84
116
  type WorkerOptions = {
85
117
  logLevel?: string; //debug, info, warn, error
86
118
  maxSystemRetries?: number; //1-3 (10ms, 100ms, 1_000ms)
@@ -115,11 +147,15 @@ export {
115
147
  ContextType,
116
148
  ConnectionConfig,
117
149
  Connection,
118
- NativeConnection,
119
150
  ProxyType,
120
151
  Registry,
121
152
  SignalOptions,
153
+ FindOptions,
122
154
  HookOptions,
155
+ MeshOSActivityOptions,
156
+ MeshOSClassConfig,
157
+ MeshOSConfig,
158
+ MeshOSOptions,
123
159
  WorkerConfig,
124
160
  WorkflowConfig,
125
161
  WorkerOptions,
package/types/index.ts CHANGED
@@ -34,10 +34,15 @@ export {
34
34
  ContextType,
35
35
  ConnectionConfig,
36
36
  Connection,
37
- NativeConnection,
38
37
  ProxyType,
39
38
  Registry,
39
+ SignalOptions,
40
+ FindOptions,
40
41
  HookOptions,
42
+ MeshOSActivityOptions,
43
+ MeshOSClassConfig,
44
+ MeshOSConfig,
45
+ MeshOSOptions,
41
46
  WorkflowConfig,
42
47
  WorkerConfig,
43
48
  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
- }