Skip to content

feat: Import .jsonl file with events into the events table#414

Merged
phoenix-server merged 8 commits intocameri:mainfrom
Anshumancanrock:import-json-file
Apr 10, 2026
Merged

feat: Import .jsonl file with events into the events table#414
phoenix-server merged 8 commits intocameri:mainfrom
Anshumancanrock:import-json-file

Conversation

@Anshumancanrock
Copy link
Copy Markdown
Contributor

@Anshumancanrock Anshumancanrock commented Apr 9, 2026

Description

Implements a CLI utility for importing NIP-01 events from .jsonl files into the events table.

  • Streams the file line-by-line via readline to keep memory usage constant regardless of file size.
  • Validates every event before insertion: Joi schema, SHA-256 id hash, and Schnorr signature.
  • Inserts events in batched database transactions (default batch size: 1000, configurable via --batch-size).
  • Handles all event kinds consistently with the relay: regular inserts with ON CONFLICT DO NOTHING, replaceable/parameterized replaceable upserts using the existing replaceable_events_idx, delete event application in stream order, and ephemeral event filtering.
  • Duplicates are skipped gracefully without interrupting the import.
  • Interacts directly with the database layer via Knex, bypassing WebSocket and rate limiting.

Related Issue

Closes #406

Motivation and Context

There's no built-in way to seed a relay with existing data or migrate events from another relay. This adds a straightforward CLI for it.

How Has This Been Tested?

  • 4 new unit tests covering batching, duplicate tracking, error counting, and persistence failure propagation.
  • Full existing test suite passes (493/493).
  • TypeScript build and ESLint both clean.

Tested locally against a real PostgreSQL instance , imported 463 events from a .jsonl file and all inserted successfully in ~1s. Progress tracking and final summary both working as expected.

image

Types of changes

  • Non-functional change (docs, style, minor refactor)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my code changes.
  • All new and existing tests passed.

@Anshumancanrock
Copy link
Copy Markdown
Contributor Author

Anshumancanrock commented Apr 9, 2026

Hi @cameri, I tested the imports locally and they work fine. Please take a look when you’re free and let me know if you’d like any changes. Thanks!

@cameri
Copy link
Copy Markdown
Owner

cameri commented Apr 9, 2026

Thank you. I will send you an events database for you to test this against. Stay tuned.

Comment on lines +25 to +29
const REPLACEABLE_EVENT_CONFLICT_TARGET =
'(event_pubkey, event_kind, event_deduplication) '
+ 'WHERE (event_kind = 0 OR event_kind = 3 OR event_kind = 41 '
+ 'OR (event_kind >= 10000 AND event_kind < 20000)) '
+ 'OR (event_kind >= 30000 AND event_kind < 40000)'
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My concern here is that this query will drift from the queries in the EventRepository over time.

Is there a reason why the event import service essentially re-implements the database layer instead of re-using it?

@Anshumancanrock Anshumancanrock requested a review from cameri April 9, 2026 15:15
@Anshumancanrock
Copy link
Copy Markdown
Contributor Author

Hi @cameri, I’ve updated the importer to reuse EventRepository batch writes. It now streams .jsonl line by line, validates each event (schema, id hash, and signature), and persists them in batches: regular events via createMany, replaceable via upsertMany, and delete events via flush + deleteByPubkeyAndIds+ storing the delete event.

Ephemeral events are skipped, duplicates are handled gracefully, and progress/errors are reported during import.

Am i doing something wrong in this approch? Please let me know.
Screenshot 2026-04-09 235259

@phoenix-server phoenix-server merged commit cbdf967 into cameri:main Apr 10, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Import .jsonl file with events into the events table

3 participants