Context
In persistPayloadEnvelopeInput(), a DB write failure causes the in-memory PayloadEnvelopeInput to be pruned via .finally(), losing data from both DB and memory with no recovery path. This is the same pattern as persistBlockInput().
Current behavior
await writePayloadEnvelopeInputToDb.call(this, payloadInput)
.catch((e) => {
this.logger.error("Error persisting payload envelope in hot db", {...}, e);
})
.finally(() => {
this.seenPayloadEnvelopeInput.prune(payloadInput.blockRootHex);
// ...
});
On a transient DB error (disk full, I/O timeout), .catch() logs the error but .finally() still prunes the in-memory data. The envelope is now gone from both DB and memory — irrecoverable.
Proposed fix
- Only prune on success (move prune from
.finally() to .then())
- Add a retry mechanism for transient failures (exponential backoff, bounded retries)
- Apply the same fix to
persistBlockInput() which has the identical pattern
References
/cc @nflaig @twoeths
Context
In
persistPayloadEnvelopeInput(), a DB write failure causes the in-memoryPayloadEnvelopeInputto be pruned via.finally(), losing data from both DB and memory with no recovery path. This is the same pattern aspersistBlockInput().Current behavior
On a transient DB error (disk full, I/O timeout),
.catch()logs the error but.finally()still prunes the in-memory data. The envelope is now gone from both DB and memory — irrecoverable.Proposed fix
.finally()to.then())persistBlockInput()which has the identical patternReferences
writePayloadEnvelopeInputToDb.ts(review thread)persistBlockInput()(noted by @twoeths)/cc @nflaig @twoeths