@fabriktor/fx 0.0.127 → 0.0.128

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.
@@ -15,6 +15,7 @@ export type MultiCreateCheckpoint = {
15
15
  before_request?: () => void;
16
16
  };
17
17
  export type MultiCreateAttempt = MultiCreateCheckpoint & {
18
+ entry_id?: string;
18
19
  idempotency_key: string;
19
20
  signal: AbortSignal;
20
21
  };
@@ -148,6 +148,7 @@ export class MultiCreator {
148
148
  signal.throwIfAborted();
149
149
  this.opts.before_request?.();
150
150
  const result = await this.opts.run(structuredClone(current.input), {
151
+ entry_id: current.id,
151
152
  signal,
152
153
  idempotency_key: current.idempotency_key,
153
154
  created_id: current.created_id,
@@ -311,23 +311,28 @@ export class PayrollsWorkspace {
311
311
  : command.resource;
312
312
  if (attempt.created_id)
313
313
  return this.owned(actor, resource, attempt.created_id, attempt.signal);
314
+ const requestID = attempt.entry_id ?? attempt.idempotency_key;
314
315
  const fingerprint = JSON.stringify({ owner_id: actor.owner_id, command });
315
- const previous = this.submitted.get(attempt.idempotency_key);
316
- requirePayroll(!previous || previous === fingerprint, "changed");
316
+ const previous = this.submitted.get(requestID);
317
+ requirePayroll(!previous || previous.fingerprint === fingerprint, "changed");
317
318
  const sourceKeys = command.resource === PayrollResource.HourBanks ||
318
319
  command.resource === PayrollResource.Payables
319
320
  ? command.input.ids.map((id) => `${actor.owner_id}:${command.resource}:${id}`)
320
321
  : [];
321
322
  for (const key of sourceKeys)
322
323
  requirePayroll(!this.sourceRequests.has(key) ||
323
- this.sourceRequests.get(key) === attempt.idempotency_key, "pending_source");
324
- if (!previous)
324
+ this.sourceRequests.get(key) === requestID, "pending_source");
325
+ // A fresh HTTP attempt must re-read configuration and source consumption state.
326
+ if (!previous || previous.idempotency_key !== attempt.idempotency_key)
325
327
  await this.validateCommand(actor, command, attempt.signal);
326
328
  attempt.before_request?.();
327
329
  attempt.signal.throwIfAborted();
328
- this.submitted.set(attempt.idempotency_key, fingerprint);
330
+ this.submitted.set(requestID, {
331
+ fingerprint,
332
+ idempotency_key: attempt.idempotency_key,
333
+ });
329
334
  for (const key of sourceKeys)
330
- this.sourceRequests.set(key, attempt.idempotency_key);
335
+ this.sourceRequests.set(key, requestID);
331
336
  const p = this.payrolls;
332
337
  const request = {
333
338
  signal: attempt.signal,
@@ -365,7 +370,7 @@ export class PayrollsWorkspace {
365
370
  isHTTPClientErr(error) &&
366
371
  error.status !== undefined &&
367
372
  payrollGenerationRejectionStatuses.includes(error.status)) {
368
- this.submitted.delete(attempt.idempotency_key);
373
+ this.submitted.delete(requestID);
369
374
  for (const key of sourceKeys)
370
375
  this.sourceRequests.delete(key);
371
376
  attempt.on_rejected?.();
@@ -374,7 +379,7 @@ export class PayrollsWorkspace {
374
379
  });
375
380
  const id = requiredOperationID(out, "Generated payroll record response did not contain an ID.");
376
381
  attempt.on_created?.(id);
377
- this.submitted.delete(attempt.idempotency_key);
382
+ this.submitted.delete(requestID);
378
383
  for (const key of sourceKeys)
379
384
  this.sourceRequests.delete(key);
380
385
  return this.owned(actor, resource, id, attempt.signal);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabriktor/fx",
3
- "version": "0.0.127",
3
+ "version": "0.0.128",
4
4
  "description": "![Fabriktor Logo](./img/fabriktor-character.gif)",
5
5
  "type": "module",
6
6
  "exports": {