diff --git a/catalyst-gateway/Earthfile b/catalyst-gateway/Earthfile index 1cde02848f7..bde5adb213f 100644 --- a/catalyst-gateway/Earthfile +++ b/catalyst-gateway/Earthfile @@ -124,3 +124,19 @@ check-builder-src-cache: RUN diff ../src_fingerprint.txt ../src_fingerprint_uncached.txt \ || (echo "ERROR: Source fingerprints do not match. Caching Error Detected!!" && exit 1) \ && echo "Source fingerprints match. Caching OK." + +test: + FROM +builder-src + + COPY docker-compose.yml . + + ENV EVENT_DB_URL "postgres://catalyst-event-dev:CHANGE_ME@localhost/CatalystEventDev" + + WITH DOCKER \ + --compose "./docker-compose.yml" \ + --load ./event-db+build \ + --pull alpine:3.20.3 \ + --service event-db-is-running + RUN --mount=$EARTHLY_RUST_CARGO_HOME_CACHE --mount=$EARTHLY_RUST_TARGET_CACHE \ + cargo nextest run --release --run-ignored=only signed_docs + END \ No newline at end of file diff --git a/catalyst-gateway/bin/Cargo.toml b/catalyst-gateway/bin/Cargo.toml index fbba8109c1b..4f664ec101d 100644 --- a/catalyst-gateway/bin/Cargo.toml +++ b/catalyst-gateway/bin/Cargo.toml @@ -43,6 +43,7 @@ tokio-postgres = { version = "0.7.12", features = [ "with-chrono-0_4", "with-serde_json-1", "with-time-0_3", + "with-uuid-1" ] } tokio = { version = "1.41.0", features = ["rt", "macros", "rt-multi-thread"] } dotenvy = "0.15.7" @@ -77,7 +78,7 @@ poem-openapi = { version = "5.1.2", features = [ "url", "chrono", ] } -uuid = { version = "1.11.0", features = ["v4", "serde"] } +uuid = { version = "1.11.0", features = ["v4", "v7", "serde"] } ulid = { version = "1.1.3", features = ["serde", "uuid"] } blake2b_simd = "1.0.2" url = "2.5.3" diff --git a/catalyst-gateway/bin/src/db/event/mod.rs b/catalyst-gateway/bin/src/db/event/mod.rs index e0e28b1b923..1bc4bd1d476 100644 --- a/catalyst-gateway/bin/src/db/event/mod.rs +++ b/catalyst-gateway/bin/src/db/event/mod.rs @@ -18,6 +18,7 @@ pub(crate) mod config; pub(crate) mod error; pub(crate) mod legacy; pub(crate) mod schema_check; +pub(crate) mod signed_docs; /// Database version this crate matches. /// Must equal the last Migrations Version Number from `event-db/migrations`. @@ -212,7 +213,7 @@ impl EventDB { /// /// The env var "`DATABASE_URL`" can be set directly as an anv var, or in a /// `.env` file. -pub(crate) fn establish_connection() { +pub fn establish_connection() { let (url, user, pass) = Settings::event_db_settings(); // This was pre-validated and can't fail, but provide default in the impossible case it diff --git a/catalyst-gateway/bin/src/db/event/signed_docs/mod.rs b/catalyst-gateway/bin/src/db/event/signed_docs/mod.rs new file mode 100644 index 00000000000..19ae3a854b3 --- /dev/null +++ b/catalyst-gateway/bin/src/db/event/signed_docs/mod.rs @@ -0,0 +1,32 @@ +//! Signed docs queries + +#[cfg(test)] +mod tests; + +use super::EventDB; + +/// Insert sql query +const INSERT_SIGNED_DOCS: &str = include_str!("./sql/insert_signed_documents.sql"); + +/// Make an insert query into the `event-db` by adding data into the `signed_docs` table +/// +/// * IF the record primary key (id,ver) does not exist, then add the new record. Return +/// success. +/// * IF the record does exist, but all values are the same as stored, return Success. +/// * Otherwise return an error. (Can not over-write an existing record with new data). +/// +/// # Arguments: +/// - `id` is a UUID v7 +/// - `ver` is a UUID v7 +/// - `doc_type` is a UUID v4 +#[allow(dead_code)] +pub(crate) async fn insert_signed_docs( + id: &uuid::Uuid, ver: &uuid::Uuid, doc_type: &uuid::Uuid, author: &String, + metadata: &Option, payload: &Option, raw: &Vec, +) -> anyhow::Result<()> { + EventDB::modify(INSERT_SIGNED_DOCS, &[ + id, ver, doc_type, author, metadata, payload, raw, + ]) + .await?; + Ok(()) +} diff --git a/catalyst-gateway/bin/src/db/event/signed_docs/sql/insert_signed_documents.sql b/catalyst-gateway/bin/src/db/event/signed_docs/sql/insert_signed_documents.sql new file mode 100644 index 00000000000..61183ea693a --- /dev/null +++ b/catalyst-gateway/bin/src/db/event/signed_docs/sql/insert_signed_documents.sql @@ -0,0 +1,12 @@ +INSERT INTO signed_docs +( + id, + ver, + type, + author, + metadata, + payload, + raw +) +VALUES +($1, $2, $3, $4, $5, $6, $7) diff --git a/catalyst-gateway/bin/src/db/event/signed_docs/tests/mod.rs b/catalyst-gateway/bin/src/db/event/signed_docs/tests/mod.rs new file mode 100644 index 00000000000..a65c9206adc --- /dev/null +++ b/catalyst-gateway/bin/src/db/event/signed_docs/tests/mod.rs @@ -0,0 +1,50 @@ +//! Integration tests of the `signed docs` queries + +use super::*; +use crate::db::event::establish_connection; + +#[ignore = "An integration test which requires a running EventDB instance, disabled from `testunit` CI run"] +#[tokio::test] +async fn some_test() { + establish_connection(); + + let docs = [ + ( + uuid::Uuid::now_v7(), + uuid::Uuid::now_v7(), + uuid::Uuid::new_v4(), + "Alex".to_string(), + &Some(serde_json::Value::Null), + &Some(serde_json::Value::Null), + vec![1, 2, 3, 4], + ), + ( + uuid::Uuid::now_v7(), + uuid::Uuid::now_v7(), + uuid::Uuid::new_v4(), + "Steven".to_string(), + &Some(serde_json::Value::Null), + &Some(serde_json::Value::Null), + vec![5, 6, 7, 8], + ), + ( + uuid::Uuid::now_v7(), + uuid::Uuid::now_v7(), + uuid::Uuid::new_v4(), + "Sasha".to_string(), + &None, + &None, + vec![9, 10, 11, 12], + ), + ]; + + for (id, ver, doc_type, author, metadata, payload, raw) in &docs { + insert_signed_docs(id, ver, doc_type, author, metadata, payload, raw) + .await + .unwrap(); + // // try to insert the same data again + // insert_signed_docs(id, ver, doc_type, author, metadata, payload, raw) + // .await + // .unwrap(); + } +} diff --git a/catalyst-gateway/blueprint.cue b/catalyst-gateway/blueprint.cue index c81c19d56c6..9e36433f3f4 100644 --- a/catalyst-gateway/blueprint.cue +++ b/catalyst-gateway/blueprint.cue @@ -12,4 +12,9 @@ project: { } } } + ci: { + targets: { + test: privileged: true + } + } } diff --git a/catalyst-gateway/docker-compose.yml b/catalyst-gateway/docker-compose.yml index 4b2d833735b..00b2a348764 100644 --- a/catalyst-gateway/docker-compose.yml +++ b/catalyst-gateway/docker-compose.yml @@ -1,10 +1,7 @@ -version: "3" - services: event-db: image: event-db:latest environment: - # Required environment variables for migrations - DB_HOST=localhost - DB_PORT=5432 - DB_NAME=CatalystEventDev @@ -16,7 +13,6 @@ services: - INIT_AND_DROP_DB=true - WITH_MIGRATIONS=true - - WITH_SEED_DATA=true ports: - 5432:5432 healthcheck: @@ -25,6 +21,14 @@ services: timeout: 5s retries: 10 +# it is a helper service to wait until the event-db will be ready +# mainly its a trick for Earthly how to wait until service will be fully functional + event-db-is-running: + image: alpine:3.20.3 + depends_on: + event-db: + condition: service_healthy + cat-gateway: image: cat-gateway:latest environment: diff --git a/catalyst-gateway/event-db/migrations/V2__signed_documents.sql b/catalyst-gateway/event-db/migrations/V2__signed_documents.sql index 523680ef9f2..28ff361d4a3 100644 --- a/catalyst-gateway/event-db/migrations/V2__signed_documents.sql +++ b/catalyst-gateway/event-db/migrations/V2__signed_documents.sql @@ -12,11 +12,11 @@ -- Signed Documents Storage Repository defintion. CREATE TABLE IF NOT EXISTS signed_docs ( - id UUID NOT NULL, -- Actually a ULID - ver UUID NOT NULL, -- Actually a ULID - type UUID NOT NULL, -- Yes its a UUID this time + id UUID NOT NULL, -- UUID v7 + ver UUID NOT NULL, -- UUID v7 + type UUID NOT NULL, -- UUID v4 author TEXT NOT NULL, - metadata JSONB NOT NULL, + metadata JSONB NULL, payload JSONB NULL, raw BYTEA NOT NULL,