Conversation
Collaborator
There was a problem hiding this comment.
Pull request overview
This PR aligns batch replaceable-event ingestion (EventRepository.upsertMany()) with single-event ingestion (upsert()) by applying NIP-01’s deterministic tie-break rule when created_at timestamps are equal.
Changes:
- Update
upsertMany()’s conflict-update condition to also update on equal timestamps when the incomingevent_idis lexically smaller. - Add unit tests covering
upsertMany([]) === 0and verifying the generated conflict WHERE condition includes the tie-breaker. - Add a Changesets entry documenting the patch fix.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/repositories/event-repository.ts |
Extends upsertMany()’s ON CONFLICT update condition to match NIP-01 tie-break semantics used by upsert(). |
test/unit/repositories/event-repository.spec.ts |
Adds focused unit coverage for upsertMany() empty input and tie-breaker conflict condition. |
.changeset/fix-upsertmany-tiebreak.md |
Records the change as a patch release note. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR fixes a gap in
EventRepository.upsertMany()for replaceable and parameterized-replaceable events.upsert()already handled the NIP-01 tie-break rule for equal timestamps (lower lexicalevent_idwins), butupsertMany()only compared strictly newer timestamps. That made batch paths behave differently from single-event ingestion.Changes in this PR:
upsertMany()conflict condition to matchupsert()semantics:excluded.event_created_atis newerevent_idis lexically greaterupsertMany():0for empty inputRelated Issue
Fixes #536
Motivation and Context
Nostr replaceable events require deterministic winners when
created_atties occur. Without this fallback inupsertMany(), import/batch flows could keep a different winner than the live websocket path, which creates inconsistent relay state for the same event set.This aligns batch behavior with existing single-event behavior and preserves protocol-consistent conflict resolution.
How Has This Been Tested?
npm run test:unit -- test/unit/repositories/event-repository.spec.tsupsertManytests pass:returns 0 when no events are providedapplies NIP-01 tie-breaker in batch conflict conditionevent_idfallback.Screenshots (if appropriate):
N/A
Types of changes
Checklist: