lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit abeff0a20f394d15288d360f195fee786e468a7c
parent 4272a7278973989138a3b3b49e53c14595970190
Author: triesap <tyson@radroots.org>
Date:   Fri, 26 Jun 2026 08:41:33 +0000

storage: rename canonical workflow tables

- Rename event-store tables to nostr_events and nostr_event_tags.
- Rename the outbox operation table to outbox_operations.
- Update store queries and migration down paths to the target names.
- Keep the change breaking with no compatibility views or aliases.

Diffstat:
Mcrates/event_store/migrations/0001_event_store.down.sql | 4++--
Mcrates/event_store/migrations/0001_event_store.up.sql | 22+++++++++++-----------
Mcrates/event_store/src/store.rs | 24++++++++++++------------
Mcrates/outbox/migrations/0001_outbox.down.sql | 2+-
Mcrates/outbox/migrations/0001_outbox.up.sql | 8++++----
Mcrates/outbox/src/model.rs | 2+-
Mcrates/outbox/src/store.rs | 22+++++++++++-----------
7 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/crates/event_store/migrations/0001_event_store.down.sql b/crates/event_store/migrations/0001_event_store.down.sql @@ -1,5 +1,5 @@ DROP TABLE projection_cursor; DROP TABLE nostr_event_head; DROP TABLE relay_event_seen; -DROP TABLE nostr_event_tag; -DROP TABLE nostr_event; +DROP TABLE nostr_event_tags; +DROP TABLE nostr_events; diff --git a/crates/event_store/migrations/0001_event_store.up.sql b/crates/event_store/migrations/0001_event_store.up.sql @@ -1,4 +1,4 @@ -CREATE TABLE IF NOT EXISTS nostr_event ( +CREATE TABLE IF NOT EXISTS nostr_events ( seq INTEGER PRIMARY KEY AUTOINCREMENT, event_id TEXT NOT NULL UNIQUE, pubkey TEXT NOT NULL, @@ -17,14 +17,14 @@ CREATE TABLE IF NOT EXISTS nostr_event ( updated_at_ms INTEGER NOT NULL ); -CREATE INDEX IF NOT EXISTS nostr_event_kind_created_idx ON nostr_event(kind, created_at, event_id); -CREATE INDEX IF NOT EXISTS nostr_event_contract_idx ON nostr_event(contract_id, seq); -CREATE INDEX IF NOT EXISTS nostr_event_projection_idx ON nostr_event(projection_eligible, seq); +CREATE INDEX IF NOT EXISTS nostr_event_kind_created_idx ON nostr_events(kind, created_at, event_id); +CREATE INDEX IF NOT EXISTS nostr_event_contract_idx ON nostr_events(contract_id, seq); +CREATE INDEX IF NOT EXISTS nostr_event_projection_idx ON nostr_events(projection_eligible, seq); CREATE INDEX IF NOT EXISTS nostr_event_verification_contract_idx -ON nostr_event(verification_status, contract_status, seq); +ON nostr_events(verification_status, contract_status, seq); -CREATE TABLE IF NOT EXISTS nostr_event_tag ( - event_id TEXT NOT NULL REFERENCES nostr_event(event_id) ON DELETE CASCADE, +CREATE TABLE IF NOT EXISTS nostr_event_tags ( + event_id TEXT NOT NULL REFERENCES nostr_events(event_id) ON DELETE CASCADE, tag_index INTEGER NOT NULL, tag_name TEXT NOT NULL, tag_value TEXT, @@ -35,11 +35,11 @@ CREATE TABLE IF NOT EXISTS nostr_event_tag ( PRIMARY KEY (event_id, tag_index) ); -CREATE INDEX IF NOT EXISTS nostr_event_tag_lookup_idx ON nostr_event_tag(tag_name, tag_value, event_id); -CREATE INDEX IF NOT EXISTS nostr_event_tag_relay_idx ON nostr_event_tag(relay_indexed, tag_name, tag_value, event_id); +CREATE INDEX IF NOT EXISTS nostr_event_tag_lookup_idx ON nostr_event_tags(tag_name, tag_value, event_id); +CREATE INDEX IF NOT EXISTS nostr_event_tag_relay_idx ON nostr_event_tags(relay_indexed, tag_name, tag_value, event_id); CREATE TABLE IF NOT EXISTS relay_event_seen ( - event_id TEXT NOT NULL REFERENCES nostr_event(event_id) ON DELETE CASCADE, + event_id TEXT NOT NULL REFERENCES nostr_events(event_id) ON DELETE CASCADE, relay_url TEXT NOT NULL, observation_type TEXT NOT NULL, first_seen_at_ms INTEGER NOT NULL, @@ -56,7 +56,7 @@ CREATE TABLE IF NOT EXISTS nostr_event_head ( kind INTEGER NOT NULL, pubkey TEXT NOT NULL, d_tag TEXT, - event_id TEXT NOT NULL REFERENCES nostr_event(event_id) ON DELETE CASCADE, + event_id TEXT NOT NULL REFERENCES nostr_events(event_id) ON DELETE CASCADE, created_at INTEGER NOT NULL, updated_at_ms INTEGER NOT NULL, CHECK ( diff --git a/crates/event_store/src/store.rs b/crates/event_store/src/store.rs @@ -80,7 +80,7 @@ impl RadrootsEventStore { &self, ) -> Result<RadrootsEventStoreStatusSummary, RadrootsEventStoreError> { let row = sqlx::query( - "SELECT COUNT(*) AS total_events, COALESCE(SUM(CASE WHEN projection_eligible = 1 THEN 1 ELSE 0 END), 0) AS projection_eligible_events, MAX(seq) AS last_event_seq, MAX(updated_at_ms) AS last_event_updated_at_ms FROM nostr_event", + "SELECT COUNT(*) AS total_events, COALESCE(SUM(CASE WHEN projection_eligible = 1 THEN 1 ELSE 0 END), 0) AS projection_eligible_events, MAX(seq) AS last_event_seq, MAX(updated_at_ms) AS last_event_updated_at_ms FROM nostr_events", ) .fetch_one(&self.pool) .await?; @@ -132,7 +132,7 @@ impl RadrootsEventStore { projection_eligible = head.projection_eligible; head_decision = head.decision; sqlx::query( - "UPDATE nostr_event SET projection_eligible = ?, updated_at_ms = ? WHERE event_id = ?", + "UPDATE nostr_events SET projection_eligible = ?, updated_at_ms = ? WHERE event_id = ?", ) .bind(bool_i64(projection_eligible)) .bind(ingest.observed_at_ms) @@ -173,7 +173,7 @@ impl RadrootsEventStore { event_id: &str, ) -> Result<Option<RadrootsStoredEvent>, RadrootsEventStoreError> { let row = sqlx::query( - "SELECT seq, event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms FROM nostr_event WHERE event_id = ?", + "SELECT seq, event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms FROM nostr_events WHERE event_id = ?", ) .bind(event_id) .fetch_optional(&self.pool) @@ -186,7 +186,7 @@ impl RadrootsEventStore { event_id: &str, ) -> Result<Vec<RadrootsStoredEventTag>, RadrootsEventStoreError> { let rows = sqlx::query( - "SELECT event_id, tag_index, tag_name, tag_value, tag_json, contract_semantic, contract_value_type, relay_indexed FROM nostr_event_tag WHERE event_id = ? ORDER BY tag_index", + "SELECT event_id, tag_index, tag_name, tag_value, tag_json, contract_semantic, contract_value_type, relay_indexed FROM nostr_event_tags WHERE event_id = ? ORDER BY tag_index", ) .bind(event_id) .fetch_all(&self.pool) @@ -279,7 +279,7 @@ impl RadrootsEventStore { .map(|cursor| cursor.last_event_seq) .unwrap_or(0); let rows = sqlx::query( - "SELECT seq, event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms FROM nostr_event WHERE projection_eligible = 1 AND seq > ? ORDER BY seq ASC LIMIT ?", + "SELECT seq, event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms FROM nostr_events WHERE projection_eligible = 1 AND seq > ? ORDER BY seq ASC LIMIT ?", ) .bind(last_event_seq) .bind(i64::from(limit)) @@ -296,7 +296,7 @@ impl RadrootsEventStore { ) -> Result<Vec<RadrootsStoredEvent>, RadrootsEventStoreError> { validate_tag_query(tag_name, limit)?; let rows = sqlx::query( - "SELECT seq, event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms FROM nostr_event AS event WHERE projection_eligible = 1 AND EXISTS (SELECT 1 FROM nostr_event_tag AS tag WHERE tag.event_id = event.event_id AND tag.tag_name = ? AND tag.tag_value = ?) ORDER BY event.seq ASC LIMIT ?", + "SELECT seq, event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms FROM nostr_events AS event WHERE projection_eligible = 1 AND EXISTS (SELECT 1 FROM nostr_event_tags AS tag WHERE tag.event_id = event.event_id AND tag.tag_name = ? AND tag.tag_value = ?) ORDER BY event.seq ASC LIMIT ?", ) .bind(tag_name) .bind(tag_value) @@ -321,7 +321,7 @@ impl RadrootsEventStore { .collect::<Vec<_>>() .join(", "); let sql = format!( - "SELECT seq, event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms FROM nostr_event AS event WHERE projection_eligible = 1 AND contract_id IN ({placeholders}) AND EXISTS (SELECT 1 FROM nostr_event_tag AS tag WHERE tag.event_id = event.event_id AND tag.tag_name = ? AND tag.tag_value = ?) ORDER BY event.seq ASC LIMIT ?" + "SELECT seq, event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms FROM nostr_events AS event WHERE projection_eligible = 1 AND contract_id IN ({placeholders}) AND EXISTS (SELECT 1 FROM nostr_event_tags AS tag WHERE tag.event_id = event.event_id AND tag.tag_name = ? AND tag.tag_value = ?) ORDER BY event.seq ASC LIMIT ?" ); let mut query = sqlx::query(sql.as_str()); for contract_id in contract_ids { @@ -474,7 +474,7 @@ async fn insert_raw_event( .map(|contract| StoredEventClass::from_event_class(contract.class).as_str()); let projection_eligible = classification.base_projection_eligible(verification_status); let result = sqlx::query( - "INSERT OR IGNORE INTO nostr_event(event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "INSERT OR IGNORE INTO nostr_events(event_id, pubkey, created_at, kind, tags_json, content, sig, raw_json, verification_status, contract_status, contract_id, event_class, projection_eligible, inserted_at_ms, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", ) .bind(event.id.as_str()) .bind(event.author.as_str()) @@ -503,7 +503,7 @@ async fn event_seq( tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>, event_id: &str, ) -> Result<i64, RadrootsEventStoreError> { - let row = sqlx::query("SELECT seq FROM nostr_event WHERE event_id = ?") + let row = sqlx::query("SELECT seq FROM nostr_events WHERE event_id = ?") .bind(event_id) .fetch_one(&mut **tx) .await?; @@ -530,7 +530,7 @@ async fn insert_tags( let contract_value_type = tag_contract.map(|tag| tag_value_type_name(tag.value_type)); let relay_indexed = tag_contract.map(|tag| tag.relay_indexed).unwrap_or(false); sqlx::query( - "INSERT INTO nostr_event_tag(event_id, tag_index, tag_name, tag_value, tag_json, contract_semantic, contract_value_type, relay_indexed) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO nostr_event_tags(event_id, tag_index, tag_name, tag_value, tag_json, contract_semantic, contract_value_type, relay_indexed) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", ) .bind(event.id.as_str()) .bind(i64::try_from(index).map_err(|_| RadrootsEventStoreError::IntegerRange { @@ -1021,12 +1021,12 @@ mod tests { let store = RadrootsEventStore::open_memory().await.expect("open"); store.migrate_down().await.expect("down"); - let missing = sqlx::query("SELECT COUNT(*) FROM nostr_event") + let missing = sqlx::query("SELECT COUNT(*) FROM nostr_events") .fetch_one(store.pool()) .await .err() .expect("table should be removed"); - assert!(missing.to_string().contains("nostr_event")); + assert!(missing.to_string().contains("nostr_events")); } #[tokio::test] diff --git a/crates/outbox/migrations/0001_outbox.down.sql b/crates/outbox/migrations/0001_outbox.down.sql @@ -1,3 +1,3 @@ DROP TABLE outbox_event_relay_status; DROP TABLE outbox_event; -DROP TABLE outbox_operation; +DROP TABLE outbox_operations; diff --git a/crates/outbox/migrations/0001_outbox.up.sql b/crates/outbox/migrations/0001_outbox.up.sql @@ -1,4 +1,4 @@ -CREATE TABLE IF NOT EXISTS outbox_operation ( +CREATE TABLE IF NOT EXISTS outbox_operations ( operation_id INTEGER PRIMARY KEY AUTOINCREMENT, operation_kind TEXT NOT NULL, expected_pubkey TEXT NOT NULL, @@ -10,15 +10,15 @@ CREATE TABLE IF NOT EXISTS outbox_operation ( ); CREATE UNIQUE INDEX IF NOT EXISTS outbox_operation_idempotency_idx -ON outbox_operation(operation_kind, expected_pubkey, idempotency_key) +ON outbox_operations(operation_kind, expected_pubkey, idempotency_key) WHERE idempotency_key IS NOT NULL; CREATE INDEX IF NOT EXISTS outbox_operation_status_idx -ON outbox_operation(status, created_at_ms, operation_id); +ON outbox_operations(status, created_at_ms, operation_id); CREATE TABLE IF NOT EXISTS outbox_event ( outbox_event_id INTEGER PRIMARY KEY AUTOINCREMENT, - operation_id INTEGER NOT NULL REFERENCES outbox_operation(operation_id) ON DELETE CASCADE, + operation_id INTEGER NOT NULL REFERENCES outbox_operations(operation_id) ON DELETE CASCADE, event_id TEXT NOT NULL, expected_pubkey TEXT NOT NULL, draft_json TEXT NOT NULL, diff --git a/crates/outbox/src/model.rs b/crates/outbox/src/model.rs @@ -28,7 +28,7 @@ impl RadrootsOutboxOperationStatus { "failed_terminal" => Ok(Self::FailedTerminal), "cancelled" => Ok(Self::Cancelled), _ => Err(RadrootsOutboxError::InvalidStoredEnum { - field: "outbox_operation.status", + field: "outbox_operations.status", value: value.to_owned(), }), } diff --git a/crates/outbox/src/store.rs b/crates/outbox/src/store.rs @@ -160,7 +160,7 @@ impl RadrootsOutbox { } let operation = sqlx::query( - "INSERT INTO outbox_operation(operation_kind, expected_pubkey, idempotency_key, idempotency_digest, status, created_at_ms, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO outbox_operations(operation_kind, expected_pubkey, idempotency_key, idempotency_digest, status, created_at_ms, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?, ?)", ) .bind(input.operation_kind.as_str()) .bind(input.draft.expected_pubkey.as_str()) @@ -258,7 +258,7 @@ impl RadrootsOutbox { } let operation = sqlx::query( - "INSERT INTO outbox_operation(operation_kind, expected_pubkey, idempotency_key, idempotency_digest, status, created_at_ms, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO outbox_operations(operation_kind, expected_pubkey, idempotency_key, idempotency_digest, status, created_at_ms, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?, ?)", ) .bind(input.operation_kind.as_str()) .bind(input.draft.expected_pubkey.as_str()) @@ -318,7 +318,7 @@ impl RadrootsOutbox { operation_id: i64, ) -> Result<Option<RadrootsOutboxOperationRecord>, RadrootsOutboxError> { let row = sqlx::query( - "SELECT operation_id, operation_kind, expected_pubkey, idempotency_key, idempotency_digest, status, created_at_ms, updated_at_ms FROM outbox_operation WHERE operation_id = ?", + "SELECT operation_id, operation_kind, expected_pubkey, idempotency_key, idempotency_digest, status, created_at_ms, updated_at_ms FROM outbox_operations WHERE operation_id = ?", ) .bind(operation_id) .fetch_optional(&self.pool) @@ -755,7 +755,7 @@ impl RadrootsOutbox { if let Some(operation_status) = operation_status { sqlx::query( - "UPDATE outbox_operation SET status = ?, updated_at_ms = ? WHERE operation_id = ?", + "UPDATE outbox_operations SET status = ?, updated_at_ms = ? WHERE operation_id = ?", ) .bind(operation_status.as_str()) .bind(now_ms) @@ -875,7 +875,7 @@ impl RadrootsOutbox { } sqlx::query( - "UPDATE outbox_operation SET status = ?, updated_at_ms = ? WHERE operation_id = ?", + "UPDATE outbox_operations SET status = ?, updated_at_ms = ? WHERE operation_id = ?", ) .bind(operation_status.as_str()) .bind(now_ms) @@ -976,7 +976,7 @@ async fn existing_idempotent_operation( idempotency_key: &str, ) -> Result<Option<ExistingOperation>, RadrootsOutboxError> { let row = sqlx::query( - "SELECT o.operation_id, o.idempotency_digest, e.outbox_event_id, e.event_id FROM outbox_operation o JOIN outbox_event e ON e.operation_id = o.operation_id WHERE o.operation_kind = ? AND o.expected_pubkey = ? AND o.idempotency_key = ? ORDER BY e.outbox_event_id LIMIT 1", + "SELECT o.operation_id, o.idempotency_digest, e.outbox_event_id, e.event_id FROM outbox_operations o JOIN outbox_event e ON e.operation_id = o.operation_id WHERE o.operation_kind = ? AND o.expected_pubkey = ? AND o.idempotency_key = ? ORDER BY e.outbox_event_id LIMIT 1", ) .bind(operation_kind) .bind(expected_pubkey) @@ -1608,7 +1608,7 @@ mod tests { .expect_err("empty relays"); assert!(matches!(err, RadrootsOutboxError::EmptyTargetRelays)); - assert_eq!(table_count(&outbox, "outbox_operation").await, 0); + assert_eq!(table_count(&outbox, "outbox_operations").await, 0); assert_eq!(table_count(&outbox, "outbox_event").await, 0); assert_eq!(table_count(&outbox, "outbox_event_relay_status").await, 0); } @@ -1634,7 +1634,7 @@ mod tests { .expect_err("empty relays"); assert!(matches!(err, RadrootsOutboxError::EmptyTargetRelays)); - assert_eq!(table_count(&outbox, "outbox_operation").await, 0); + assert_eq!(table_count(&outbox, "outbox_operations").await, 0); assert_eq!(table_count(&outbox, "outbox_event").await, 0); assert_eq!(table_count(&outbox, "outbox_event_relay_status").await, 0); } @@ -1936,7 +1936,7 @@ mod tests { assert_eq!(second.status, RadrootsOutboxEnqueueStatus::Existing); assert_eq!(first.operation_id, second.operation_id); assert_eq!(first.outbox_event_id, second.outbox_event_id); - assert_eq!(table_count(&outbox, "outbox_operation").await, 1); + assert_eq!(table_count(&outbox, "outbox_operations").await, 1); assert_eq!(table_count(&outbox, "outbox_event").await, 1); let changed_draft = post_draft(FIXTURE_ALICE_PUBLIC_KEY_HEX, "changed"); @@ -1972,7 +1972,7 @@ mod tests { error, RadrootsOutboxError::SignedEventDraftMismatch(_) )); - assert_eq!(table_count(&outbox, "outbox_operation").await, 0); + assert_eq!(table_count(&outbox, "outbox_operations").await, 0); assert_eq!(table_count(&outbox, "outbox_event").await, 0); } @@ -1993,7 +1993,7 @@ mod tests { error, RadrootsOutboxError::SignedEventDraftMismatch(_) )); - assert_eq!(table_count(&outbox, "outbox_operation").await, 0); + assert_eq!(table_count(&outbox, "outbox_operations").await, 0); assert_eq!(table_count(&outbox, "outbox_event").await, 0); }