@vertesia/workflow 1.1.1-dev.20260505.163000Z → 1.2.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/lib/cjs/activities/executeInteraction.js +5 -3
- package/lib/cjs/activities/executeInteraction.js.map +1 -1
- package/lib/esm/activities/executeInteraction.js +5 -3
- package/lib/esm/activities/executeInteraction.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/activities/executeInteraction.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/activities/executeInteraction.test.ts +83 -0
- package/src/activities/executeInteraction.ts +5 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executeInteraction.d.ts","sourceRoot":"","sources":["../../../src/activities/executeInteraction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,YAAY,EAAmB,MAAM,oBAAoB,CAAC;AAErF,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EACH,2BAA2B,EAC3B,eAAe,EAMlB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,YAAY,EAAoB,MAAM,oBAAoB,CAAC;AAiDpE,MAAM,WAAW,0BAA0B;IACvC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,aAAa,CAAC,EAAE,GAAG,CAAC;IAEpB,uDAAuD;IACvD,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,aAAa,CAAC,EAAE,YAAY,CAAC;IAE7B;;OAEG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAyB,SAAQ,0BAA0B;IAExE,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe,CAAC,wBAAwB,CAAC;IACjF,IAAI,EAAE,oBAAoB,CAAC;CAC9B;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,2BAA2B,CAAC,wBAAwB,CAAC,
|
|
1
|
+
{"version":3,"file":"executeInteraction.d.ts","sourceRoot":"","sources":["../../../src/activities/executeInteraction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,YAAY,EAAmB,MAAM,oBAAoB,CAAC;AAErF,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EACH,2BAA2B,EAC3B,eAAe,EAMlB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,YAAY,EAAoB,MAAM,oBAAoB,CAAC;AAiDpE,MAAM,WAAW,0BAA0B;IACvC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,aAAa,CAAC,EAAE,GAAG,CAAC;IAEpB,uDAAuD;IACvD,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,aAAa,CAAC,EAAE,YAAY,CAAC;IAE7B;;OAEG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAyB,SAAQ,0BAA0B;IAExE,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe,CAAC,wBAAwB,CAAC;IACjF,IAAI,EAAE,oBAAoB,CAAC;CAC9B;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,2BAA2B,CAAC,wBAAwB,CAAC,gBAqHtG;AAED,wBAAsB,8BAA8B,CAChD,MAAM,EAAE,cAAc,EACtB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,0BAA0B,EAClC,WAAW,EAAE,GAAG,EAChB,KAAK,CAAC,EAAE,OAAO,oFAuFlB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertesia/workflow",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vertesia workflow DSL",
|
|
6
6
|
"main": "./lib/esm/index.js",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"tmp-promise": "^3.0.3",
|
|
45
45
|
"yaml": "^2.6.0",
|
|
46
46
|
"@llumiverse/common": "1.1.1-dev.20260505.151157Z",
|
|
47
|
-
"@vertesia/client": "1.
|
|
48
|
-
"@vertesia/
|
|
49
|
-
"@vertesia/
|
|
50
|
-
"@vertesia/
|
|
47
|
+
"@vertesia/api-fetch-client": "1.2.0",
|
|
48
|
+
"@vertesia/common": "1.2.0",
|
|
49
|
+
"@vertesia/client": "1.2.0",
|
|
50
|
+
"@vertesia/memory": "1.2.0"
|
|
51
51
|
},
|
|
52
52
|
"ts_dual_module": {
|
|
53
53
|
"outDir": "lib",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ApplicationFailure } from '@temporalio/activity';
|
|
2
|
+
import { MockActivityEnvironment } from '@temporalio/testing';
|
|
3
|
+
import type { VertesiaClient } from '@vertesia/client';
|
|
4
|
+
import { ContentEventName, type DSLActivityExecutionPayload } from '@vertesia/common';
|
|
5
|
+
import type { ActivityContext } from '../dsl/setup/ActivityContext.js';
|
|
6
|
+
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
+
import { executeInteraction, type ExecuteInteractionParams } from './executeInteraction.js';
|
|
8
|
+
|
|
9
|
+
vi.mock('../dsl/setup/ActivityContext.js', async (importOriginal) => {
|
|
10
|
+
const actual = await importOriginal<typeof import('../dsl/setup/ActivityContext.js')>();
|
|
11
|
+
return { ...actual, setupActivity: vi.fn() };
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
let testEnv: MockActivityEnvironment;
|
|
15
|
+
|
|
16
|
+
beforeAll(() => {
|
|
17
|
+
testEnv = new MockActivityEnvironment();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
vi.clearAllMocks();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const createPayload = (): DSLActivityExecutionPayload<ExecuteInteractionParams> => ({
|
|
25
|
+
auth_token: 'mock-token',
|
|
26
|
+
account_id: 'test-account',
|
|
27
|
+
project_id: 'test-project',
|
|
28
|
+
params: {
|
|
29
|
+
interactionName: 'testInteraction',
|
|
30
|
+
prompt_data: {},
|
|
31
|
+
},
|
|
32
|
+
config: { studio_url: 'http://mock-studio', store_url: 'http://mock-store' },
|
|
33
|
+
workflow_name: 'test-workflow',
|
|
34
|
+
event: ContentEventName.create,
|
|
35
|
+
objectIds: ['test-object-id'],
|
|
36
|
+
input: { inputType: 'objectIds', objectIds: ['test-object-id'] },
|
|
37
|
+
vars: {},
|
|
38
|
+
activity: { name: 'executeInteraction', params: {} },
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
async function mockInteractionError(error: Error & { statusCode?: number; status?: number; code?: number }): Promise<void> {
|
|
42
|
+
const { setupActivity } = await import('../dsl/setup/ActivityContext.js');
|
|
43
|
+
const mockClient = {
|
|
44
|
+
interactions: {
|
|
45
|
+
executeByName: vi.fn().mockRejectedValue(error),
|
|
46
|
+
},
|
|
47
|
+
} as unknown as VertesiaClient;
|
|
48
|
+
|
|
49
|
+
vi.mocked(setupActivity).mockResolvedValue({
|
|
50
|
+
client: mockClient,
|
|
51
|
+
inputType: 'objectIds',
|
|
52
|
+
params: createPayload().params,
|
|
53
|
+
} as unknown as ActivityContext<ExecuteInteractionParams>);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe('executeInteraction retryability', () => {
|
|
57
|
+
it('leaves 412 rendition-in-progress failures retryable', async () => {
|
|
58
|
+
await mockInteractionError(Object.assign(new Error('rendition in progress'), { statusCode: 412 }));
|
|
59
|
+
|
|
60
|
+
await expect(testEnv.run(executeInteraction, createPayload())).rejects.toMatchObject({
|
|
61
|
+
message: 'Interaction Execution failed testInteraction: rendition in progress',
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it.each([
|
|
66
|
+
['status', { status: 412 }],
|
|
67
|
+
['code', { code: 412 }],
|
|
68
|
+
])('leaves 412 failures retryable when reported as %s', async (_field, statusProps) => {
|
|
69
|
+
await mockInteractionError(Object.assign(new Error('precondition failed'), statusProps));
|
|
70
|
+
|
|
71
|
+
await expect(testEnv.run(executeInteraction, createPayload())).rejects.toMatchObject({
|
|
72
|
+
message: 'Interaction Execution failed testInteraction: precondition failed',
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('marks other 4xx failures as non-retryable', async () => {
|
|
77
|
+
await mockInteractionError(Object.assign(new Error('bad request'), { statusCode: 400 }));
|
|
78
|
+
|
|
79
|
+
await expect(testEnv.run(executeInteraction, createPayload())).rejects.toMatchObject({
|
|
80
|
+
nonRetryable: true,
|
|
81
|
+
} satisfies Partial<ApplicationFailure>);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -203,7 +203,8 @@ export async function executeInteraction(payload: DSLActivityExecutionPayload<Ex
|
|
|
203
203
|
if (error.statusCode === 429 && params.exit_on_resource_exhaustion) {
|
|
204
204
|
throw new ResourceExhaustedError(error.statusCode, "Resource exhausted - rate limit exceeded");
|
|
205
205
|
} else if (is4xxNonRetryable(error.status) || is4xxNonRetryable(error.statusCode) || is4xxNonRetryable(error.code) || error.retryable === false) {
|
|
206
|
-
// 4xx HTTP errors (except
|
|
206
|
+
// 4xx HTTP errors (except retryable statuses) are permanent client errors
|
|
207
|
+
// (e.g. model not found, invalid request).
|
|
207
208
|
// Errors explicitly marked as non-retryable (e.g. LlumiverseError) also fall here.
|
|
208
209
|
// They will not be resolved by retrying.
|
|
209
210
|
throw ApplicationFailure.create({
|
|
@@ -341,9 +342,10 @@ export async function executeInteractionFromActivity(
|
|
|
341
342
|
|
|
342
343
|
/**
|
|
343
344
|
* Returns true for 4xx status codes that indicate permanent client errors.
|
|
344
|
-
* 429 (Too Many Requests)
|
|
345
|
+
* 412 (Precondition Failed) and 429 (Too Many Requests) are excluded because
|
|
346
|
+
* they are retryable.
|
|
345
347
|
*/
|
|
346
348
|
function is4xxNonRetryable(code: number | undefined): boolean {
|
|
347
349
|
if (code === undefined || typeof code !== 'number') return false;
|
|
348
|
-
return code >= 400 && code < 500 && code !== 429;
|
|
350
|
+
return code >= 400 && code < 500 && code !== 412 && code !== 429;
|
|
349
351
|
}
|