@mnci/az-durable 0.1.1 → 0.1.3

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,225 +0,0 @@
1
- function _instanceof(left, right) {
2
- "@swc/helpers - instanceof";
3
- if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
4
- return !!right[Symbol.hasInstance](left);
5
- } else return left instanceof right;
6
- }
7
- function _type_of(obj) {
8
- "@swc/helpers - typeof";
9
- return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
10
- }
11
- /**
12
- * Runs an orchestration against stubbed activities, with no Azure running.
13
- *
14
- * @remarks
15
- * Drives the generator synchronously, feeding each yielded task the stubbed
16
- * result for that activity's name. There is no host, no emulator and no
17
- * storage — a three-step workflow with a short-circuit branch is testable in
18
- * about fifteen lines.
19
- *
20
- * **How it intercepts.** The orchestration is driven with a fake
21
- * `OrchestrationContext`, which works only because every scheduling call in
22
- * this package goes through `context.df` rather than through the registered
23
- * callable. The alternative — reading the name off `task.action.functionName` —
24
- * is an undocumented SDK internal the package's non-goals forbid.
25
- *
26
- * **Limits, stated rather than discovered later.** Retry policies are not
27
- * simulated: a stub returning an `Error` throws once, it does not exhaust
28
- * attempts. `Task.any` resolves to the FIRST task in the list, since there is
29
- * no real concurrency to race. Timers complete immediately.
30
- *
31
- * @param orchestration - The orchestration to run.
32
- * @param input - The input, checked against its declared type.
33
- * @param stub - The activity fakes, clock and instance id.
34
- * @returns The result, the ordered calls, and the status transitions.
35
- * @throws Error when an activity is called with no stub registered for it.
36
- * @typeParam TInput - The orchestration's input type.
37
- * @typeParam TOutput - The orchestration's output type.
38
- */ function runWorkflow(orchestration, input, stub) {
39
- var _stub_now, _stub_instanceId;
40
- var calls = [];
41
- var statuses = [];
42
- var continuedAsNew;
43
- var clock = (_stub_now = stub.now) !== null && _stub_now !== void 0 ? _stub_now : new Date(0);
44
- var schedule = function schedule(name, scheduledInput) {
45
- calls.push({
46
- name: name,
47
- input: scheduledInput
48
- });
49
- return {
50
- isCompleted: false,
51
- isFaulted: false,
52
- __name: name,
53
- __input: scheduledInput
54
- };
55
- };
56
- var context = {
57
- df: {
58
- instanceId: (_stub_instanceId = stub.instanceId) !== null && _stub_instanceId !== void 0 ? _stub_instanceId : 'test-instance',
59
- isReplaying: false,
60
- currentUtcDateTime: clock,
61
- callActivity: schedule,
62
- callActivityWithRetry: function callActivityWithRetry(name, _retry, i) {
63
- return schedule(name, i);
64
- },
65
- callSubOrchestrator: function callSubOrchestrator(name, i) {
66
- return schedule(name, i);
67
- },
68
- callSubOrchestratorWithRetry: function callSubOrchestratorWithRetry(name, _retry, i) {
69
- return schedule(name, i);
70
- },
71
- waitForExternalEvent: function waitForExternalEvent(name) {
72
- return schedule(name, undefined);
73
- },
74
- // Timers complete immediately: there is no real time to wait for, and a
75
- // harness that blocked on one would be useless. `cancel` is real,
76
- // because an orchestration that correctly cancels its losing timer must
77
- // not crash in a test for doing the right thing.
78
- createTimer: function createTimer(fireAt) {
79
- var timer = schedule('__timer', fireAt.toISOString());
80
- timer.isCanceled = false;
81
- timer.cancel = function() {
82
- timer.isCanceled = true;
83
- };
84
- return timer;
85
- },
86
- setCustomStatus: function setCustomStatus(value) {
87
- statuses.push(String(value));
88
- },
89
- continueAsNew: function continueAsNew(next) {
90
- continuedAsNew = next;
91
- },
92
- Task: {
93
- all: function all(tasks) {
94
- return {
95
- isCompleted: false,
96
- isFaulted: false,
97
- __all: tasks
98
- };
99
- },
100
- // A marker, not a winner. `Task.any` resolves to the winning TASK, not
101
- // to its value, so choosing here would hand the orchestration the
102
- // wrong kind of thing — which is exactly the bug the reconstructed
103
- // workflows found.
104
- any: function any(tasks) {
105
- return {
106
- isCompleted: false,
107
- isFaulted: false,
108
- __any: tasks
109
- };
110
- }
111
- }
112
- }
113
- };
114
- var generator = orchestration.handler(context, input);
115
- var step = generator.next();
116
- while(!step.done){
117
- var resumed = resolve(step.value, stub);
118
- // INTO the generator, not out of the driver. Throwing here instead is the
119
- // bug the reconstructed workflows found: every compensation branch was
120
- // unreachable, while the docstring promised the opposite.
121
- step = isThrowRequest(resumed) ? generator.throw(resumed.__throw) : generator.next(resumed);
122
- }
123
- return continuedAsNew === undefined ? {
124
- result: step.value,
125
- calls: calls,
126
- statuses: statuses
127
- } : {
128
- result: step.value,
129
- calls: calls,
130
- statuses: statuses,
131
- continuedAsNew: continuedAsNew
132
- };
133
- }
134
- /**
135
- * Produces the value the driver resumes a yielded task with.
136
- *
137
- * @remarks
138
- * Separated so the `Task.all` fan-out case — where one yielded task stands for
139
- * several — is handled in one place rather than inline in the drive loop.
140
- *
141
- * @param task - The task the orchestration yielded.
142
- * @param stub - The stubs to resolve against.
143
- * @returns The value to resume with, or a {@link ThrowRequest} for the driver to inject.
144
- * @throws Error naming an activity with no stub registered.
145
- * @typeParam None - this function has no generic type parameters.
146
- */ function resolve(task, stub) {
147
- var fanOut = task.__all;
148
- if (fanOut !== undefined) {
149
- return fanOut.map(function(t) {
150
- return resolve(t, stub);
151
- });
152
- }
153
- var race = task.__any;
154
- if (race !== undefined) {
155
- return resolveRace(race, stub);
156
- }
157
- var name = task.__name, input = task.__input;
158
- if (name === '__timer') {
159
- return undefined;
160
- }
161
- var activity = stub.activities[name];
162
- if (activity === undefined) {
163
- // Naming the activity matters: the alternative is `undefined` flowing into
164
- // the orchestration and failing somewhere unrelated.
165
- throw new Error("No stub registered for '".concat(name, "'. Add it to stub.activities to run this workflow."));
166
- }
167
- var result = activity(input);
168
- if (_instanceof(result, Error)) {
169
- // A returned Error becomes a THROWN error inside the orchestration, which
170
- // is what makes failure branches testable at all. Handed back as a request
171
- // so the DRIVER injects it; see {@link ThrowRequest}.
172
- return {
173
- __throw: result
174
- };
175
- }
176
- return result;
177
- }
178
- /**
179
- * Settles a `Task.any` race and returns the winning TASK.
180
- *
181
- * @remarks
182
- * The distinction that matters: the SDK's `Task.any` resolves to the winning
183
- * task object, not to its value, and callers read the value afterwards with
184
- * `resultOf`. An earlier harness returned the resolved value instead, which
185
- * made every orchestration using a race fail with "Task.any returned a task
186
- * that was not one of the inputs" — correct code, rejected by the fake.
187
- *
188
- * The winner's `result` is populated and `isCompleted` set, so `resultOf` and
189
- * an `isCompleted` check on the loser both behave as they do in production.
190
- *
191
- * @param candidates - The racing tasks.
192
- * @param stub - The stubs to resolve the winner against.
193
- * @returns The winning task, completed and carrying its result.
194
- * @throws Error when `raceWinner` names a task that is not racing.
195
- * @typeParam None - this function has no generic type parameters.
196
- */ function resolveRace(candidates, stub) {
197
- var _ref;
198
- var _stub_raceWinner;
199
- var names = candidates.map(function(c) {
200
- return c.__name;
201
- });
202
- var chosen = (_ref = (_stub_raceWinner = stub.raceWinner) === null || _stub_raceWinner === void 0 ? void 0 : _stub_raceWinner.call(stub, names)) !== null && _ref !== void 0 ? _ref : names[0];
203
- var winner = candidates.find(function(c) {
204
- return c.__name === chosen;
205
- });
206
- if (winner === undefined) {
207
- throw new Error("raceWinner chose '".concat(String(chosen), "', which is not racing. Candidates: ").concat(names.join(', '), "."));
208
- }
209
- var mutable = winner;
210
- mutable.result = winner.__name === '__timer' ? undefined : resolve(winner, stub);
211
- mutable.isCompleted = true;
212
- return winner;
213
- }
214
- /**
215
- * Whether a resolved value is a request to throw inside the orchestration.
216
- *
217
- * @param value - Whatever `resolve` produced.
218
- * @returns `true` when the driver should call `generator.throw`.
219
- * @throws Never - a type guard.
220
- * @typeParam None - this function has no generic type parameters.
221
- */ function isThrowRequest(value) {
222
- return (typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object' && value !== null && '__throw' in value;
223
- }
224
-
225
- export { runWorkflow };