@hotmeshio/hotmesh 0.0.59 → 0.1.0
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 +1 -1
- package/build/modules/enums.d.ts +2 -1
- package/build/modules/enums.js +13 -3
- package/build/modules/errors.d.ts +3 -3
- package/build/modules/errors.js +8 -8
- package/build/modules/key.d.ts +1 -1
- package/build/modules/key.js +3 -3
- package/build/modules/utils.d.ts +6 -6
- package/build/modules/utils.js +22 -14
- package/build/package.json +41 -38
- package/build/services/activities/activity.js +37 -20
- package/build/services/activities/await.d.ts +1 -1
- package/build/services/activities/await.js +15 -7
- package/build/services/activities/cycle.d.ts +1 -1
- package/build/services/activities/cycle.js +16 -8
- package/build/services/activities/hook.d.ts +1 -1
- package/build/services/activities/hook.js +8 -4
- package/build/services/activities/interrupt.d.ts +1 -1
- package/build/services/activities/interrupt.js +14 -6
- package/build/services/activities/signal.d.ts +1 -1
- package/build/services/activities/signal.js +12 -4
- package/build/services/activities/trigger.d.ts +1 -1
- package/build/services/activities/trigger.js +19 -12
- package/build/services/activities/worker.d.ts +1 -1
- package/build/services/activities/worker.js +15 -7
- package/build/services/collator/index.js +12 -12
- package/build/services/compiler/deployer.js +17 -12
- package/build/services/compiler/index.js +4 -4
- package/build/services/compiler/validator.d.ts +3 -3
- package/build/services/compiler/validator.js +12 -3
- package/build/services/durable/client.d.ts +1 -1
- package/build/services/durable/client.js +18 -12
- package/build/services/durable/connection.d.ts +1 -1
- package/build/services/durable/exporter.d.ts +1 -1
- package/build/services/durable/exporter.js +3 -4
- package/build/services/durable/handle.d.ts +1 -1
- package/build/services/durable/handle.js +4 -1
- package/build/services/durable/index.d.ts +1 -1
- package/build/services/durable/index.js +2 -2
- package/build/services/durable/schemas/factory.d.ts +1 -1
- package/build/services/durable/search.js +19 -11
- package/build/services/durable/worker.js +50 -30
- package/build/services/durable/workflow.d.ts +5 -5
- package/build/services/durable/workflow.js +34 -18
- package/build/services/engine/index.js +33 -26
- package/build/services/exporter/index.d.ts +1 -1
- package/build/services/exporter/index.js +3 -3
- package/build/services/hotmesh/index.js +1 -1
- package/build/services/logger/index.js +1 -1
- package/build/services/mapper/index.js +3 -1
- package/build/services/pipe/functions/date.js +1 -1
- package/build/services/pipe/index.js +37 -10
- package/build/services/quorum/index.js +14 -11
- package/build/services/reporter/index.js +15 -12
- package/build/services/router/index.d.ts +2 -2
- package/build/services/router/index.js +73 -23
- package/build/services/serializer/index.js +48 -26
- package/build/services/store/cache.d.ts +5 -5
- package/build/services/store/cache.js +2 -2
- package/build/services/store/clients/ioredis.js +3 -3
- package/build/services/store/clients/redis.js +24 -4
- package/build/services/store/index.d.ts +9 -3
- package/build/services/store/index.js +122 -60
- package/build/services/stream/clients/ioredis.js +4 -4
- package/build/services/stream/clients/redis.js +31 -4
- package/build/services/task/index.js +8 -11
- package/build/services/telemetry/index.js +21 -14
- package/build/services/worker/index.d.ts +6 -6
- package/build/services/worker/index.js +12 -7
- package/build/types/activity.d.ts +3 -3
- package/build/types/exporter.d.ts +2 -2
- package/build/types/exporter.js +0 -6
- package/build/types/hook.d.ts +1 -1
- package/build/types/hotmesh.js +0 -1
- package/build/types/index.d.ts +12 -12
- package/build/types/job.d.ts +1 -1
- package/build/types/logger.js +0 -1
- package/build/types/quorum.d.ts +1 -1
- package/build/types/stats.d.ts +1 -1
- package/build/types/stream.d.ts +1 -2
- package/build/types/telemetry.d.ts +1 -1
- package/build/types/transition.d.ts +1 -1
- package/package.json +41 -38
- package/types/activity.ts +56 -39
- package/types/async.ts +2 -3
- package/types/collator.ts +5 -5
- package/types/durable.ts +161 -161
- package/types/error.ts +37 -37
- package/types/exporter.ts +14 -9
- package/types/hook.ts +11 -4
- package/types/hotmesh.ts +26 -25
- package/types/index.ts +53 -53
- package/types/job.ts +33 -33
- package/types/logger.ts +1 -1
- package/types/map.ts +1 -1
- package/types/pipe.ts +10 -8
- package/types/quorum.ts +20 -13
- package/types/redis.ts +70 -15
- package/types/serializer.ts +8 -6
- package/types/stats.ts +22 -6
- package/types/stream.ts +9 -9
- package/types/task.ts +7 -1
- package/types/telemetry.ts +2 -1
- package/types/transition.ts +8 -8
|
@@ -60,7 +60,8 @@ class TelemetryService {
|
|
|
60
60
|
else if (role === stream_1.StreamRole.WORKER) {
|
|
61
61
|
type = 'EXECUTE';
|
|
62
62
|
}
|
|
63
|
-
else if (data.type === stream_1.StreamDataType.RESULT ||
|
|
63
|
+
else if (data.type === stream_1.StreamDataType.RESULT ||
|
|
64
|
+
data.type === stream_1.StreamDataType.RESPONSE) {
|
|
64
65
|
type = 'FANIN';
|
|
65
66
|
}
|
|
66
67
|
else {
|
|
@@ -77,7 +78,7 @@ class TelemetryService {
|
|
|
77
78
|
this.traceId = traceId;
|
|
78
79
|
this.spanId = spanId;
|
|
79
80
|
const tracer = telemetry_1.trace.getTracer(package_json_1.default.name, package_json_1.default.version);
|
|
80
|
-
|
|
81
|
+
const parentContext = this.getParentSpanContext();
|
|
81
82
|
const span = tracer.startSpan(spanName, { kind: telemetry_1.SpanKind.CLIENT, attributes, root: !parentContext }, parentContext);
|
|
82
83
|
return span;
|
|
83
84
|
}
|
|
@@ -91,7 +92,7 @@ class TelemetryService {
|
|
|
91
92
|
result[`app.activity.data.${key}`] = telemetryAtts[key];
|
|
92
93
|
}
|
|
93
94
|
return result;
|
|
94
|
-
}, {})
|
|
95
|
+
}, {}),
|
|
95
96
|
};
|
|
96
97
|
this.span?.setAttributes(namespacedAtts);
|
|
97
98
|
}
|
|
@@ -144,7 +145,6 @@ class TelemetryService {
|
|
|
144
145
|
'app.activity.leg': leg,
|
|
145
146
|
};
|
|
146
147
|
}
|
|
147
|
-
;
|
|
148
148
|
getStreamSpanAttrs(input) {
|
|
149
149
|
return {
|
|
150
150
|
...Object.keys(input.metadata).reduce((result, key) => {
|
|
@@ -152,10 +152,9 @@ class TelemetryService {
|
|
|
152
152
|
result[`app.stream.${key}`] = input.metadata[key];
|
|
153
153
|
}
|
|
154
154
|
return result;
|
|
155
|
-
}, {})
|
|
155
|
+
}, {}),
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
|
-
;
|
|
159
158
|
setTelemetryContext(span, leg) {
|
|
160
159
|
if (!this.context.metadata.trc) {
|
|
161
160
|
this.context.metadata.trc = span.spanContext().traceId;
|
|
@@ -208,22 +207,30 @@ class TelemetryService {
|
|
|
208
207
|
static bindActivityTelemetryToState(state, config, metadata, context, leg) {
|
|
209
208
|
if (config.type === 'trigger') {
|
|
210
209
|
//trigger activities run non-duplexed and only have a single leg (2)
|
|
211
|
-
state[`${metadata.aid}/output/metadata/l1s`] =
|
|
212
|
-
|
|
210
|
+
state[`${metadata.aid}/output/metadata/l1s`] =
|
|
211
|
+
context['$self'].output.metadata.l1s;
|
|
212
|
+
state[`${metadata.aid}/output/metadata/l2s`] =
|
|
213
|
+
context['$self'].output.metadata.l2s;
|
|
213
214
|
}
|
|
214
|
-
else if (utils_1.polyfill.resolveActivityType(config.type) === 'hook' &&
|
|
215
|
+
else if (utils_1.polyfill.resolveActivityType(config.type) === 'hook' &&
|
|
216
|
+
leg === 1) {
|
|
215
217
|
//hook activities run non-duplexed and only have a single leg (1)
|
|
216
|
-
state[`${metadata.aid}/output/metadata/l1s`] =
|
|
217
|
-
|
|
218
|
+
state[`${metadata.aid}/output/metadata/l1s`] =
|
|
219
|
+
context['$self'].output.metadata.l1s;
|
|
220
|
+
state[`${metadata.aid}/output/metadata/l2s`] =
|
|
221
|
+
context['$self'].output.metadata.l1s;
|
|
218
222
|
}
|
|
219
223
|
else if (config.type === 'signal' && leg === 1) {
|
|
220
224
|
//signal activities run non-duplexed and only have a single leg (1)
|
|
221
|
-
state[`${metadata.aid}/output/metadata/l1s`] =
|
|
222
|
-
|
|
225
|
+
state[`${metadata.aid}/output/metadata/l1s`] =
|
|
226
|
+
context['$self'].output.metadata.l1s;
|
|
227
|
+
state[`${metadata.aid}/output/metadata/l2s`] =
|
|
228
|
+
context['$self'].output.metadata.l1s;
|
|
223
229
|
}
|
|
224
230
|
else {
|
|
225
231
|
const target = `l${leg}s`;
|
|
226
|
-
state[`${metadata.aid}/output/metadata/${target}`] =
|
|
232
|
+
state[`${metadata.aid}/output/metadata/${target}`] =
|
|
233
|
+
context['$self'].output.metadata[target];
|
|
227
234
|
}
|
|
228
235
|
}
|
|
229
236
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { ILogger } from
|
|
3
|
-
import { Router } from
|
|
2
|
+
import { ILogger } from '../logger';
|
|
3
|
+
import { Router } from '../router';
|
|
4
4
|
import { StoreService } from '../store';
|
|
5
5
|
import { StreamService } from '../stream';
|
|
6
6
|
import { SubService } from '../sub';
|
|
7
|
-
import { HotMeshConfig, HotMeshWorker } from
|
|
8
|
-
import { RollCallMessage, SubscriptionCallback } from
|
|
9
|
-
import { RedisClient, RedisMulti } from
|
|
10
|
-
import { StreamData, StreamDataResponse } from
|
|
7
|
+
import { HotMeshConfig, HotMeshWorker } from '../../types/hotmesh';
|
|
8
|
+
import { RollCallMessage, SubscriptionCallback } from '../../types/quorum';
|
|
9
|
+
import { RedisClient, RedisMulti } from '../../types/redis';
|
|
10
|
+
import { StreamData, StreamDataResponse } from '../../types/stream';
|
|
11
11
|
declare class WorkerService {
|
|
12
12
|
namespace: string;
|
|
13
13
|
appId: string;
|
|
@@ -38,7 +38,10 @@ class WorkerService {
|
|
|
38
38
|
await service.subscribe.subscribe(key_1.KeyType.QUORUM, service.subscriptionHandler(), appId, service.guid);
|
|
39
39
|
await service.initStreamChannel(service, worker.stream);
|
|
40
40
|
service.router = service.initRouter(worker, logger);
|
|
41
|
-
const key = service.stream.mintKey(key_1.KeyType.STREAMS, {
|
|
41
|
+
const key = service.stream.mintKey(key_1.KeyType.STREAMS, {
|
|
42
|
+
appId: service.appId,
|
|
43
|
+
topic: worker.topic,
|
|
44
|
+
});
|
|
42
45
|
await service.router.consumeMessages(key, 'WORKER', service.guid, worker.callback);
|
|
43
46
|
service.inited = (0, utils_1.formatISODate)(new Date());
|
|
44
47
|
services.push(service);
|
|
@@ -47,9 +50,9 @@ class WorkerService {
|
|
|
47
50
|
return services;
|
|
48
51
|
}
|
|
49
52
|
verifyWorkerFields(worker) {
|
|
50
|
-
if (
|
|
53
|
+
if (!(0, utils_1.identifyRedisType)(worker.store) ||
|
|
51
54
|
!(0, utils_1.identifyRedisType)(worker.stream) ||
|
|
52
|
-
!(0, utils_1.identifyRedisType)(worker.sub)
|
|
55
|
+
!(0, utils_1.identifyRedisType)(worker.sub) ||
|
|
53
56
|
!(worker.topic && worker.callback)) {
|
|
54
57
|
throw new Error('worker must include `store`, `stream`, and `sub` fields along with a callback function and topic.');
|
|
55
58
|
}
|
|
@@ -97,7 +100,8 @@ class WorkerService {
|
|
|
97
100
|
return async (topic, message) => {
|
|
98
101
|
self.logger.debug('worker-event-received', { topic, type: message.type });
|
|
99
102
|
if (message.type === 'throttle') {
|
|
100
|
-
if (message.topic !== null) {
|
|
103
|
+
if (message.topic !== null) {
|
|
104
|
+
//undefined allows passthrough
|
|
101
105
|
self.throttle(message.throttle);
|
|
102
106
|
}
|
|
103
107
|
}
|
|
@@ -105,7 +109,8 @@ class WorkerService {
|
|
|
105
109
|
self.sayPong(self.appId, self.guid, message.originator, message.details);
|
|
106
110
|
}
|
|
107
111
|
else if (message.type === 'rollcall') {
|
|
108
|
-
if (message.topic !== null) {
|
|
112
|
+
if (message.topic !== null) {
|
|
113
|
+
//undefined allows passthrough
|
|
109
114
|
self.doRollCall(message);
|
|
110
115
|
}
|
|
111
116
|
}
|
|
@@ -117,10 +122,10 @@ class WorkerService {
|
|
|
117
122
|
*/
|
|
118
123
|
async doRollCall(message) {
|
|
119
124
|
let iteration = 0;
|
|
120
|
-
|
|
125
|
+
const max = !isNaN(message.max) ? message.max : enums_1.HMSH_QUORUM_ROLLCALL_CYCLES;
|
|
121
126
|
if (this.rollCallInterval)
|
|
122
127
|
clearTimeout(this.rollCallInterval);
|
|
123
|
-
const base =
|
|
128
|
+
const base = message.interval / 2;
|
|
124
129
|
const amount = base + Math.ceil(Math.random() * base);
|
|
125
130
|
do {
|
|
126
131
|
await (0, utils_1.sleepFor)(Math.ceil(Math.random() * 1000));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MetricTypes } from
|
|
2
|
-
import { StreamRetryPolicy } from
|
|
1
|
+
import { MetricTypes } from './stats';
|
|
2
|
+
import { StreamRetryPolicy } from './stream';
|
|
3
3
|
type ActivityExecutionType = 'trigger' | 'await' | 'worker' | 'activity' | 'emit' | 'interrupt' | 'cycle' | 'signal' | 'hook';
|
|
4
4
|
type Consumes = Record<string, string[]>;
|
|
5
5
|
interface BaseActivity {
|
|
@@ -194,4 +194,4 @@ type ActivityDataType = {
|
|
|
194
194
|
hook?: Record<string, unknown>;
|
|
195
195
|
};
|
|
196
196
|
type ActivityLeg = 1 | 2;
|
|
197
|
-
export { ActivityContext, ActivityData, ActivityDataType, ActivityDuplex, ActivityLeg, ActivityMetadata, ActivityType, Consumes, TriggerActivityStats, AwaitActivity, CycleActivity, HookActivity, SignalActivity, BaseActivity, InterruptActivity, TriggerActivity, WorkerActivity };
|
|
197
|
+
export { ActivityContext, ActivityData, ActivityDataType, ActivityDuplex, ActivityLeg, ActivityMetadata, ActivityType, Consumes, TriggerActivityStats, AwaitActivity, CycleActivity, HookActivity, SignalActivity, BaseActivity, InterruptActivity, TriggerActivity, WorkerActivity, };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StringAnyType } from
|
|
2
|
-
export type ExportItem = [
|
|
1
|
+
import { StringAnyType } from './serializer';
|
|
2
|
+
export type ExportItem = [string | null, string, any];
|
|
3
3
|
/**
|
|
4
4
|
* job export data can be large, particularly transitions the timeline
|
|
5
5
|
*/
|
package/build/types/exporter.js
CHANGED
package/build/types/hook.d.ts
CHANGED
|
@@ -28,4 +28,4 @@ interface HookInterface {
|
|
|
28
28
|
id: string;
|
|
29
29
|
}): Promise<void>;
|
|
30
30
|
}
|
|
31
|
-
export { HookCondition, HookConditions, HookGate, HookInterface, HookRule, HookRules, HookSignal };
|
|
31
|
+
export { HookCondition, HookConditions, HookGate, HookInterface, HookRule, HookRules, HookSignal, };
|
package/build/types/hotmesh.js
CHANGED
package/build/types/index.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
export { ActivityType, ActivityDataType, ActivityContext, ActivityData, ActivityDuplex, ActivityLeg, ActivityMetadata, Consumes, AwaitActivity, BaseActivity, CycleActivity, HookActivity, WorkerActivity, InterruptActivity, SignalActivity, TriggerActivity, TriggerActivityStats } from './activity';
|
|
1
|
+
export { ActivityType, ActivityDataType, ActivityContext, ActivityData, ActivityDuplex, ActivityLeg, ActivityMetadata, Consumes, AwaitActivity, BaseActivity, CycleActivity, HookActivity, WorkerActivity, InterruptActivity, SignalActivity, TriggerActivity, TriggerActivityStats, } from './activity';
|
|
2
2
|
export { App, AppVID, AppTransitions, AppSubscriptions } from './app';
|
|
3
3
|
export { AsyncSignal } from './async';
|
|
4
4
|
export { CacheMode } from './cache';
|
|
5
5
|
export { CollationFaultType, CollationStage } from './collator';
|
|
6
6
|
export { ActivityConfig, ActivityWorkflowDataType, ChildResponseType, ClientConfig, ContextType, ConnectionConfig, Connection, ProxyResponseType, ProxyType, Registry, SignalOptions, FindJobsOptions, FindOptions, FindWhereOptions, FindWhereQuery, HookOptions, SearchResults, WorkflowConfig, WorkerConfig, WorkerOptions, WorkflowContext, WorkflowSearchOptions, WorkflowDataType, WorkflowOptions, } from './durable';
|
|
7
|
-
export { DurableChildErrorType, DurableProxyErrorType, DurableSleepErrorType, DurableWaitForAllErrorType, DurableWaitForErrorType } from
|
|
8
|
-
export { ActivityAction, DependencyExport, DurableJobExport, ExportCycles, ExportItem, ExportOptions, ExportTransitions, JobAction, JobExport, JobActionExport, JobTimeline } from './exporter';
|
|
9
|
-
export { HookCondition, HookConditions, HookGate, HookInterface, HookRule, HookRules, HookSignal } from './hook';
|
|
7
|
+
export { DurableChildErrorType, DurableProxyErrorType, DurableSleepErrorType, DurableWaitForAllErrorType, DurableWaitForErrorType, } from './error';
|
|
8
|
+
export { ActivityAction, DependencyExport, DurableJobExport, ExportCycles, ExportItem, ExportOptions, ExportTransitions, JobAction, JobExport, JobActionExport, JobTimeline, } from './exporter';
|
|
9
|
+
export { HookCondition, HookConditions, HookGate, HookInterface, HookRule, HookRules, HookSignal, } from './hook';
|
|
10
10
|
export { ILogger } from './logger';
|
|
11
|
-
export { ExtensionType, JobCompletionOptions, JobData, JobsData, JobInterruptOptions, JobMetadata, JobOutput, JobState, JobStatus, PartialJobState } from './job';
|
|
11
|
+
export { ExtensionType, JobCompletionOptions, JobData, JobsData, JobInterruptOptions, JobMetadata, JobOutput, JobState, JobStatus, PartialJobState, } from './job';
|
|
12
12
|
export { MappingStatements } from './map';
|
|
13
|
-
export { Pipe, PipeContext, PipeItem, PipeItems, PipeObject, ReduceObject } from './pipe';
|
|
14
|
-
export { HotMesh, HotMeshApp, HotMeshApps, HotMeshConfig, HotMeshEngine, RedisConfig, HotMeshGraph, HotMeshManifest, HotMeshSettings, HotMeshWorker, KeyStoreParams, KeyType } from './hotmesh';
|
|
15
|
-
export { ActivateMessage, CronMessage, JobMessage, JobMessageCallback, PingMessage, PongMessage, QuorumMessage, QuorumMessageCallback, QuorumProfile, RollCallMessage, RollCallOptions, SubscriptionCallback, SubscriptionOptions, SystemHealth, ThrottleMessage, ThrottleOptions, WorkMessage } from './quorum';
|
|
13
|
+
export { Pipe, PipeContext, PipeItem, PipeItems, PipeObject, ReduceObject, } from './pipe';
|
|
14
|
+
export { HotMesh, HotMeshApp, HotMeshApps, HotMeshConfig, HotMeshEngine, RedisConfig, HotMeshGraph, HotMeshManifest, HotMeshSettings, HotMeshWorker, KeyStoreParams, KeyType, } from './hotmesh';
|
|
15
|
+
export { ActivateMessage, CronMessage, JobMessage, JobMessageCallback, PingMessage, PongMessage, QuorumMessage, QuorumMessageCallback, QuorumProfile, RollCallMessage, RollCallOptions, SubscriptionCallback, SubscriptionOptions, SystemHealth, ThrottleMessage, ThrottleOptions, WorkMessage, } from './quorum';
|
|
16
16
|
export { RedisClass, RedisRedisClientType, RedisRedisClientOptions, RedisRedisClassType, IORedisClientType, RedisClient, RedisMulti, RedisRedisMultiType, IORedisClientOptions, IORedisClassType, IORedisMultiType, RedisOptions, MultiResponseFlags, isRedisClient, isIORedisClient, } from './redis';
|
|
17
|
-
export { JSONSchema, StringAnyType, StringScalarType, StringStringType, SymbolMap, SymbolMaps, SymbolRanges, Symbols, SymbolSets } from './serializer';
|
|
18
|
-
export { AggregatedData, CountByFacet, GetStatsOptions, IdsData, Measure, MeasureIds, MetricTypes, StatType, StatsType, IdsResponse, JobStats, JobStatsInput, JobStatsRange, StatsResponse, Segment, TimeSegment } from './stats';
|
|
19
|
-
export { ReclaimedMessageType, StreamCode, StreamConfig, StreamData, StreamDataType, StreamError, StreamDataResponse, StreamRetryPolicy, StreamRole, StreamStatus } from './stream';
|
|
20
|
-
export { context, Context, Counter, Meter, metrics, propagation, SpanContext, Span, SpanStatus, SpanStatusCode, SpanKind, trace, Tracer, ValueType } from './telemetry';
|
|
17
|
+
export { JSONSchema, StringAnyType, StringScalarType, StringStringType, SymbolMap, SymbolMaps, SymbolRanges, Symbols, SymbolSets, } from './serializer';
|
|
18
|
+
export { AggregatedData, CountByFacet, GetStatsOptions, IdsData, Measure, MeasureIds, MetricTypes, StatType, StatsType, IdsResponse, JobStats, JobStatsInput, JobStatsRange, StatsResponse, Segment, TimeSegment, } from './stats';
|
|
19
|
+
export { ReclaimedMessageType, StreamCode, StreamConfig, StreamData, StreamDataType, StreamError, StreamDataResponse, StreamRetryPolicy, StreamRole, StreamStatus, } from './stream';
|
|
20
|
+
export { context, Context, Counter, Meter, metrics, propagation, SpanContext, Span, SpanStatus, SpanStatusCode, SpanKind, trace, Tracer, ValueType, } from './telemetry';
|
|
21
21
|
export { WorkListTaskType } from './task';
|
|
22
22
|
export { TransitionMatch, TransitionRule, Transitions } from './transition';
|
package/build/types/job.d.ts
CHANGED
package/build/types/logger.js
CHANGED
package/build/types/quorum.d.ts
CHANGED
package/build/types/stats.d.ts
CHANGED
|
@@ -81,4 +81,4 @@ interface IdsResponse {
|
|
|
81
81
|
counts: CountByFacet[];
|
|
82
82
|
segments: TimeSegment[];
|
|
83
83
|
}
|
|
84
|
-
export { StatsType, StatType, MetricTypes, JobStats, JobStatsRange, JobStatsInput, GetStatsOptions, StatsResponse, AggregatedData, Measure, Segment, IdsData, MeasureIds, TimeSegment, IdsResponse, CountByFacet };
|
|
84
|
+
export { StatsType, StatType, MetricTypes, JobStats, JobStatsRange, JobStatsInput, GetStatsOptions, StatsResponse, AggregatedData, Measure, Segment, IdsData, MeasureIds, TimeSegment, IdsResponse, CountByFacet, };
|
package/build/types/stream.d.ts
CHANGED
|
@@ -91,8 +91,7 @@ export interface StreamData {
|
|
|
91
91
|
stack?: string;
|
|
92
92
|
}
|
|
93
93
|
/** Extends StreamData for responses, allowing for inheritance of the base properties */
|
|
94
|
-
export
|
|
95
|
-
}
|
|
94
|
+
export type StreamDataResponse = StreamData;
|
|
96
95
|
export declare enum StreamRole {
|
|
97
96
|
WORKER = "worker",
|
|
98
97
|
ENGINE = "engine",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { context, Context, Counter, Meter, metrics, propagation, SpanContext, Span, SpanStatus, SpanStatusCode, SpanKind, trace, Tracer, ValueType } from '@opentelemetry/api';
|
|
1
|
+
export { context, Context, Counter, Meter, metrics, propagation, SpanContext, Span, SpanStatus, SpanStatusCode, SpanKind, trace, Tracer, ValueType, } from '@opentelemetry/api';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotmeshio/hotmesh",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Unbreakable Workflows",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -13,63 +13,63 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
|
-
"clean": "rimraf ./build",
|
|
17
16
|
"build": "tsc --build tsconfig.json",
|
|
17
|
+
"clean": "rimraf ./build",
|
|
18
18
|
"clean-build": "npm run clean && npm run build",
|
|
19
19
|
"lint": "eslint . --ext .ts",
|
|
20
20
|
"lint:fix": "eslint . --fix --ext .ts",
|
|
21
21
|
"start": "ts-node src/index.ts",
|
|
22
22
|
"test": "NODE_ENV=test jest --detectOpenHandles --forceExit --verbose",
|
|
23
|
-
"test:
|
|
24
|
-
"test:unit": "NODE_ENV=test jest ./tests/unit/*/*/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
25
|
-
"test:pipe": "NODE_ENV=test jest ./tests/unit/services/pipe/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
23
|
+
"test:await": "NODE_ENV=test jest ./tests/functional/awaiter/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
26
24
|
"test:compile": "NODE_ENV=test jest ./tests/functional/compile/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
27
|
-
"test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
28
|
-
"test:trigger": "NODE_ENV=test jest ./tests/unit/services/activities/trigger.test.ts --detectOpenHandles --forceExit --verbose",
|
|
29
25
|
"test:connect": "NODE_ENV=test jest ./tests/unit/services/connector/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
30
|
-
"test:connect:redis": "NODE_ENV=test jest ./tests/unit/services/connector/clients/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
31
26
|
"test:connect:ioredis": "NODE_ENV=test jest ./tests/unit/services/connector/clients/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
32
|
-
"test:
|
|
27
|
+
"test:connect:redis": "NODE_ENV=test jest ./tests/unit/services/connector/clients/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
28
|
+
"test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
29
|
+
"test:durable": "NODE_ENV=test jest ./tests/durable/*/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
30
|
+
"test:durable:basic": "NODE_ENV=test jest ./tests/durable/basic/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
31
|
+
"test:durable:collision": "NODE_ENV=test jest ./tests/durable/collision/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
32
|
+
"test:durable:fatal": "NODE_ENV=test jest ./tests/durable/fatal/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
33
|
+
"test:durable:goodbye": "NODE_ENV=test jest ./tests/durable/goodbye/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
34
|
+
"test:durable:hello": "NODE_ENV=test jest ./tests/durable/helloworld/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
35
|
+
"test:durable:hook": "NODE_ENV=test jest ./tests/durable/hook/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
36
|
+
"test:durable:interrupt": "NODE_ENV=test jest ./tests/durable/interrupt/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
37
|
+
"test:durable:loopactivity": "NODE_ENV=test jest ./tests/durable/loopactivity/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
38
|
+
"test:durable:nested": "NODE_ENV=test jest ./tests/durable/nested/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
39
|
+
"test:durable:retry": "NODE_ENV=test jest ./tests/durable/retry/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
40
|
+
"test:durable:sleep": "NODE_ENV=test jest ./tests/durable/sleep/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
41
|
+
"test:durable:signal": "NODE_ENV=test jest ./tests/durable/signal/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
42
|
+
"test:durable:unknown": "NODE_ENV=test jest ./tests/durable/unknown/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
33
43
|
"test:emit": "NODE_ENV=test jest ./tests/functional/emit/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
34
|
-
"test:
|
|
35
|
-
"test:
|
|
44
|
+
"test:functional": "NODE_ENV=test jest ./tests/functional/*/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
45
|
+
"test:hmsh": "NODE_ENV=test jest ./tests/functional/index.test.ts --detectOpenHandles --verbose",
|
|
36
46
|
"test:hook": "NODE_ENV=test jest ./tests/functional/hook/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
37
|
-
"test:signal": "NODE_ENV=test jest ./tests/functional/signal/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
38
47
|
"test:interrupt": "NODE_ENV=test jest ./tests/functional/interrupt/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
39
48
|
"test:parallel": "NODE_ENV=test jest ./tests/functional/parallel/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
40
|
-
"test:
|
|
49
|
+
"test:pipe": "NODE_ENV=test jest ./tests/unit/services/pipe/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
41
50
|
"test:quorum": "NODE_ENV=test jest ./tests/functional/quorum/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
42
51
|
"test:reclaim": "NODE_ENV=test jest ./tests/functional/reclaim/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
43
52
|
"test:redeploy": "NODE_ENV=test jest ./tests/functional/redeploy/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
53
|
+
"test:reentrant": "NODE_ENV=test jest ./tests/functional/reentrant/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
44
54
|
"test:retry": "NODE_ENV=test jest ./tests/functional/retry/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
55
|
+
"test:sequence": "NODE_ENV=test jest ./tests/functional/sequence/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
56
|
+
"test:signal": "NODE_ENV=test jest ./tests/functional/signal/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
45
57
|
"test:status": "NODE_ENV=test jest ./tests/functional/status/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
46
|
-
"test:store:redis": "NODE_ENV=test jest ./tests/functional/store/clients/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
47
58
|
"test:store:ioredis": "NODE_ENV=test jest ./tests/functional/store/clients/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
48
|
-
"test:
|
|
59
|
+
"test:store:redis": "NODE_ENV=test jest ./tests/functional/store/clients/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
49
60
|
"test:stream:ioredis": "NODE_ENV=test jest ./tests/functional/stream/clients/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
50
|
-
"test:
|
|
61
|
+
"test:stream:redis": "NODE_ENV=test jest ./tests/functional/stream/clients/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
51
62
|
"test:sub:ioredis": "NODE_ENV=test jest ./tests/functional/sub/clients/ioredis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
52
|
-
"test:
|
|
53
|
-
"test:
|
|
54
|
-
"test:
|
|
55
|
-
"test:durable:hello": "NODE_ENV=test jest ./tests/durable/helloworld/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
56
|
-
"test:durable:interrupt": "NODE_ENV=test jest ./tests/durable/interrupt/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
57
|
-
"test:durable:goodbye": "NODE_ENV=test jest ./tests/durable/goodbye/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
58
|
-
"test:durable:hook": "NODE_ENV=test jest ./tests/durable/hook/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
59
|
-
"test:durable:retry": "NODE_ENV=test jest ./tests/durable/retry/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
60
|
-
"test:durable:fatal": "NODE_ENV=test jest ./tests/durable/fatal/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
61
|
-
"test:durable:unknown": "NODE_ENV=test jest ./tests/durable/unknown/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
62
|
-
"test:durable:sleep": "NODE_ENV=test jest ./tests/durable/sleep/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
63
|
-
"test:durable:signal": "NODE_ENV=test jest ./tests/durable/signal/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
64
|
-
"test:durable:loopactivity": "NODE_ENV=test jest ./tests/durable/loopactivity/index.test.ts --detectOpenHandles --forceExit --verbose",
|
|
65
|
-
"test:durable:nested": "NODE_ENV=test jest ./tests/durable/nested/index.test.ts --detectOpenHandles --forceExit --verbose"
|
|
63
|
+
"test:sub:redis": "NODE_ENV=test jest ./tests/functional/sub/clients/redis.test.ts --detectOpenHandles --forceExit --verbose",
|
|
64
|
+
"test:trigger": "NODE_ENV=test jest ./tests/unit/services/activities/trigger.test.ts --detectOpenHandles --forceExit --verbose",
|
|
65
|
+
"test:unit": "NODE_ENV=test jest ./tests/unit/*/*/index.test.ts --detectOpenHandles --forceExit --verbose"
|
|
66
66
|
},
|
|
67
67
|
"keywords": [
|
|
68
|
+
"workflow",
|
|
68
69
|
"durable workflow",
|
|
69
|
-
"HotMesh",
|
|
70
|
-
"service mesh",
|
|
71
|
-
"workflows",
|
|
72
70
|
"operational data",
|
|
71
|
+
"service mesh",
|
|
72
|
+
"HotMesh",
|
|
73
73
|
"Redis",
|
|
74
74
|
"OLAP",
|
|
75
75
|
"OLTP",
|
|
@@ -89,9 +89,12 @@
|
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@types/jest": "^29.5.0",
|
|
91
91
|
"@types/node": "^18.15.11",
|
|
92
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
93
|
-
"@typescript-eslint/parser": "^5.
|
|
94
|
-
"eslint": "^8.
|
|
92
|
+
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
|
93
|
+
"@typescript-eslint/parser": "^5.62.0",
|
|
94
|
+
"eslint": "^8.57.0",
|
|
95
|
+
"eslint-config-prettier": "^9.1.0",
|
|
96
|
+
"eslint-plugin-import": "^2.29.1",
|
|
97
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
95
98
|
"ioredis": "^5.3.2",
|
|
96
99
|
"jest": "^29.5.0",
|
|
97
100
|
"redis": "^4.6.13",
|
|
@@ -102,7 +105,7 @@
|
|
|
102
105
|
"typescript": "^5.0.4"
|
|
103
106
|
},
|
|
104
107
|
"peerDependencies": {
|
|
105
|
-
"
|
|
106
|
-
"
|
|
108
|
+
"ioredis": "^4.0.0 || ^5.0.0",
|
|
109
|
+
"redis": "^4.0.0"
|
|
107
110
|
}
|
|
108
111
|
}
|
package/types/activity.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { MetricTypes } from
|
|
2
|
-
import { StreamRetryPolicy } from
|
|
3
|
-
|
|
4
|
-
type ActivityExecutionType =
|
|
1
|
+
import { MetricTypes } from './stats';
|
|
2
|
+
import { StreamRetryPolicy } from './stream';
|
|
3
|
+
|
|
4
|
+
type ActivityExecutionType =
|
|
5
|
+
| 'trigger'
|
|
6
|
+
| 'await'
|
|
7
|
+
| 'worker'
|
|
8
|
+
| 'activity'
|
|
9
|
+
| 'emit'
|
|
10
|
+
| 'interrupt'
|
|
11
|
+
| 'cycle'
|
|
12
|
+
| 'signal'
|
|
13
|
+
| 'hook';
|
|
5
14
|
|
|
6
15
|
type Consumes = Record<string, string[]>;
|
|
7
16
|
|
|
@@ -15,20 +24,20 @@ interface BaseActivity {
|
|
|
15
24
|
job?: Record<string, any>;
|
|
16
25
|
hook?: Record<string, any>;
|
|
17
26
|
telemetry?: Record<string, any>;
|
|
18
|
-
emit?: boolean;
|
|
19
|
-
sleep?: number;
|
|
20
|
-
expire?: number;
|
|
21
|
-
retry?: StreamRetryPolicy
|
|
22
|
-
cycle?: boolean;
|
|
23
|
-
collationInt?: number;
|
|
24
|
-
consumes?: Consumes;
|
|
25
|
-
PRODUCES?: string[];
|
|
26
|
-
produces?: string[];
|
|
27
|
-
publishes?: string;
|
|
28
|
-
subscribes?: string;
|
|
29
|
-
trigger?: string;
|
|
30
|
-
parent?: string;
|
|
31
|
-
ancestors?: string[];
|
|
27
|
+
emit?: boolean; //if true, the activity will emit a message to the `publishes` topic immediately before transitioning to adjacent activities
|
|
28
|
+
sleep?: number; //@pipe /in seconds
|
|
29
|
+
expire?: number; //-1 forever; 0 persists the flow until the parent flow that expired it is dismissed; 15 seconds is the default
|
|
30
|
+
retry?: StreamRetryPolicy;
|
|
31
|
+
cycle?: boolean; //if true, the `notary` will leave leg 2 open, so it can be re/cycled
|
|
32
|
+
collationInt?: number; //compiler
|
|
33
|
+
consumes?: Consumes; //compiler
|
|
34
|
+
PRODUCES?: string[]; //compiler
|
|
35
|
+
produces?: string[]; //compiler
|
|
36
|
+
publishes?: string; //compiler
|
|
37
|
+
subscribes?: string; //compiler
|
|
38
|
+
trigger?: string; //compiler
|
|
39
|
+
parent?: string; //compiler
|
|
40
|
+
ancestors?: string[]; //compiler
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
interface Measure {
|
|
@@ -38,9 +47,9 @@ interface Measure {
|
|
|
38
47
|
|
|
39
48
|
interface TriggerActivityStats {
|
|
40
49
|
/**
|
|
41
|
-
* dependent parent job id; including this allows the parent's
|
|
42
|
-
* expiration/interruption events to cascade; set
|
|
43
|
-
* `expire` in the YAML for the dependent graph
|
|
50
|
+
* dependent parent job id; including this allows the parent's
|
|
51
|
+
* expiration/interruption events to cascade; set
|
|
52
|
+
* `expire` in the YAML for the dependent graph
|
|
44
53
|
* to 0 and provide the parent for dependent,
|
|
45
54
|
* cascading interruption and cleanup
|
|
46
55
|
*/
|
|
@@ -96,50 +105,50 @@ interface HookActivity extends BaseActivity {
|
|
|
96
105
|
}
|
|
97
106
|
|
|
98
107
|
interface SignalActivity extends BaseActivity {
|
|
99
|
-
type: 'signal';
|
|
100
|
-
subtype: 'one' | 'all';
|
|
101
|
-
topic: string;
|
|
102
|
-
key_name?: string;
|
|
103
|
-
key_value?: string;
|
|
104
|
-
scrub?: boolean;
|
|
105
|
-
signal?: Record<string, any>;
|
|
108
|
+
type: 'signal'; //signal activities call hook/hookAll
|
|
109
|
+
subtype: 'one' | 'all'; //trigger: hook(One) or hookAll
|
|
110
|
+
topic: string; //e.g., 'hook.resume'
|
|
111
|
+
key_name?: string; //e.g., 'parent_job_id'
|
|
112
|
+
key_value?: string; //e.g., '1234567890'
|
|
113
|
+
scrub?: boolean; //if true, the index will be deleted after use
|
|
114
|
+
signal?: Record<string, any>; //used to define/map the signal input data (what to send/singnal into the job(s))
|
|
106
115
|
resolver?: Record<string, any>; //used to define/map the signal key resolver (the key used to lookup the job(s that are assigned to the key)
|
|
107
|
-
status?: string;
|
|
108
|
-
code?: number;
|
|
116
|
+
status?: string; //pending, success (default), error
|
|
117
|
+
code?: number; //202, 200 (default)
|
|
109
118
|
}
|
|
110
119
|
|
|
111
120
|
interface InterruptActivity extends BaseActivity {
|
|
112
121
|
type: 'interrupt';
|
|
113
122
|
|
|
114
|
-
/**
|
|
123
|
+
/**
|
|
115
124
|
* Optional Reason; will be used as the error `message` when thrown
|
|
116
125
|
* @default 'Job Interrupted'
|
|
117
126
|
*/
|
|
118
127
|
reason?: string;
|
|
119
128
|
|
|
120
|
-
/**
|
|
129
|
+
/**
|
|
121
130
|
* throw JobInterrupted error upon interrupting
|
|
122
131
|
* @default true
|
|
123
132
|
*/
|
|
124
133
|
throw?: boolean;
|
|
125
134
|
|
|
126
|
-
/**
|
|
135
|
+
/**
|
|
127
136
|
* Interrupt child/descendant jobs
|
|
128
137
|
* @default false
|
|
129
138
|
*/
|
|
130
139
|
descend?: boolean;
|
|
131
140
|
|
|
132
|
-
/**
|
|
141
|
+
/**
|
|
133
142
|
* Target job id (if not present the current job will be targeted)
|
|
134
143
|
*/
|
|
135
144
|
target?: string;
|
|
136
145
|
|
|
137
|
-
/**
|
|
146
|
+
/**
|
|
138
147
|
* Optional topic to publish the interrupt message (if not present the current job topic will be used
|
|
139
148
|
*/
|
|
140
149
|
topic?: string;
|
|
141
150
|
|
|
142
|
-
/**
|
|
151
|
+
/**
|
|
143
152
|
* Optional Error Code; will be used as the error `code` when thrown
|
|
144
153
|
* @default 410
|
|
145
154
|
*/
|
|
@@ -151,7 +160,15 @@ interface InterruptActivity extends BaseActivity {
|
|
|
151
160
|
stack?: string;
|
|
152
161
|
}
|
|
153
162
|
|
|
154
|
-
type ActivityType =
|
|
163
|
+
type ActivityType =
|
|
164
|
+
| BaseActivity
|
|
165
|
+
| TriggerActivity
|
|
166
|
+
| AwaitActivity
|
|
167
|
+
| WorkerActivity
|
|
168
|
+
| InterruptActivity
|
|
169
|
+
| HookActivity
|
|
170
|
+
| SignalActivity
|
|
171
|
+
| CycleActivity;
|
|
155
172
|
|
|
156
173
|
type ActivityData = Record<string, any>;
|
|
157
174
|
|
|
@@ -213,7 +230,7 @@ type ActivityMetadata = {
|
|
|
213
230
|
type ActivityContext = {
|
|
214
231
|
data?: ActivityData | null;
|
|
215
232
|
metadata: ActivityMetadata;
|
|
216
|
-
hook?: ActivityData
|
|
233
|
+
hook?: ActivityData;
|
|
217
234
|
};
|
|
218
235
|
|
|
219
236
|
type ActivityDuplex = 1 | 2;
|
|
@@ -243,5 +260,5 @@ export {
|
|
|
243
260
|
BaseActivity,
|
|
244
261
|
InterruptActivity,
|
|
245
262
|
TriggerActivity,
|
|
246
|
-
WorkerActivity
|
|
263
|
+
WorkerActivity,
|
|
247
264
|
};
|
package/types/async.ts
CHANGED
package/types/collator.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export type CollationStage = 'enter' | 'exit' | 'confirm';
|
|
2
2
|
|
|
3
3
|
export enum CollationFaultType {
|
|
4
|
-
MISSING = 'missing',
|
|
5
|
-
DUPLICATE = 'duplicate',
|
|
6
|
-
INACTIVE = 'inactive',
|
|
7
|
-
INVALID = 'invalid',
|
|
8
|
-
FORBIDDEN = 'forbidden',
|
|
4
|
+
MISSING = 'missing', //`as` uninitialized; leg1 entry not allowed
|
|
5
|
+
DUPLICATE = 'duplicate', //1st digit < 8
|
|
6
|
+
INACTIVE = 'inactive', //3rd digit is 8
|
|
7
|
+
INVALID = 'invalid', //unknown value (corrupt for unknown reasons)
|
|
8
|
+
FORBIDDEN = 'forbidden', //leg 1 not completed; reentry (leg 2) not allowed
|
|
9
9
|
}
|