@hotmeshio/hotmesh 0.0.28 → 0.0.29
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.
- package/README.md +9 -9
- package/build/package.json +1 -1
- package/build/services/durable/client.js +3 -0
- package/build/services/durable/meshos.d.ts +8 -5
- package/build/services/durable/meshos.js +6 -3
- package/package.json +1 -1
- package/services/durable/client.ts +3 -0
- package/services/durable/meshos.ts +8 -5
package/README.md
CHANGED
|
@@ -17,9 +17,7 @@ npm install @hotmeshio/hotmesh
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Design
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
1. Start with any ordinary class. Pay attention to unpredictable functions: those that execute slowly, cause problems at scale, or simply fail to return. *Note how the `flaky` function throws an error 50% of the time. This is exactly the type of function that can be fixed using HotMesh.*
|
|
20
|
+
1. Start with any ordinary class. Pay attention to unpredictable functions: those that execute slowly, cause problems at scale, or simply fail to return now and then. *Note how the `flaky` function throws an error 50% of the time. This is exactly the type of function that can be fixed using HotMesh.*
|
|
23
21
|
```javascript
|
|
24
22
|
//myworkflow.ts
|
|
25
23
|
|
|
@@ -44,7 +42,7 @@ The HotMesh SDK is designed to keep your code front-and-center. Write code as yo
|
|
|
44
42
|
}
|
|
45
43
|
}
|
|
46
44
|
```
|
|
47
|
-
2. Import `Redis` and `MeshOS`
|
|
45
|
+
2. Import and configure `Redis` and `MeshOS` as shown. List those functions that Redis should govern as durable workflows (like `run` and `flaky`). And that's it! *Your functions don't actually change; rather, their governance does.*
|
|
48
46
|
```javascript
|
|
49
47
|
//myworkflow.ts
|
|
50
48
|
|
|
@@ -53,6 +51,7 @@ The HotMesh SDK is designed to keep your code front-and-center. Write code as yo
|
|
|
53
51
|
|
|
54
52
|
export class MyWorkflow extends MeshOS {
|
|
55
53
|
|
|
54
|
+
//configure Redis
|
|
56
55
|
redisClass = Redis;
|
|
57
56
|
redisOptions = { host: 'localhost', port: 6379 };
|
|
58
57
|
|
|
@@ -62,13 +61,14 @@ The HotMesh SDK is designed to keep your code front-and-center. Write code as yo
|
|
|
62
61
|
//list functions to retry and cache
|
|
63
62
|
proxyFunctions = ['flaky'];
|
|
64
63
|
|
|
64
|
+
//no need to change anything else!
|
|
65
|
+
|
|
65
66
|
async run(name: string): Promise<string> {
|
|
66
67
|
const hi = await this.flaky(name);
|
|
67
68
|
const hello = await this.greet(name);
|
|
68
69
|
return `${hi} ${hello}`;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
//this function is now durable and will be retried until it succeeds!
|
|
72
72
|
async flaky(name: string): Promise<string> {
|
|
73
73
|
if (Math.random() < 0.5) {
|
|
74
74
|
throw new Error('Ooops!');
|
|
@@ -81,7 +81,7 @@ The HotMesh SDK is designed to keep your code front-and-center. Write code as yo
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
```
|
|
84
|
-
3. Invoke your class, providing a unique id (it's now an idempotent workflow and needs a GUID). Nothing changes from the outside, *but Redis now governs the end-to-end execution.* It's guaranteed to succeed, even if it
|
|
84
|
+
3. Invoke your class, providing a unique id (it's now an idempotent workflow and needs a GUID). Nothing changes from the outside, *but Redis now governs the end-to-end execution.* It's guaranteed to succeed, even if it breaks a few times along the way.
|
|
85
85
|
```javascript
|
|
86
86
|
//mycaller.ts
|
|
87
87
|
|
|
@@ -90,11 +90,11 @@ The HotMesh SDK is designed to keep your code front-and-center. Write code as yo
|
|
|
90
90
|
//Hi, World! Hello, World!
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
Redis governance delivers more than just reliability. Externalizing state fundamentally changes the execution profile for your functions, allowing you to design long-running, durable workflows.
|
|
93
|
+
Redis governance delivers more than just reliability. Externalizing state fundamentally changes the execution profile for your functions, allowing you to design long-running, durable workflows. The `MeshOS` base class (shown in the examples above) provides additional methods for solving the most common state management challenges.
|
|
94
94
|
|
|
95
|
-
- `waitForSignal` | Pause and wait for external event(s) before continuing. The *waitForSignal* method will collate and cache the signals and only awaken your function once they've all arrived.
|
|
95
|
+
- `waitForSignal` | Pause your function and wait for external event(s) before continuing. The *waitForSignal* method will collate and cache the signals and only awaken your function once they've all arrived.
|
|
96
96
|
- `signal` | Send a signal (and optional payload) to any paused function.
|
|
97
|
-
- `hook` | Redis governance
|
|
97
|
+
- `hook` | Redis governance converts your functions into 're-entrant processes'. Optionally use the *hook* method to spawn parallel execution threads to augment a running workflow.
|
|
98
98
|
- `sleep` | Pause function execution for a ridiculous amount of time (months, years, etc). There's no risk of information loss, as Redis governs function state. When your function awakens, function state is efficiently (and automatically) restored.
|
|
99
99
|
- `random` | Generate a deterministic random number that can be used in a reentrant process workflow (replaces `Math.random()`).
|
|
100
100
|
- `executeChild` | Call another durable function and await the response. *Design sophisticated, multi-process solutions by leveraging this command.*
|
package/build/package.json
CHANGED
|
@@ -70,6 +70,9 @@ class ClientService {
|
|
|
70
70
|
};
|
|
71
71
|
this.search = async (hotMeshClient, index, query) => {
|
|
72
72
|
const store = hotMeshClient.engine.store;
|
|
73
|
+
if (query[0]?.startsWith('FT.')) {
|
|
74
|
+
return await store.exec(...query);
|
|
75
|
+
}
|
|
73
76
|
return await store.exec('FT.SEARCH', index, ...query);
|
|
74
77
|
};
|
|
75
78
|
this.workflow = {
|
|
@@ -91,19 +91,22 @@ export declare class MeshOSService {
|
|
|
91
91
|
*/
|
|
92
92
|
static startWorkers(options?: MeshOSWorkerOptions): Promise<void>;
|
|
93
93
|
/**
|
|
94
|
-
* executes the redis FT search query
|
|
94
|
+
* executes the redis FT search query; optionally specify other commands
|
|
95
95
|
* @example '@_quantity:[89 89]'
|
|
96
|
+
* @example '@_quantity:[89 89] @_name:"John"'
|
|
97
|
+
* @example 'FT.search my-index @_quantity:[89 89]'
|
|
98
|
+
* @param {FindOptions} options
|
|
96
99
|
* @param {any[]} args
|
|
97
|
-
* @returns {string}
|
|
100
|
+
* @returns {Promise<string[] | [number] | Array<number, string | number | string[]>>}
|
|
98
101
|
*/
|
|
99
|
-
static find(options: FindOptions, ...args: string[]): Promise<string[] | [number]
|
|
102
|
+
static find(options: FindOptions, ...args: string[]): Promise<string[] | [number] | Array<string | number | string[]>>;
|
|
100
103
|
/**
|
|
101
104
|
* Provides a JSON abstraction for the Redis FT.search command
|
|
102
105
|
* (e.g, `count`, `query`, `return`, `limit`)
|
|
103
106
|
* @param {FindWhereOptions} options
|
|
104
|
-
* @returns {Promise<string[] | [number]
|
|
107
|
+
* @returns {Promise<string[] | [number] | Array<string | number | string[]>>}
|
|
105
108
|
*/
|
|
106
|
-
static findWhere(options: FindWhereOptions): Promise<string[] | [number]
|
|
109
|
+
static findWhere(options: FindWhereOptions): Promise<string[] | [number] | Array<string | number | string[]>>;
|
|
107
110
|
static generateSearchQuery(query: FindWhereQuery[]): string;
|
|
108
111
|
/**
|
|
109
112
|
* returns the workflow handle. The handle can then be
|
|
@@ -140,10 +140,13 @@ class MeshOSService {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
/**
|
|
143
|
-
* executes the redis FT search query
|
|
143
|
+
* executes the redis FT search query; optionally specify other commands
|
|
144
144
|
* @example '@_quantity:[89 89]'
|
|
145
|
+
* @example '@_quantity:[89 89] @_name:"John"'
|
|
146
|
+
* @example 'FT.search my-index @_quantity:[89 89]'
|
|
147
|
+
* @param {FindOptions} options
|
|
145
148
|
* @param {any[]} args
|
|
146
|
-
* @returns {string}
|
|
149
|
+
* @returns {Promise<string[] | [number] | Array<number, string | number | string[]>>}
|
|
147
150
|
*/
|
|
148
151
|
static async find(options, ...args) {
|
|
149
152
|
const my = new this();
|
|
@@ -170,7 +173,7 @@ class MeshOSService {
|
|
|
170
173
|
* Provides a JSON abstraction for the Redis FT.search command
|
|
171
174
|
* (e.g, `count`, `query`, `return`, `limit`)
|
|
172
175
|
* @param {FindWhereOptions} options
|
|
173
|
-
* @returns {Promise<string[] | [number]
|
|
176
|
+
* @returns {Promise<string[] | [number] | Array<string | number | string[]>>}
|
|
174
177
|
*/
|
|
175
178
|
static async findWhere(options) {
|
|
176
179
|
const args = [this.generateSearchQuery(options.query)];
|
package/package.json
CHANGED
|
@@ -85,6 +85,9 @@ export class ClientService {
|
|
|
85
85
|
|
|
86
86
|
search = async (hotMeshClient: HotMesh, index: string, query: string[]): Promise<string[]> => {
|
|
87
87
|
const store = hotMeshClient.engine.store;
|
|
88
|
+
if (query[0]?.startsWith('FT.')) {
|
|
89
|
+
return await store.exec(...query) as string[];
|
|
90
|
+
}
|
|
88
91
|
return await store.exec('FT.SEARCH', index, ...query) as string[];
|
|
89
92
|
}
|
|
90
93
|
|
|
@@ -236,12 +236,15 @@ export class MeshOSService {
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
/**
|
|
239
|
-
* executes the redis FT search query
|
|
239
|
+
* executes the redis FT search query; optionally specify other commands
|
|
240
240
|
* @example '@_quantity:[89 89]'
|
|
241
|
+
* @example '@_quantity:[89 89] @_name:"John"'
|
|
242
|
+
* @example 'FT.search my-index @_quantity:[89 89]'
|
|
243
|
+
* @param {FindOptions} options
|
|
241
244
|
* @param {any[]} args
|
|
242
|
-
* @returns {string}
|
|
245
|
+
* @returns {Promise<string[] | [number] | Array<number, string | number | string[]>>}
|
|
243
246
|
*/
|
|
244
|
-
static async find(options: FindOptions, ...args: string[]): Promise<string[] | [number]
|
|
247
|
+
static async find(options: FindOptions, ...args: string[]): Promise<string[] | [number] | Array<string | number | string[]>> {
|
|
245
248
|
const my = new this();
|
|
246
249
|
const client = new Client({ connection: {
|
|
247
250
|
class: my.redisClass,
|
|
@@ -272,9 +275,9 @@ export class MeshOSService {
|
|
|
272
275
|
* Provides a JSON abstraction for the Redis FT.search command
|
|
273
276
|
* (e.g, `count`, `query`, `return`, `limit`)
|
|
274
277
|
* @param {FindWhereOptions} options
|
|
275
|
-
* @returns {Promise<string[] | [number]
|
|
278
|
+
* @returns {Promise<string[] | [number] | Array<string | number | string[]>>}
|
|
276
279
|
*/
|
|
277
|
-
static async findWhere(options: FindWhereOptions): Promise<string[] | [number]
|
|
280
|
+
static async findWhere(options: FindWhereOptions): Promise<string[] | [number] | Array<string | number | string[]>> {
|
|
278
281
|
const args: string[] = [this.generateSearchQuery(options.query)];
|
|
279
282
|
if (options.count) {
|
|
280
283
|
args.push('LIMIT', '0', '0');
|