@skedulo/integration-sdk 0.5.3 → 0.5.5
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/CHANGELOG.md +11 -4
- package/dist/actions/event/on-skedulo.action.d.ts.map +1 -1
- package/dist/actions/event/on-skedulo.action.js +26 -28
- package/dist/actions/event/on-skedulo.action.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/services/dataflow.service.d.ts.map +1 -1
- package/dist/services/dataflow.service.js +7 -4
- package/dist/services/dataflow.service.js.map +1 -1
- package/dist/services/id-mapping-sync.strategy.d.ts +3 -0
- package/dist/services/id-mapping-sync.strategy.d.ts.map +1 -1
- package/dist/services/id-mapping-sync.strategy.js +171 -61
- package/dist/services/id-mapping-sync.strategy.js.map +1 -1
- package/dist/services/id-mapping.service.d.ts +35 -7
- package/dist/services/id-mapping.service.d.ts.map +1 -1
- package/dist/services/id-mapping.service.js +151 -58
- package/dist/services/id-mapping.service.js.map +1 -1
- package/dist/services/sync-runner.d.ts +2 -2
- package/dist/services/sync-runner.d.ts.map +1 -1
- package/dist/services/sync-runner.js +56 -8
- package/dist/services/sync-runner.js.map +1 -1
- package/dist/utils/artifact-builder.d.ts +6 -1
- package/dist/utils/artifact-builder.d.ts.map +1 -1
- package/dist/utils/artifact-builder.js +14 -3
- package/dist/utils/artifact-builder.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [0.5.
|
|
3
|
+
## [0.5.5]
|
|
4
4
|
|
|
5
5
|
**Direction-agnostic relationship lookup resolution.**
|
|
6
6
|
|
|
7
|
-
- `IdMappingService.resolveLookups` — relationship lookups now resolve regardless of which direction the related object was synced.
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
- `IdMappingService.resolveLookups` — relationship lookups now resolve regardless of which direction the related object was synced. One query per object matches the id on either side of the system pair: `(src→tgt, ObjectType scoped, SourceId IN ids)` OR `(tgt→src, TargetId IN ids)`; the counterpart is the other system's id. Fixes `id_mapping_lookup_miss` when a relationship synced one way is used by a flow going the other (e.g. companies synced HubSpot→Skedulo, resolved by an outbound Skedulo→HubSpot flow).
|
|
8
|
+
- Own-direction (forward) matches take precedence — a single forward match wins and reverse rows are ignored; reverse only decides when forward is empty. Ambiguity within the winning tier (>1 distinct counterpart) is left unresolved (`id_mapping_lookup_ambiguous`). The query is paginated, so ambiguity detection always sees every matching row.
|
|
9
|
+
- Both the batch and event paths build their lookup queries through the same helper and run the same resolution, so they can't diverge. Primary identity still resolves own-direction only via `resolve()` (it decides create vs. update). The event path wraps resolution so a failure becomes a controlled `failed` result instead of an uncaught throw, matching the batch path.
|
|
10
|
+
|
|
11
|
+
**Fixes**
|
|
12
|
+
|
|
13
|
+
- Concurrent deliveries of the same new record (e.g. a Skedulo `INSERT` plus a near-instant `UPDATE`) no longer create duplicate target records. Before writing a create, `IdMappingSyncStrategy` reserves the record's `UniqueKey` via `IdMappingService.claimCreates` (an `insert` the unique constraint rejects for a racing duplicate); the winner creates and finalizes the reservation with the real `TargetId`, a loser skips (its change reconciles on the next sync) rather than inserting a second record. A failed target write releases the reservation so a stale row can't permanently block re-creation. Covers both `processBatch` (batch + `event.on-skedulo`) and the single-event path.
|
|
14
|
+
- `DataFlowService.deactivate` no longer fails with `409 "Deactivate the flow to edit"`. It now flips IS to INACTIVE before clearing `trigger_name` (IS rejects edits to an active flow), preserving the clear-before-delete ordering that keeps a mid-failure recoverable.
|
|
15
|
+
- `event.on-skedulo` now processes a multi-record delivery as a **batch** (`SyncRunner.handleFlowEventBatch`) — upserts run through the shared `SyncService.processBatch` path (one grouped `resolveLookups` + one insert/update batch for all records) instead of resolving and writing each record one at a time; deletes stay per-record. Resolves the real source adapter so the source id is read correctly (Skedulo → `UID`), matching the batch sync path.
|
|
16
|
+
- `buildArtifactName` now names each object with its system — `sked-int-<sourceSystem>-<sourceObject>-to-<targetSystem>-<targetObject>-flow<id>` — so an outbound flow reads `sked-int-skedulo-jobs-to-salesforce-…` instead of `sked-int-salesforce-jobs-to-…`, where the vendor prefix looked like part of the (actually Skedulo) source object. Falls back to `skedulo`/`<integrationType>` for legacy flows with no explicit systems. **Existing realtime flows get a renamed triggered action on their next deactivate→reactivate cycle** (deactivate deletes the old artifact by its stored name, so cleanup is unaffected).
|
|
10
17
|
|
|
11
18
|
## [0.5.2]
|
|
12
19
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-skedulo.action.d.ts","sourceRoot":"","sources":["../../../src/actions/event/on-skedulo.action.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"on-skedulo.action.d.ts","sourceRoot":"","sources":["../../../src/actions/event/on-skedulo.action.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,oBAAoB,EAAiB,MAAM,SAAS,CAAC;AAkCnG,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,SAAS,GACd,MAAM,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,CA+CnD"}
|
|
@@ -9,7 +9,7 @@ const errors_1 = require("../utils/errors");
|
|
|
9
9
|
* Parse one element of the ElasticServer triggered-action `call_url` body. Each
|
|
10
10
|
* element is the GraphQL query result wrapped under a single subscription-name
|
|
11
11
|
* key inside `data`, plus an `operation`, e.g.
|
|
12
|
-
* `{ "data": { "contacts": { "UID": "…", "Email": … } }, "operation": "INSERT" }`
|
|
12
|
+
* `[{ "data": { "contacts": { "UID": "…", "Email": … } }, "operation": "INSERT" }]`
|
|
13
13
|
*/
|
|
14
14
|
function parseSkeduloChange(raw, index) {
|
|
15
15
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
@@ -39,42 +39,40 @@ function makeOnSkeduloEventAction(deps) {
|
|
|
39
39
|
return {
|
|
40
40
|
name: action_names_1.ACTIONS.event.onSkedulo,
|
|
41
41
|
parseInput(raw, meta) {
|
|
42
|
-
|
|
43
|
-
const dataFlowId =
|
|
42
|
+
// The flow id always rides on the `sked-data-flow-id` header (lifted into meta).
|
|
43
|
+
const dataFlowId = meta === null || meta === void 0 ? void 0 : meta.dataFlowId;
|
|
44
44
|
if (!Number.isInteger(dataFlowId) || dataFlowId <= 0) {
|
|
45
|
-
throw new errors_1.InvalidInputError('dataFlowId must be a positive integer');
|
|
45
|
+
throw new errors_1.InvalidInputError('dataFlowId must be a positive integer (from the sked-data-flow-id header)');
|
|
46
46
|
}
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const changes =
|
|
47
|
+
// The ElasticServer triggered action always posts a bare array of change elements.
|
|
48
|
+
if (!Array.isArray(raw)) {
|
|
49
|
+
throw new errors_1.InvalidInputError('expected an array of Skedulo change events');
|
|
50
|
+
}
|
|
51
|
+
const changes = raw.map(parseSkeduloChange);
|
|
52
52
|
return { dataFlowId: dataFlowId, changes };
|
|
53
53
|
},
|
|
54
54
|
async handler(input, ctx) {
|
|
55
55
|
const integrationType = deps.adapter.integrationType;
|
|
56
56
|
const lookupStrategy = (0, helpers_1.resolveLookupStrategy)(deps.adapter);
|
|
57
57
|
const runner = new sync_runner_1.SyncRunner(deps.registry);
|
|
58
|
-
|
|
59
|
-
for
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (results.some((r) => r.status === 'failed')) {
|
|
75
|
-
throw new errors_1.UpstreamPermanentError('Skedulo event processing failed', { details: results });
|
|
58
|
+
// One delivery can carry many record changes — process them as a batch so
|
|
59
|
+
// resolution and writes happen once for the whole set, not per record.
|
|
60
|
+
const result = await runner.handleFlowEventBatch({
|
|
61
|
+
flowId: input.dataFlowId,
|
|
62
|
+
events: input.changes.map((change) => ({
|
|
63
|
+
integrationType,
|
|
64
|
+
objectType: '',
|
|
65
|
+
operation: change.operation,
|
|
66
|
+
recordId: change.recordId,
|
|
67
|
+
payload: change.payload,
|
|
68
|
+
dataFlowId: input.dataFlowId,
|
|
69
|
+
})),
|
|
70
|
+
options: { lookupStrategy },
|
|
71
|
+
}, ctx);
|
|
72
|
+
if (result.status === 'failed') {
|
|
73
|
+
throw new errors_1.UpstreamPermanentError('Skedulo event processing failed', { details: result });
|
|
76
74
|
}
|
|
77
|
-
return { message: 'Skedulo event processed', results };
|
|
75
|
+
return { message: 'Skedulo event processed', results: [result] };
|
|
78
76
|
},
|
|
79
77
|
};
|
|
80
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-skedulo.action.js","sourceRoot":"","sources":["../../../src/actions/event/on-skedulo.action.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"on-skedulo.action.js","sourceRoot":"","sources":["../../../src/actions/event/on-skedulo.action.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare const OperationName: {
|
|
|
13
13
|
readonly PUSH_FETCH: "pushFetch";
|
|
14
14
|
readonly PREVIEW: (id: number) => string;
|
|
15
15
|
readonly MAPPING_RESOLVE: "idMappingResolve";
|
|
16
|
+
readonly MAPPING_CLAIM: "idMappingClaim";
|
|
16
17
|
readonly MAPPING_UPSERT: "idMappingUpsert";
|
|
17
18
|
readonly MAPPING_DELETE_LOOKUP: "idMappingDeleteLookup";
|
|
18
19
|
readonly MAPPING_DELETE: "idMappingDelete";
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAEX,eAAO,MAAM,aAAa;;gCAEL,MAAM;;;wBAGd,MAAM;0CACY,MAAM;;2BAErB,MAAM
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAEX,eAAO,MAAM,aAAa;;gCAEL,MAAM;;;wBAGd,MAAM;0CACY,MAAM;;2BAErB,MAAM;;;;;;;CAOZ,CAAC;AAEX,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,oFAAoF;AACpF,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAElF,wEAAwE;AACxE,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,eAAO,MAAM,WAAW;;;CAGd,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE,eAAO,MAAM,QAAQ;;;CAGX,CAAC;AACX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC;AAEhE,eAAO,MAAM,cAAc;IACzB,kFAAkF;;IAElF,sFAAsF;;CAE9E,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.OperationName = {
|
|
|
16
16
|
PUSH_FETCH: 'pushFetch',
|
|
17
17
|
PREVIEW: (id) => `preview_${id}`,
|
|
18
18
|
MAPPING_RESOLVE: 'idMappingResolve',
|
|
19
|
+
MAPPING_CLAIM: 'idMappingClaim',
|
|
19
20
|
MAPPING_UPSERT: 'idMappingUpsert',
|
|
20
21
|
MAPPING_DELETE_LOOKUP: 'idMappingDeleteLookup',
|
|
21
22
|
MAPPING_DELETE: 'idMappingDelete',
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,QAAQ,GAAG;IACtB,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,kBAAkB,EAAE,oBAAoB;CAChC,CAAC;AAEE,QAAA,aAAa,GAAG;IAC3B,eAAe,EAAE,gBAAgB;IACjC,YAAY,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,gBAAgB,EAAE,EAAE;IAClD,qBAAqB,EAAE,6BAA6B;IACpD,cAAc,EAAE,uBAAuB;IACvC,IAAI,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE;IAClC,cAAc,EAAE,CAAC,UAAkB,EAAE,EAAE,CAAC,iBAAiB,UAAU,EAAE;IACrE,UAAU,EAAE,WAAW;IACvB,OAAO,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE;IACxC,eAAe,EAAE,kBAAkB;IACnC,cAAc,EAAE,iBAAiB;IACjC,qBAAqB,EAAE,uBAAuB;IAC9C,cAAc,EAAE,iBAAiB;IACjC,mBAAmB,EAAE,qBAAqB;CAClC,CAAC;AAEE,QAAA,iBAAiB,GAAG,GAAG,CAAC;AAErC,oFAAoF;AACvE,QAAA,cAAc,GAAG;IAC5B,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;CACZ,CAAC;AAGX,wEAAwE;AAC3D,QAAA,cAAc,GAAG,SAAS,CAAC;AAE3B,QAAA,WAAW,GAAG;IACzB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;CACR,CAAC;AAGE,QAAA,QAAQ,GAAG;IACtB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;CACN,CAAC;AAGE,QAAA,cAAc,GAAG;IAC5B,kFAAkF;IAClF,UAAU,EAAE,YAAY;IACxB,sFAAsF;IACtF,SAAS,EAAE,WAAW;CACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,QAAQ,GAAG;IACtB,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,kBAAkB,EAAE,oBAAoB;CAChC,CAAC;AAEE,QAAA,aAAa,GAAG;IAC3B,eAAe,EAAE,gBAAgB;IACjC,YAAY,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,gBAAgB,EAAE,EAAE;IAClD,qBAAqB,EAAE,6BAA6B;IACpD,cAAc,EAAE,uBAAuB;IACvC,IAAI,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE;IAClC,cAAc,EAAE,CAAC,UAAkB,EAAE,EAAE,CAAC,iBAAiB,UAAU,EAAE;IACrE,UAAU,EAAE,WAAW;IACvB,OAAO,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE;IACxC,eAAe,EAAE,kBAAkB;IACnC,aAAa,EAAE,gBAAgB;IAC/B,cAAc,EAAE,iBAAiB;IACjC,qBAAqB,EAAE,uBAAuB;IAC9C,cAAc,EAAE,iBAAiB;IACjC,mBAAmB,EAAE,qBAAqB;CAClC,CAAC;AAEE,QAAA,iBAAiB,GAAG,GAAG,CAAC;AAErC,oFAAoF;AACvE,QAAA,cAAc,GAAG;IAC5B,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;CACZ,CAAC;AAGX,wEAAwE;AAC3D,QAAA,cAAc,GAAG,SAAS,CAAC;AAE3B,QAAA,WAAW,GAAG;IACzB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;CACR,CAAC;AAGE,QAAA,QAAQ,GAAG;IACtB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;CACN,CAAC;AAGE,QAAA,cAAc,GAAG;IAC5B,kFAAkF;IAClF,UAAU,EAAE,YAAY;IACxB,sFAAsF;IACtF,SAAS,EAAE,WAAW;CACd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataflow.service.d.ts","sourceRoot":"","sources":["../../src/services/dataflow.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,EAGL,KAAK,QAAQ,EAEd,MAAM,wCAAwC,CAAC;AAUhD,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAE7C,gBAAgB,CAAC,IAAI,EAAE;QAC3B,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAajB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAIjD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,UAAU,CAAC,MAAM,EAAE;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAajB,IAAI,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAIhE,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIrD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIjE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;;;;;;;;;;OAWG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAyDtE;;;;OAIG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"dataflow.service.d.ts","sourceRoot":"","sources":["../../src/services/dataflow.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,EAGL,KAAK,QAAQ,EAEd,MAAM,wCAAwC,CAAC;AAUhD,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,cAAc;IAE7C,gBAAgB,CAAC,IAAI,EAAE;QAC3B,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAajB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAIjD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,UAAU,CAAC,MAAM,EAAE;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAajB,IAAI,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAIhE,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIrD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAIjE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;;;;;;;;;;OAWG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAyDtE;;;;OAIG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAsCzE"}
|
|
@@ -140,13 +140,17 @@ class DataFlowService {
|
|
|
140
140
|
throw new errors_1.NotFoundError('FLOW_NOT_FOUND', `Flow ${id} not found`);
|
|
141
141
|
}
|
|
142
142
|
const sc = (0, data_flow_spec_interface_1.asSyncConfig)((_a = flow.triggerConfig) !== null && _a !== void 0 ? _a : null);
|
|
143
|
-
//
|
|
143
|
+
// Flip IS to INACTIVE FIRST. IS rejects any edit to an active flow
|
|
144
|
+
// (409 "Deactivate the flow to edit"), so the trigger_name clear below — a
|
|
145
|
+
// PATCH — is only permitted once the flow is inactive.
|
|
146
|
+
await this.client.deactivate(id);
|
|
147
|
+
// Then clear trigger_name BEFORE deleting the artifact. If we deleted first
|
|
144
148
|
// and the clear failed, the flow would be left INACTIVE with a stale
|
|
145
149
|
// trigger_name — the next activate would see it, take the "already
|
|
146
150
|
// provisioned" branch, and mark ACTIVE without recreating the artifact
|
|
147
|
-
// (silent break). Clearing first
|
|
151
|
+
// (silent break). Clearing first keeps every later failure recoverable:
|
|
148
152
|
// re-running deactivate is a no-op on the already-cleared config and
|
|
149
|
-
// safely (re-)attempts the artifact delete
|
|
153
|
+
// safely (re-)attempts the artifact delete.
|
|
150
154
|
if (sc) {
|
|
151
155
|
const { trigger_name: _n, trigger_type: _t } = sc, rest = __rest(sc, ["trigger_name", "trigger_type"]);
|
|
152
156
|
void _n;
|
|
@@ -160,7 +164,6 @@ class DataFlowService {
|
|
|
160
164
|
const client = ctx.newArtifactClient(pulse_solution_services_1.ArtifactType.TRIGGERED_ACTION);
|
|
161
165
|
await (0, artifact_builder_1.deleteArtifactIfExists)(client, sc.trigger_name);
|
|
162
166
|
}
|
|
163
|
-
await this.client.deactivate(id);
|
|
164
167
|
const updated = await this.client.getById(id);
|
|
165
168
|
return updated !== null && updated !== void 0 ? updated : flow;
|
|
166
169
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataflow.service.js","sourceRoot":"","sources":["../../src/services/dataflow.service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dataflow.service.js","sourceRoot":"","sources":["../../src/services/dataflow.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,8EAAgE;AAQhE,oDAAwD;AACxD,4CAA8C;AAC9C,qFAKgD;AAChD,gEAOmC;AAEnC,MAAa,eAAe;IAC1B,YAA6B,MAAsB;QAAtB,WAAM,GAAN,MAAM,CAAgB;IAAG,CAAC;IAEvD,KAAK,CAAC,gBAAgB,CAAC,IAItB;QACC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAClC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,MAAM,EAAE,0BAAc,CAAC,MAAM;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU;QAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,MAAmB;QACpD,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAGhB;QACC,MAAM,MAAM,GAAuB;YACjC,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,MAAM,EAAE,0BAAc,CAAC,MAAM;SAC9B,CAAC;QACF,IAAI,MAAM,CAAC,YAAY;YAAE,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QAEnE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAA0B;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAA0B;QACrC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,KAA0B;QACjD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAU,EAAE,GAAuB;;QAChD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,sBAAa,CAAC,gBAAgB,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,EAAE,GAAG,IAAA,uCAAY,EAAC,MAAA,IAAI,CAAC,aAAa,mCAAI,IAAI,CAAC,CAAC;QAEpD,0EAA0E;QAC1E,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC/B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC9C,OAAO,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,IAAI,CAAC;QACzB,CAAC;QAED,IAAI,EAAE,CAAC,YAAY,EAAE,CAAC;YACpB,iDAAiD;YACjD,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC/B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC9C,OAAO,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,IAAI,CAAC;QACzB,CAAC;QAED,MAAM,IAAI,GAAG,IAAA,oCAAiB,EAAC,IAAI,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,IAAA,sCAAmB,EAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAA,+CAA4B,EAAC;YAC5C,IAAI;YACJ,GAAG;YACH,UAAU,EAAE,IAAI,CAAC,YAAY;YAC7B,KAAK,EAAE,IAAA,oCAAiB,EAAC,IAAI,CAAC;YAC9B,UAAU,EAAE,IAAI,CAAC,EAAE;SACpB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,CAAC,sCAAY,CAAC,gBAAgB,CAAC,CAAC;QACpE,MAAM,IAAA,iCAAc,EAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAE7C,IAAI,CAAC;YACH,iEAAiE;YACjE,MAAM,iBAAiB,GAAkB;gBACvC,WAAW,kCAAO,EAAE,KAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,sCAAW,CAAC,gBAAgB,GAAE;aACvF,CAAC;YACF,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE;gBAC3B,aAAa,EAAE,iBAAuD;aACvE,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,IAAA,yCAAsB,EAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC7C,CAAC;YAAC,WAAM,CAAC;gBACP,8DAA8D;YAChE,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9C,OAAO,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,IAAI,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,GAAuB;;QAClD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,sBAAa,CAAC,gBAAgB,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,EAAE,GAAG,IAAA,uCAAY,EAAC,MAAA,IAAI,CAAC,aAAa,mCAAI,IAAI,CAAC,CAAC;QAEpD,mEAAmE;QACnE,2EAA2E;QAC3E,uDAAuD;QACvD,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAEjC,4EAA4E;QAC5E,qEAAqE;QACrE,mEAAmE;QACnE,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,4CAA4C;QAC5C,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,KAAc,EAAE,EAAX,IAAI,UAAK,EAAE,EAApD,gCAA+C,CAAK,CAAC;YAC3D,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;YACR,MAAM,iBAAiB,GAAkB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;YAC/D,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE;gBAC3B,aAAa,EAAE,iBAAuD;aACvE,CAAC,CAAC;QACL,CAAC;QAED,IAAI,EAAE,aAAF,EAAE,uBAAF,EAAE,CAAE,YAAY,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,CAAC,sCAAY,CAAC,gBAAgB,CAAC,CAAC;YACpE,MAAM,IAAA,yCAAsB,EAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9C,OAAO,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,IAAI,CAAC;IACzB,CAAC;CACF;AA5KD,0CA4KC"}
|
|
@@ -10,8 +10,11 @@ export declare class IdMappingSyncStrategy implements SyncFlowStrategy {
|
|
|
10
10
|
private readonly idMappingService;
|
|
11
11
|
constructor(idMappingService: IdMappingService);
|
|
12
12
|
processBatch(ctx: IntegrationContext, flow: DataFlow, source: Adapter | null, target: Adapter, records: Record<string, unknown>[], localFilter: FilterSpec | null): Promise<BatchResult>;
|
|
13
|
+
private _claimCreatesForBatch;
|
|
14
|
+
private _releaseFailedClaims;
|
|
13
15
|
handleDeleteEvent(ctx: IntegrationContext, flow: DataFlow, target: Adapter, recordId: string): Promise<SyncResult>;
|
|
14
16
|
handleUpsertEvent(ctx: IntegrationContext, flow: DataFlow, source: Adapter | null, target: Adapter, event: MappedEvent): Promise<SyncResult>;
|
|
17
|
+
private _buildLookupQueries;
|
|
15
18
|
private _resolveRelationshipsBatch;
|
|
16
19
|
private _resolveRelationshipsOne;
|
|
17
20
|
private _writeMappingEntries;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id-mapping-sync.strategy.d.ts","sourceRoot":"","sources":["../../src/services/id-mapping-sync.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,iCAAiC,CAAC;AAC9F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAGnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AA+CxD,qBAAa,qBAAsB,YAAW,gBAAgB;IAChD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;gBAAhB,gBAAgB,EAAE,gBAAgB;IAEzD,YAAY,CAChB,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GAAG,IAAI,EACtB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAClC,WAAW,EAAE,UAAU,GAAG,IAAI,GAC7B,OAAO,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"id-mapping-sync.strategy.d.ts","sourceRoot":"","sources":["../../src/services/id-mapping-sync.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAiC,MAAM,iCAAiC,CAAC;AAC9F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAGnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AA+CxD,qBAAa,qBAAsB,YAAW,gBAAgB;IAChD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;gBAAhB,gBAAgB,EAAE,gBAAgB;IAEzD,YAAY,CAChB,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GAAG,IAAI,EACtB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAClC,WAAW,EAAE,UAAU,GAAG,IAAI,GAC7B,OAAO,CAAC,WAAW,CAAC;YAmKT,qBAAqB;YAyBrB,oBAAoB;IAsB5B,iBAAiB,CACrB,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC;IAqDhB,iBAAiB,CACrB,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GAAG,IAAI,EACtB,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,UAAU,CAAC;IAoItB,OAAO,CAAC,mBAAmB;YAsCb,0BAA0B;YAmF1B,wBAAwB;YAkExB,oBAAoB;CA4CnC"}
|
|
@@ -83,14 +83,37 @@ class IdMappingSyncStrategy {
|
|
|
83
83
|
const activeSrcIds = activeSourceIds.filter((_, i) => !skipSet.has(i));
|
|
84
84
|
if (activePairs.length === 0)
|
|
85
85
|
return stats;
|
|
86
|
-
|
|
86
|
+
// Step 4b: claim creates. The mapping table has no idempotency key on the target write,
|
|
87
|
+
// so concurrent deliveries of the same new record (e.g. a Skedulo INSERT plus a near-instant
|
|
88
|
+
// UPDATE) can both resolve to "no mapping" and both insert — a duplicate. Reserving the
|
|
89
|
+
// UniqueKey before the write serializes them: the winner creates, a loser means another
|
|
90
|
+
// in-flight delivery already owns the create, so we skip it (its change reconciles on the
|
|
91
|
+
// next sync) rather than create a second record.
|
|
92
|
+
const wonUidBySourceId = await this._claimCreatesForBatch(ctx, flow, activePairs, activeSrcIds);
|
|
93
|
+
const keep = [];
|
|
94
|
+
for (let i = 0; i < activePairs.length; i++) {
|
|
95
|
+
const isCreateI = activePairs[i].mapped['__targetUID'] == null;
|
|
96
|
+
if (isCreateI && activeSrcIds[i] && !wonUidBySourceId.has(activeSrcIds[i])) {
|
|
97
|
+
stats.skipped++;
|
|
98
|
+
stats.succeeded--;
|
|
99
|
+
ctx.logger.warn(`id_mapping_create_lost_claim: dataFlowId=${flow.id} sourceId=${activeSrcIds[i]} ` +
|
|
100
|
+
`objectType=${flow.targetObject} — concurrent create won the claim; skipping to avoid a duplicate`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
keep.push(i);
|
|
104
|
+
}
|
|
105
|
+
const dispatchPairs = keep.map((i) => activePairs[i]);
|
|
106
|
+
const dispatchSrcIds = keep.map((i) => activeSrcIds[i]);
|
|
107
|
+
if (dispatchPairs.length === 0)
|
|
108
|
+
return stats;
|
|
109
|
+
const isCreate = dispatchPairs.map((p) => p.mapped['__targetUID'] == null);
|
|
87
110
|
// Step 5: write to target — adapter performs insert (new) or update (existing).
|
|
88
111
|
await ((_j = source === null || source === void 0 ? void 0 : source.beforeUpsert) === null || _j === void 0 ? void 0 : _j.call(source, ctx));
|
|
89
112
|
await ((_k = target.beforeUpsert) === null || _k === void 0 ? void 0 : _k.call(target, ctx));
|
|
90
|
-
let outcomes = new Array(
|
|
113
|
+
let outcomes = new Array(dispatchPairs.length);
|
|
91
114
|
try {
|
|
92
115
|
if (typeof target.insert === 'function' || typeof target.update === 'function') {
|
|
93
|
-
const { inserts, updates } = splitForDispatch(
|
|
116
|
+
const { inserts, updates } = splitForDispatch(dispatchPairs);
|
|
94
117
|
if (inserts.length > 0) {
|
|
95
118
|
const insertOutcomes = typeof target.insert === 'function'
|
|
96
119
|
? await target.insert(ctx, flow, inserts.map((x) => x.mapped))
|
|
@@ -111,15 +134,15 @@ class IdMappingSyncStrategy {
|
|
|
111
134
|
else {
|
|
112
135
|
// Legacy adapters that only implement upsert(): pass the pairs through
|
|
113
136
|
// verbatim — they read __targetUID themselves and branch internally.
|
|
114
|
-
outcomes = await target.upsert(ctx, flow,
|
|
137
|
+
outcomes = await target.upsert(ctx, flow, dispatchPairs.map((p) => p.mapped));
|
|
115
138
|
}
|
|
116
139
|
if (ctx.pipeline)
|
|
117
140
|
ctx.pipeline.outcomes = outcomes;
|
|
118
141
|
for (let i = 0; i < outcomes.length; i++) {
|
|
119
142
|
if (outcomes[i].status !== 'ok') {
|
|
120
143
|
const message = (_l = outcomes[i].error) !== null && _l !== void 0 ? _l : outcomes[i].status;
|
|
121
|
-
captureRecordError(ctx, 'upsert', i, message, (_m =
|
|
122
|
-
ctx.logger.error(`upsert_failed: dataFlowId=${flow.id} recordIndex=${i} status=${outcomes[i].status} error=${message} data=${JSON.stringify((_p = (_o =
|
|
144
|
+
captureRecordError(ctx, 'upsert', i, message, (_m = dispatchPairs[i]) === null || _m === void 0 ? void 0 : _m.raw);
|
|
145
|
+
ctx.logger.error(`upsert_failed: dataFlowId=${flow.id} recordIndex=${i} status=${outcomes[i].status} error=${message} data=${JSON.stringify((_p = (_o = dispatchPairs[i]) === null || _o === void 0 ? void 0 : _o.raw) !== null && _p !== void 0 ? _p : {})}`);
|
|
123
146
|
stats.succeeded--;
|
|
124
147
|
stats.failed++;
|
|
125
148
|
}
|
|
@@ -129,15 +152,67 @@ class IdMappingSyncStrategy {
|
|
|
129
152
|
}
|
|
130
153
|
catch (err) {
|
|
131
154
|
const message = err instanceof Error ? err.message : String(err);
|
|
132
|
-
captureProcessError(ctx, 'upsert', message,
|
|
133
|
-
stats.failed +=
|
|
134
|
-
stats.succeeded -=
|
|
155
|
+
captureProcessError(ctx, 'upsert', message, dispatchPairs.length);
|
|
156
|
+
stats.failed += dispatchPairs.length;
|
|
157
|
+
stats.succeeded -= dispatchPairs.length;
|
|
158
|
+
// Outcomes can be partial — one dispatch bucket may have landed before the other threw.
|
|
159
|
+
// Finalize any create that actually succeeded (so it isn't re-created as a duplicate next
|
|
160
|
+
// run) and release reservations only for creates with no successful outcome.
|
|
161
|
+
await this._writeMappingEntries(ctx, flow, target, dispatchSrcIds, outcomes, isCreate);
|
|
162
|
+
await this._releaseFailedClaims(ctx, dispatchSrcIds, isCreate, outcomes, wonUidBySourceId);
|
|
135
163
|
return stats;
|
|
136
164
|
}
|
|
137
|
-
//
|
|
138
|
-
|
|
165
|
+
// Release reservations for creates whose target write failed (empty-TargetId rows would
|
|
166
|
+
// otherwise block the record from ever being created again).
|
|
167
|
+
await this._releaseFailedClaims(ctx, dispatchSrcIds, isCreate, outcomes, wonUidBySourceId);
|
|
168
|
+
// Step 6: write back — finalize each won reservation with the real TargetId (upsert on
|
|
169
|
+
// UniqueKey updates the placeholder row written at claim time).
|
|
170
|
+
await this._writeMappingEntries(ctx, flow, target, dispatchSrcIds, outcomes, isCreate);
|
|
139
171
|
return stats;
|
|
140
172
|
}
|
|
173
|
+
// Reserve the UniqueKey for every create-classified pair. Returns the reserved-row UID per
|
|
174
|
+
// won sourceId; absence from the map means the claim was lost to a concurrent delivery.
|
|
175
|
+
async _claimCreatesForBatch(ctx, flow, activePairs, activeSrcIds) {
|
|
176
|
+
const claims = activePairs
|
|
177
|
+
.map((p, i) => ({ create: p.mapped['__targetUID'] == null, sourceId: activeSrcIds[i] }))
|
|
178
|
+
.filter((c) => c.create && c.sourceId)
|
|
179
|
+
.map((c) => {
|
|
180
|
+
var _a, _b;
|
|
181
|
+
return ({
|
|
182
|
+
sourceSystem: (_a = flow.sourceSystem) !== null && _a !== void 0 ? _a : '',
|
|
183
|
+
targetSystem: (_b = flow.targetSystem) !== null && _b !== void 0 ? _b : '',
|
|
184
|
+
objectType: flow.targetObject,
|
|
185
|
+
sourceId: c.sourceId,
|
|
186
|
+
dataFlowId: String(flow.id),
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
if (claims.length === 0)
|
|
190
|
+
return new Map();
|
|
191
|
+
const { wonUidBySourceId } = await this.idMappingService.claimCreates(ctx, claims);
|
|
192
|
+
return wonUidBySourceId;
|
|
193
|
+
}
|
|
194
|
+
// Delete reserved claim rows for creates with no successful outcome, so a stale empty-TargetId
|
|
195
|
+
// row can't permanently block the record from ever being created. Retried once for symmetry
|
|
196
|
+
// with the mapping write — a transient failure here strands the reservation. (A crash between
|
|
197
|
+
// reserve and this release is still possible; such a row needs manual cleanup or reclaim.)
|
|
198
|
+
async _releaseFailedClaims(ctx, dispatchSrcIds, isCreate, outcomes, wonUidBySourceId) {
|
|
199
|
+
var _a;
|
|
200
|
+
const uids = [];
|
|
201
|
+
for (let i = 0; i < dispatchSrcIds.length; i++) {
|
|
202
|
+
if (!isCreate[i])
|
|
203
|
+
continue;
|
|
204
|
+
if (((_a = outcomes[i]) === null || _a === void 0 ? void 0 : _a.status) === 'ok')
|
|
205
|
+
continue;
|
|
206
|
+
const uid = wonUidBySourceId.get(dispatchSrcIds[i]);
|
|
207
|
+
if (uid)
|
|
208
|
+
uids.push(uid);
|
|
209
|
+
}
|
|
210
|
+
if (uids.length === 0)
|
|
211
|
+
return;
|
|
212
|
+
await retryOnce(() => this.idMappingService.deleteReservations(ctx, uids)).catch((err) => {
|
|
213
|
+
ctx.logger.error(`id_mapping_reservation_release_failed: ${err instanceof Error ? err.message : String(err)} uids=${JSON.stringify(uids)}`);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
141
216
|
async handleDeleteEvent(ctx, flow, target, recordId) {
|
|
142
217
|
var _a, _b, _c, _d;
|
|
143
218
|
const mappingTable = await this.idMappingService.resolve(ctx, [
|
|
@@ -183,7 +258,7 @@ class IdMappingSyncStrategy {
|
|
|
183
258
|
return { status: 'synced', recordsProcessed: 1 };
|
|
184
259
|
}
|
|
185
260
|
async handleUpsertEvent(ctx, flow, source, target, event) {
|
|
186
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
261
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
187
262
|
// Initialise pipeline data so beforeMap can mutate raw.
|
|
188
263
|
if (ctx.pipeline) {
|
|
189
264
|
ctx.pipeline.data = [{ raw: event.payload, mapped: {} }];
|
|
@@ -215,35 +290,71 @@ class IdMappingSyncStrategy {
|
|
|
215
290
|
await ((_q = target.beforeUpsert) === null || _q === void 0 ? void 0 : _q.call(target, ctx));
|
|
216
291
|
// Dispatch insert vs update based on resolved __targetUID, mirroring processBatch.
|
|
217
292
|
const isCreate = mapped['__targetUID'] == null;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
293
|
+
// Claim the create before writing (see processBatch): serialize concurrent deliveries of the
|
|
294
|
+
// same new record via the UniqueKey constraint. A lost claim means another delivery already
|
|
295
|
+
// owns the create — skip rather than insert a duplicate.
|
|
296
|
+
let reservedUid;
|
|
297
|
+
if (isCreate) {
|
|
298
|
+
const { wonUidBySourceId, lostSourceIds } = await this.idMappingService.claimCreates(ctx, [
|
|
299
|
+
{
|
|
300
|
+
sourceSystem: (_r = flow.sourceSystem) !== null && _r !== void 0 ? _r : '',
|
|
301
|
+
targetSystem: (_s = flow.targetSystem) !== null && _s !== void 0 ? _s : '',
|
|
302
|
+
objectType: flow.targetObject,
|
|
303
|
+
sourceId,
|
|
304
|
+
dataFlowId: String(flow.id),
|
|
305
|
+
},
|
|
306
|
+
]);
|
|
307
|
+
if (lostSourceIds.length > 0) {
|
|
308
|
+
ctx.logger.warn(`id_mapping_create_lost_claim: dataFlowId=${flow.id} sourceId=${sourceId} ` +
|
|
309
|
+
`objectType=${flow.targetObject} — concurrent create won the claim; skipping to avoid a duplicate`);
|
|
310
|
+
return { status: 'skipped', recordsProcessed: 0, reason: 'concurrent_create' };
|
|
311
|
+
}
|
|
312
|
+
reservedUid = wonUidBySourceId.get(sourceId);
|
|
222
313
|
}
|
|
223
|
-
|
|
224
|
-
|
|
314
|
+
const releaseReservation = async () => {
|
|
315
|
+
if (isCreate && reservedUid) {
|
|
316
|
+
await retryOnce(() => this.idMappingService.deleteReservations(ctx, [reservedUid])).catch((err) => ctx.logger.error(`id_mapping_reservation_release_failed: sourceId=${sourceId} ` +
|
|
317
|
+
`uid=${reservedUid} error=${err instanceof Error ? err.message : String(err)}`));
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
let outcomes;
|
|
321
|
+
try {
|
|
322
|
+
if (isCreate && typeof target.insert === 'function') {
|
|
323
|
+
const _z = mapped, { __targetUID: _drop } = _z, payload = __rest(_z, ["__targetUID"]);
|
|
324
|
+
outcomes = await target.insert(ctx, flow, [payload]);
|
|
325
|
+
}
|
|
326
|
+
else if (!isCreate && typeof target.update === 'function') {
|
|
327
|
+
outcomes = await target.update(ctx, flow, [mapped]);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
// Legacy path
|
|
331
|
+
outcomes = await target.upsert(ctx, flow, [mapped]);
|
|
332
|
+
}
|
|
225
333
|
}
|
|
226
|
-
|
|
227
|
-
//
|
|
228
|
-
|
|
334
|
+
catch (err) {
|
|
335
|
+
// Release the reservation so a stale empty-TargetId row can't permanently block re-creation.
|
|
336
|
+
await releaseReservation();
|
|
337
|
+
throw err;
|
|
229
338
|
}
|
|
230
339
|
const outcome = outcomes[0];
|
|
231
340
|
if (ctx.pipeline)
|
|
232
341
|
ctx.pipeline.outcomes = outcomes;
|
|
233
|
-
await ((
|
|
234
|
-
await ((
|
|
342
|
+
await ((_t = source === null || source === void 0 ? void 0 : source.afterUpsert) === null || _t === void 0 ? void 0 : _t.call(source, ctx));
|
|
343
|
+
await ((_u = target.afterUpsert) === null || _u === void 0 ? void 0 : _u.call(target, ctx));
|
|
235
344
|
if (outcome.status === 'precondition') {
|
|
236
|
-
|
|
345
|
+
await releaseReservation();
|
|
346
|
+
ctx.logger.error(`push_precondition: dataFlowId=${flow.id} recordId=${event.recordId} error=${(_v = outcome.error) !== null && _v !== void 0 ? _v : 'unknown'}`);
|
|
237
347
|
return {
|
|
238
348
|
status: 'precondition_failed',
|
|
239
349
|
recordsProcessed: 0,
|
|
240
|
-
error: (
|
|
350
|
+
error: (_w = outcome.error) !== null && _w !== void 0 ? _w : outcome.status,
|
|
241
351
|
};
|
|
242
352
|
}
|
|
243
353
|
if (outcome.status !== 'ok') {
|
|
354
|
+
await releaseReservation();
|
|
244
355
|
ctx.logger.error(`push_failed: dataFlowId=${flow.id} recordId=${event.recordId} ` +
|
|
245
|
-
`class=${outcome.status} error=${(
|
|
246
|
-
return { status: 'failed', recordsProcessed: 0, error: (
|
|
356
|
+
`class=${outcome.status} error=${(_x = outcome.error) !== null && _x !== void 0 ? _x : 'unknown'}`);
|
|
357
|
+
return { status: 'failed', recordsProcessed: 0, error: (_y = outcome.error) !== null && _y !== void 0 ? _y : outcome.status };
|
|
247
358
|
}
|
|
248
359
|
// Step 7: persist new source→target ID pair for a created record.
|
|
249
360
|
if (isCreate) {
|
|
@@ -251,35 +362,45 @@ class IdMappingSyncStrategy {
|
|
|
251
362
|
}
|
|
252
363
|
return { status: 'synced', recordsProcessed: 1 };
|
|
253
364
|
}
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
async _resolveRelationshipsBatch(ctx, flow, pairs, activeSourceIds, stats) {
|
|
259
|
-
var _a, _b, _c, _d, _e, _f;
|
|
365
|
+
// Collect relationship-lookup ids grouped by lookup object — shared by the batch and
|
|
366
|
+
// event paths so both build identical resolveLookups() queries (an event is a batch of one).
|
|
367
|
+
_buildLookupQueries(flow, mappedRecords) {
|
|
368
|
+
var _a, _b, _c, _d;
|
|
260
369
|
const lookupMappings = ((_b = (_a = flow.mappingConfig) === null || _a === void 0 ? void 0 : _a.mappings) !== null && _b !== void 0 ? _b : []).filter((m) => m.lookup);
|
|
261
|
-
|
|
262
|
-
const lookupIdsByObject = new Map();
|
|
370
|
+
const idsByObject = new Map();
|
|
263
371
|
for (const mapping of lookupMappings) {
|
|
264
372
|
const rule = mapping.lookup;
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
373
|
+
for (const mapped of mappedRecords) {
|
|
374
|
+
const v = mapped[mapping.target] != null ? String(mapped[mapping.target]) : '';
|
|
375
|
+
if (!v)
|
|
376
|
+
continue;
|
|
377
|
+
let set = idsByObject.get(rule.object);
|
|
378
|
+
if (!set) {
|
|
379
|
+
set = new Set();
|
|
380
|
+
idsByObject.set(rule.object, set);
|
|
381
|
+
}
|
|
382
|
+
set.add(v);
|
|
383
|
+
}
|
|
274
384
|
}
|
|
275
|
-
const sourceSystem = (
|
|
276
|
-
const targetSystem = (
|
|
277
|
-
|
|
385
|
+
const sourceSystem = (_c = flow.sourceSystem) !== null && _c !== void 0 ? _c : '';
|
|
386
|
+
const targetSystem = (_d = flow.targetSystem) !== null && _d !== void 0 ? _d : '';
|
|
387
|
+
return [...idsByObject.entries()].map(([objectType, ids]) => ({
|
|
278
388
|
sourceSystem,
|
|
279
389
|
targetSystem,
|
|
280
390
|
objectType,
|
|
281
391
|
sourceIds: [...ids],
|
|
282
392
|
}));
|
|
393
|
+
}
|
|
394
|
+
// Resolves primary identity and all relationship fields for a batch of pairs.
|
|
395
|
+
// Mutates pairs[i].mapped in place (sets __targetUID, substitutes lookup UIDs).
|
|
396
|
+
// Mutates stats in place (filtered/failed counts for onMissing handling).
|
|
397
|
+
// Returns the set of pair indices to skip, or null if the mapping table query failed.
|
|
398
|
+
async _resolveRelationshipsBatch(ctx, flow, pairs, activeSourceIds, stats) {
|
|
399
|
+
var _a, _b, _c, _d, _e;
|
|
400
|
+
const lookupMappings = ((_b = (_a = flow.mappingConfig) === null || _a === void 0 ? void 0 : _a.mappings) !== null && _b !== void 0 ? _b : []).filter((m) => m.lookup);
|
|
401
|
+
const sourceSystem = (_c = flow.sourceSystem) !== null && _c !== void 0 ? _c : '';
|
|
402
|
+
const targetSystem = (_d = flow.targetSystem) !== null && _d !== void 0 ? _d : '';
|
|
403
|
+
const lookupQueries = this._buildLookupQueries(flow, pairs.map((p) => p.mapped));
|
|
283
404
|
// Primary identity stays own-direction (it decides create vs. update); relationship
|
|
284
405
|
// lookups resolve direction-agnostically so a relationship synced the other way still
|
|
285
406
|
// resolves. Separate maps so a lookup never overwrites a primary-identity key.
|
|
@@ -305,7 +426,7 @@ class IdMappingSyncStrategy {
|
|
|
305
426
|
// SkeduloAdapter uses key presence to switch insert vs. upsert-by-UID.
|
|
306
427
|
for (let i = 0; i < pairs.length; i++) {
|
|
307
428
|
pairs[i].mapped['__targetUID'] =
|
|
308
|
-
(
|
|
429
|
+
(_e = primaryTable.get(`${flow.targetObject}:${activeSourceIds[i]}`)) !== null && _e !== void 0 ? _e : null;
|
|
309
430
|
}
|
|
310
431
|
// Apply lookup (relationship) field resolution with onMissing handling.
|
|
311
432
|
const skipSet = new Set();
|
|
@@ -349,19 +470,8 @@ class IdMappingSyncStrategy {
|
|
|
349
470
|
const lookupMappings = ((_b = (_a = flow.mappingConfig) === null || _a === void 0 ? void 0 : _a.mappings) !== null && _b !== void 0 ? _b : []).filter((m) => m.lookup);
|
|
350
471
|
const sourceSystem = (_c = flow.sourceSystem) !== null && _c !== void 0 ? _c : '';
|
|
351
472
|
const targetSystem = (_d = flow.targetSystem) !== null && _d !== void 0 ? _d : '';
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
const rule = mapping.lookup;
|
|
355
|
-
const rawValue = mapped[mapping.target] != null ? String(mapped[mapping.target]) : '';
|
|
356
|
-
if (!rawValue)
|
|
357
|
-
continue;
|
|
358
|
-
lookupQueries.push({
|
|
359
|
-
sourceSystem,
|
|
360
|
-
targetSystem,
|
|
361
|
-
objectType: rule.object,
|
|
362
|
-
sourceIds: [rawValue],
|
|
363
|
-
});
|
|
364
|
-
}
|
|
473
|
+
// Same query-builder as the batch path — a single event record is a batch of one.
|
|
474
|
+
const lookupQueries = this._buildLookupQueries(flow, [mapped]);
|
|
365
475
|
// Primary identity own-direction; relationship lookups direction-agnostic (see batch path).
|
|
366
476
|
// Convert resolve failures into a controlled terminal result — handleUpsertEvent has no
|
|
367
477
|
// outer catch, so an uncaught throw here would fail the whole event less gracefully than batch.
|