Skip to content

Feature request: Expose existing IdempotencyRecord in IdempotencyValidationError #2048

Closed
@kevin-secrist

Description

@kevin-secrist

Use case

In my current work I'm reusing the Idempotency package to consolidate potentially many events into one final entity. The first event needs to create the entity, and following events should be updates to that existing entity. The function that has been made idempotent returns the ID of the entity that was created. When the package throws a IdempotencyValidationError that is enough for me to trigger an update but it would also be nice to know the entity ID.

For example

try {
  const createdEntityId = await createThingIdempotent(createRequest)
  return createdEntityId
} catch (error) {
  if (error instanceof IdempotencyValidationError) {
    await handleTheUpdateCase() // example
    // we don't have the entityId here to return
    return -1
  }
  throw error
}

I have means of looking up what the entityId is by searching/listing resources, so this is not a blocker for me but having the existing record available seems like a reasonable thing to expect in this kind of workflow. If the payload failing validation is an exceptional scenario, ideally you'd want to be able to recover from it rather than fail outright. In order to recover, I expect you may want to know what data is in conflict.

Solution/User Experience

Simply exposing the IdempotencyRecord or at least the responseData in a similar fashion to how it is done with IdempotencyItemAlreadyExistsError should be enough to accomplish this.

class IdempotencyItemAlreadyExistsError extends Error {
public existingRecord?: IdempotencyRecord;
public constructor(message?: string, existingRecord?: IdempotencyRecord) {
super(message);
this.existingRecord = existingRecord;
}
}

if (this.getFromCache(idempotencyRecord.idempotencyKey)) {
throw new IdempotencyItemAlreadyExistsError(
`Failed to put record for already existing idempotency key: ${idempotencyRecord.idempotencyKey}`,
idempotencyRecord
);
}

At the place where this error is currently thrown, the existing record is in scope and should be easy to include.

private validatePayload(data: JSONValue, record: IdempotencyRecord): void {
if (this.payloadValidationEnabled) {
const hashedPayload: string = this.getHashedPayload(data);
if (hashedPayload !== record.payloadHash) {
throw new IdempotencyValidationError(
'Payload does not match stored record for this event key'
);
}
}
}

Alternative solutions

No response

Acknowledgment

Future readers

Please react with 👍 and your use case to help us understand customer demand.

Metadata

Metadata

Assignees

Labels

confirmedThe scope is clear, ready for implementationfeature-requestThis item refers to a feature request for an existing or new utilityidempotencyThis item relates to the Idempotency Utility

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions