@hotmeshio/hotmesh 0.0.20 → 0.0.21

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "description": "Unbreakable Workflows",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -12,10 +12,9 @@ class Search {
12
12
  this.searchSessionIndex = 0;
13
13
  const keyParams = {
14
14
  appId: hotMeshClient.appId,
15
- jobId: ''
15
+ jobId: workflowId
16
16
  };
17
- const hotMeshPrefix = key_1.KeyService.mintKey(hotMeshClient.namespace, key_1.KeyType.JOB_STATE, keyParams);
18
- this.jobId = `${hotMeshPrefix}${workflowId}`;
17
+ this.jobId = key_1.KeyService.mintKey(hotMeshClient.namespace, key_1.KeyType.JOB_STATE, keyParams);
19
18
  this.searchSessionId = searchSessionId;
20
19
  this.hotMeshClient = hotMeshClient;
21
20
  this.store = hotMeshClient.engine.store;
@@ -3,9 +3,13 @@ import { HotMeshService as HotMesh } from '../hotmesh';
3
3
  import { ActivityConfig, HookOptions, ProxyType, WorkflowOptions } from "../../types/durable";
4
4
  export declare class WorkflowService {
5
5
  /**
6
- * Spawn a child workflow. await the result.
6
+ * Spawn a child workflow. await and return the result.
7
7
  */
8
8
  static executeChild<T>(options: WorkflowOptions): Promise<T>;
9
+ /**
10
+ * spawn a child workflow. return the childJobId.
11
+ */
12
+ static startChild<T>(options: WorkflowOptions): Promise<string>;
9
13
  static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT>;
10
14
  static search(): Promise<Search>;
11
15
  /**
@@ -16,37 +16,79 @@ const worker_1 = require("./worker");
16
16
  const stream_1 = require("../../types/stream");
17
17
  class WorkflowService {
18
18
  /**
19
- * Spawn a child workflow. await the result.
19
+ * Spawn a child workflow. await and return the result.
20
20
  */
21
21
  static async executeChild(options) {
22
22
  const store = asyncLocalStorage_1.asyncLocalStorage.getStore();
23
+ const namespace = store.get('namespace');
23
24
  const workflowId = store.get('workflowId');
24
25
  const workflowDimension = store.get('workflowDimension') ?? '';
25
26
  const workflowTrace = store.get('workflowTrace');
26
27
  const workflowSpan = store.get('workflowSpan');
27
28
  const COUNTER = store.get('counter');
28
29
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
29
- const childJobId = `${workflowId}-$${options.workflowName}${workflowDimension}-${execIndex}`;
30
+ //this is risky but MUST be allowed. Users MAY set the workflowId,
31
+ //but if there is a naming collision, the data from the target entity will be used
32
+ //as there is know way of knowing if the item was generated via a prior run of the workflow
33
+ const childJobId = options.workflowId ?? `${workflowId}-$${options.workflowName}${workflowDimension}-${execIndex}`;
30
34
  const parentWorkflowId = `${workflowId}-f`;
31
35
  const client = new client_1.ClientService({
32
36
  connection: await connection_1.ConnectionService.connect(worker_1.WorkerService.connection),
33
37
  });
34
- let handle = await client.workflow.getHandle(options.taskQueue, options.workflowName, childJobId);
38
+ let handle = await client.workflow.getHandle(options.taskQueue, options.workflowName, childJobId, namespace);
35
39
  try {
36
40
  return await handle.result(true);
37
41
  }
38
42
  catch (error) {
39
43
  handle = await client.workflow.start({
40
44
  ...options,
45
+ namespace,
41
46
  workflowId: childJobId,
42
47
  parentWorkflowId,
43
48
  workflowTrace,
44
49
  workflowSpan,
45
50
  });
51
+ //todo: options.startToCloseTimeout
46
52
  const result = await handle.result();
47
53
  return result;
48
54
  }
49
55
  }
56
+ /**
57
+ * spawn a child workflow. return the childJobId.
58
+ */
59
+ static async startChild(options) {
60
+ const store = asyncLocalStorage_1.asyncLocalStorage.getStore();
61
+ const namespace = store.get('namespace');
62
+ const workflowId = store.get('workflowId');
63
+ const workflowDimension = store.get('workflowDimension') ?? '';
64
+ const workflowTrace = store.get('workflowTrace');
65
+ const workflowSpan = store.get('workflowSpan');
66
+ const COUNTER = store.get('counter');
67
+ const execIndex = COUNTER.counter = COUNTER.counter + 1;
68
+ const childJobId = options.workflowId ?? `${workflowId}-$${options.workflowName}${workflowDimension}-${execIndex}`;
69
+ const parentWorkflowId = `${workflowId}-f`;
70
+ const workflowTopic = `${options.taskQueue}-${options.workflowName}`;
71
+ try {
72
+ //get the status; if there is no error, return childJobId (what was spawned)
73
+ const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, { namespace });
74
+ await hotMeshClient.getStatus(childJobId);
75
+ return childJobId;
76
+ }
77
+ catch (error) {
78
+ const client = new client_1.ClientService({
79
+ connection: await connection_1.ConnectionService.connect(worker_1.WorkerService.connection),
80
+ });
81
+ await client.workflow.start({
82
+ ...options,
83
+ namespace,
84
+ workflowId: childJobId,
85
+ parentWorkflowId,
86
+ workflowTrace,
87
+ workflowSpan,
88
+ });
89
+ return childJobId;
90
+ }
91
+ }
50
92
  static proxyActivities(options) {
51
93
  if (options.activities) {
52
94
  worker_1.WorkerService.registerActivities(options.activities);
@@ -18,7 +18,7 @@ type WorkflowOptions = {
18
18
  namespace?: string;
19
19
  taskQueue: string;
20
20
  args: any[];
21
- workflowId: string;
21
+ workflowId?: string;
22
22
  workflowName?: string;
23
23
  parentWorkflowId?: string;
24
24
  workflowTrace?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "description": "Unbreakable Workflows",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -19,10 +19,9 @@ export class Search {
19
19
  constructor(workflowId: string, hotMeshClient: HotMesh, searchSessionId: string) {
20
20
  const keyParams = {
21
21
  appId: hotMeshClient.appId,
22
- jobId: ''
22
+ jobId: workflowId
23
23
  }
24
- const hotMeshPrefix = KeyService.mintKey(hotMeshClient.namespace, KeyType.JOB_STATE, keyParams);
25
- this.jobId = `${hotMeshPrefix}${workflowId}`;
24
+ this.jobId = KeyService.mintKey(hotMeshClient.namespace, KeyType.JOB_STATE, keyParams);
26
25
  this.searchSessionId = searchSessionId;
27
26
  this.hotMeshClient = hotMeshClient;
28
27
  this.store = hotMeshClient.engine.store as StoreService<RedisClient, RedisMulti>;
@@ -23,17 +23,21 @@ import { StreamStatus } from '../../types/stream';
23
23
  export class WorkflowService {
24
24
 
25
25
  /**
26
- * Spawn a child workflow. await the result.
26
+ * Spawn a child workflow. await and return the result.
27
27
  */
28
28
  static async executeChild<T>(options: WorkflowOptions): Promise<T> {
29
29
  const store = asyncLocalStorage.getStore();
30
+ const namespace = store.get('namespace');
30
31
  const workflowId = store.get('workflowId');
31
32
  const workflowDimension = store.get('workflowDimension') ?? '';
32
33
  const workflowTrace = store.get('workflowTrace');
33
34
  const workflowSpan = store.get('workflowSpan');
34
35
  const COUNTER = store.get('counter');
35
36
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
36
- const childJobId = `${workflowId}-$${options.workflowName}${workflowDimension}-${execIndex}`;
37
+ //this is risky but MUST be allowed. Users MAY set the workflowId,
38
+ //but if there is a naming collision, the data from the target entity will be used
39
+ //as there is know way of knowing if the item was generated via a prior run of the workflow
40
+ const childJobId = options.workflowId ?? `${workflowId}-$${options.workflowName}${workflowDimension}-${execIndex}`;
37
41
  const parentWorkflowId = `${workflowId}-f`;
38
42
 
39
43
  const client = new Client({
@@ -43,7 +47,8 @@ export class WorkflowService {
43
47
  let handle = await client.workflow.getHandle(
44
48
  options.taskQueue,
45
49
  options.workflowName,
46
- childJobId
50
+ childJobId,
51
+ namespace,
47
52
  );
48
53
 
49
54
  try {
@@ -51,16 +56,56 @@ export class WorkflowService {
51
56
  } catch (error) {
52
57
  handle = await client.workflow.start({
53
58
  ...options,
59
+ namespace,
54
60
  workflowId: childJobId,
55
61
  parentWorkflowId,
56
62
  workflowTrace,
57
63
  workflowSpan,
58
64
  });
65
+ //todo: options.startToCloseTimeout
59
66
  const result = await handle.result();
60
67
  return result as T;
61
68
  }
62
69
  }
63
70
 
71
+ /**
72
+ * spawn a child workflow. return the childJobId.
73
+ */
74
+ static async startChild<T>(options: WorkflowOptions): Promise<string> {
75
+ const store = asyncLocalStorage.getStore();
76
+ const namespace = store.get('namespace');
77
+ const workflowId = store.get('workflowId');
78
+ const workflowDimension = store.get('workflowDimension') ?? '';
79
+ const workflowTrace = store.get('workflowTrace');
80
+ const workflowSpan = store.get('workflowSpan');
81
+ const COUNTER = store.get('counter');
82
+ const execIndex = COUNTER.counter = COUNTER.counter + 1;
83
+ const childJobId = options.workflowId ?? `${workflowId}-$${options.workflowName}${workflowDimension}-${execIndex}`;
84
+ const parentWorkflowId = `${workflowId}-f`;
85
+ const workflowTopic = `${options.taskQueue}-${options.workflowName}`;
86
+
87
+ try {
88
+ //get the status; if there is no error, return childJobId (what was spawned)
89
+ const hotMeshClient = await WorkerService.getHotMesh(workflowTopic, { namespace });
90
+ await hotMeshClient.getStatus(childJobId);
91
+ return childJobId;
92
+ } catch (error) {
93
+ const client = new Client({
94
+ connection: await Connection.connect(WorkerService.connection),
95
+ });
96
+
97
+ await client.workflow.start({
98
+ ...options,
99
+ namespace,
100
+ workflowId: childJobId,
101
+ parentWorkflowId,
102
+ workflowTrace,
103
+ workflowSpan,
104
+ });
105
+ return childJobId;
106
+ }
107
+ }
108
+
64
109
  static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT> {
65
110
  if (options.activities) {
66
111
  WorkerService.registerActivities(options.activities)
package/types/durable.ts CHANGED
@@ -18,7 +18,7 @@ type WorkflowOptions = {
18
18
  namespace?: string; //'durable' is the default namespace if not provided; similar to setting `appid` in the YAML
19
19
  taskQueue: string;
20
20
  args: any[]; //input arguments to pass in
21
- workflowId: string; //execution id (the job id)
21
+ workflowId?: string; //execution id (the job id)
22
22
  workflowName?: string; //the name of the user's workflow function
23
23
  parentWorkflowId?: string; //system reserved; the id of the parent; if present the flow will not self-clean until the parent that spawned it self-cleans
24
24
  workflowTrace?: string;