From d4757230876ea6e81d83fd4575e2f9d51ddf7c6c Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 2 Sep 2023 13:35:30 -0500 Subject: [PATCH] Finish writing migrations & generate diesel schema --- src/repo/postgres.rs | 1 + .../migrations/V0000__enable_pgcrypto.rs | 11 ++ .../migrations/V0001__create_hashes.rs | 2 + .../migrations/V0002__create_variants.rs | 30 +++++ .../migrations/V0003__create_aliases.rs | 25 ++++ .../migrations/V0004__create_settings.rs | 21 ++++ .../migrations/V0005__create_details.rs | 17 +++ .../migrations/V0006__create_queue.rs | 53 ++++++++ .../V0007__create_store_migrations.rs | 16 +++ .../migrations/V0008__create_proxies.rs | 25 ++++ .../migrations/V0009__create_uploads.rs | 38 ++++++ src/repo/postgres/schema.rs | 114 ++++++++++++++++++ 12 files changed, 353 insertions(+) create mode 100644 src/repo/postgres/migrations/V0000__enable_pgcrypto.rs create mode 100644 src/repo/postgres/migrations/V0002__create_variants.rs create mode 100644 src/repo/postgres/migrations/V0003__create_aliases.rs create mode 100644 src/repo/postgres/migrations/V0004__create_settings.rs create mode 100644 src/repo/postgres/migrations/V0005__create_details.rs create mode 100644 src/repo/postgres/migrations/V0006__create_queue.rs create mode 100644 src/repo/postgres/migrations/V0007__create_store_migrations.rs create mode 100644 src/repo/postgres/migrations/V0008__create_proxies.rs create mode 100644 src/repo/postgres/migrations/V0009__create_uploads.rs create mode 100644 src/repo/postgres/schema.rs diff --git a/src/repo/postgres.rs b/src/repo/postgres.rs index 7c3b031..f4e71da 100644 --- a/src/repo/postgres.rs +++ b/src/repo/postgres.rs @@ -3,6 +3,7 @@ mod embedded { embed_migrations!("./src/repo/postgres/migrations"); } +mod schema; use diesel_async::{ pooled_connection::{ diff --git a/src/repo/postgres/migrations/V0000__enable_pgcrypto.rs b/src/repo/postgres/migrations/V0000__enable_pgcrypto.rs new file mode 100644 index 0000000..44eb85c --- /dev/null +++ b/src/repo/postgres/migrations/V0000__enable_pgcrypto.rs @@ -0,0 +1,11 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.inject_custom("CREATE EXTENSION pgcrypto;"); + + m.make::().to_string() +} diff --git a/src/repo/postgres/migrations/V0001__create_hashes.rs b/src/repo/postgres/migrations/V0001__create_hashes.rs index 30455c3..9829585 100644 --- a/src/repo/postgres/migrations/V0001__create_hashes.rs +++ b/src/repo/postgres/migrations/V0001__create_hashes.rs @@ -25,6 +25,8 @@ pub(crate) fn migration() -> String { .nullable(false) .default(AutogenFunction::CurrentTimestamp), ); + + t.add_index("ordered_hash_index", types::index(["created_at", "hash"])); }); m.make::().to_string() diff --git a/src/repo/postgres/migrations/V0002__create_variants.rs b/src/repo/postgres/migrations/V0002__create_variants.rs new file mode 100644 index 0000000..8377ddc --- /dev/null +++ b/src/repo/postgres/migrations/V0002__create_variants.rs @@ -0,0 +1,30 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.create_table("variants", |t| { + t.inject_custom(r#""id" UUID PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL UNIQUE"#); + t.add_column("hash", types::binary().nullable(false)); + t.add_column("variant", types::text().nullable(false)); + t.add_column("identifier", types::text().nullable(false)); + t.add_column( + "accessed", + types::datetime() + .nullable(false) + .default(AutogenFunction::CurrentTimestamp), + ); + + t.add_foreign_key(&["hash"], "hashes", &["hash"]); + t.add_index( + "hash_variant_index", + types::index(["hash", "variant"]).unique(true), + ); + }); + + let s = m.make::().to_string(); + println!("{s}"); + s +} diff --git a/src/repo/postgres/migrations/V0003__create_aliases.rs b/src/repo/postgres/migrations/V0003__create_aliases.rs new file mode 100644 index 0000000..a8aa37f --- /dev/null +++ b/src/repo/postgres/migrations/V0003__create_aliases.rs @@ -0,0 +1,25 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.create_table("aliases", |t| { + t.add_column( + "alias", + types::text() + .size(60) + .primary(true) + .unique(true) + .nullable(false), + ); + t.add_column("hash", types::binary().nullable(false)); + t.add_column("token", types::text().size(60).nullable(false)); + + t.add_foreign_key(&["hash"], "hashes", &["hash"]); + t.add_index("aliases_hash_index", types::index(["hash"])); + }); + + m.make::().to_string() +} diff --git a/src/repo/postgres/migrations/V0004__create_settings.rs b/src/repo/postgres/migrations/V0004__create_settings.rs new file mode 100644 index 0000000..37011ac --- /dev/null +++ b/src/repo/postgres/migrations/V0004__create_settings.rs @@ -0,0 +1,21 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.create_table("settings", |t| { + t.add_column( + "key", + types::text() + .size(80) + .primary(true) + .unique(true) + .nullable(false), + ); + t.add_column("value", types::text().size(80).nullable(false)); + }); + + m.make::().to_string() +} diff --git a/src/repo/postgres/migrations/V0005__create_details.rs b/src/repo/postgres/migrations/V0005__create_details.rs new file mode 100644 index 0000000..e324caa --- /dev/null +++ b/src/repo/postgres/migrations/V0005__create_details.rs @@ -0,0 +1,17 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.create_table("details", |t| { + t.add_column( + "identifier", + types::text().primary(true).unique(true).nullable(false), + ); + t.add_column("details", types::custom("jsonb").nullable(false)); + }); + + m.make::().to_string() +} diff --git a/src/repo/postgres/migrations/V0006__create_queue.rs b/src/repo/postgres/migrations/V0006__create_queue.rs new file mode 100644 index 0000000..293ff97 --- /dev/null +++ b/src/repo/postgres/migrations/V0006__create_queue.rs @@ -0,0 +1,53 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.inject_custom("CREATE TYPE job_status AS ENUM ('new', 'running');"); + + m.create_table("queue", |t| { + t.inject_custom(r#""id" UUID PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL UNIQUE"#); + t.add_column("queue", types::text().size(50).nullable(false)); + t.add_column("job", types::custom("jsonb").nullable(false)); + t.add_column("status", types::custom("job_status").nullable(false)); + t.add_column( + "queue_time", + types::datetime() + .nullable(false) + .default(AutogenFunction::CurrentTimestamp), + ); + t.add_column("heartbeat", types::datetime()); + + t.add_index("queue_status_index", types::index(["queue", "status"])); + t.add_index("heartbeat_index", types::index(["heartbeat"])); + }); + + m.inject_custom( + r#" +CREATE OR REPLACE FUNCTION queue_status_notify() + RETURNS trigger AS +$$ +BEGIN + PERFORM pg_notify('queue_status_channel', NEW.id::text); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + "# + .trim(), + ); + + m.inject_custom( + r#" +CREATE TRIGGER queue_status + AFTER INSERT OR UPDATE OF status + ON queue + FOR EACH ROW +EXECUTE PROCEDURE queue_status_notify(); + "# + .trim(), + ); + + m.make::().to_string() +} diff --git a/src/repo/postgres/migrations/V0007__create_store_migrations.rs b/src/repo/postgres/migrations/V0007__create_store_migrations.rs new file mode 100644 index 0000000..fe957b0 --- /dev/null +++ b/src/repo/postgres/migrations/V0007__create_store_migrations.rs @@ -0,0 +1,16 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.create_table("store_migrations", |t| { + t.add_column( + "identifier", + types::text().primary(true).nullable(false).unique(true), + ); + }); + + m.make::().to_string() +} diff --git a/src/repo/postgres/migrations/V0008__create_proxies.rs b/src/repo/postgres/migrations/V0008__create_proxies.rs new file mode 100644 index 0000000..bbb6c5d --- /dev/null +++ b/src/repo/postgres/migrations/V0008__create_proxies.rs @@ -0,0 +1,25 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.create_table("proxies", |t| { + t.add_column( + "url", + types::text().primary(true).unique(true).nullable(false), + ); + t.add_column("alias", types::text().nullable(false)); + t.add_column( + "accessed", + types::datetime() + .nullable(false) + .default(AutogenFunction::CurrentTimestamp), + ); + + t.add_foreign_key(&["alias"], "aliases", &["alias"]); + }); + + m.make::().to_string() +} diff --git a/src/repo/postgres/migrations/V0009__create_uploads.rs b/src/repo/postgres/migrations/V0009__create_uploads.rs new file mode 100644 index 0000000..9214ec4 --- /dev/null +++ b/src/repo/postgres/migrations/V0009__create_uploads.rs @@ -0,0 +1,38 @@ +use barrel::backend::Pg; +use barrel::functions::AutogenFunction; +use barrel::{types, Migration}; + +pub(crate) fn migration() -> String { + let mut m = Migration::new(); + + m.create_table("uploads", |t| { + t.inject_custom(r#""id" UUID PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL UNIQUE"#); + t.add_column("result", types::custom("jsonb")); + }); + + m.inject_custom( + r#" +CREATE OR REPLACE FUNCTION upload_completion_notify() + RETURNS trigger AS +$$ +BEGIN + PERFORM pg_notify('upload_completion_channel', NEW.id::text); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + "# + .trim(), + ); + + m.inject_custom( + r#" +CREATE TRIGGER upload_result + AFTER INSERT OR UPDATE OF result + ON uploads + FOR EACH ROW +EXECUTE PROCEDURE upload_completion_notify(); + "#, + ); + + m.make::().to_string() +} diff --git a/src/repo/postgres/schema.rs b/src/repo/postgres/schema.rs new file mode 100644 index 0000000..3ab3e46 --- /dev/null +++ b/src/repo/postgres/schema.rs @@ -0,0 +1,114 @@ +// @generated automatically by Diesel CLI. + +pub mod sql_types { + #[derive(diesel::sql_types::SqlType)] + #[diesel(postgres_type(name = "job_status"))] + pub struct JobStatus; +} + +diesel::table! { + aliases (alias) { + alias -> Text, + hash -> Bytea, + token -> Text, + } +} + +diesel::table! { + details (identifier) { + identifier -> Text, + #[sql_name = "details"] + details_json -> Jsonb, + } +} + +diesel::table! { + hashes (hash) { + hash -> Bytea, + identifier -> Text, + motion_identifier -> Nullable, + created_at -> Timestamp, + } +} + +diesel::table! { + proxies (url) { + url -> Text, + alias -> Text, + accessed -> Timestamp, + } +} + +diesel::table! { + use diesel::sql_types::*; + use super::sql_types::JobStatus; + + queue (id) { + id -> Uuid, + #[sql_name = "queue"] + queue_name -> Text, + job -> Jsonb, + status -> JobStatus, + queue_time -> Timestamp, + heartbeat -> Timestamp, + } +} + +diesel::table! { + refinery_schema_history (version) { + version -> Int4, + #[max_length = 255] + name -> Nullable, + #[max_length = 255] + applied_on -> Nullable, + #[max_length = 255] + checksum -> Nullable, + } +} + +diesel::table! { + settings (key) { + key -> Text, + value -> Text, + } +} + +diesel::table! { + store_migrations (identifier) { + identifier -> Text, + } +} + +diesel::table! { + uploads (id) { + id -> Uuid, + result -> Jsonb, + } +} + +diesel::table! { + variants (id) { + id -> Uuid, + hash -> Bytea, + variant -> Text, + identifier -> Text, + accessed -> Timestamp, + } +} + +diesel::joinable!(aliases -> hashes (hash)); +diesel::joinable!(proxies -> aliases (alias)); +diesel::joinable!(variants -> hashes (hash)); + +diesel::allow_tables_to_appear_in_same_query!( + aliases, + details, + hashes, + proxies, + queue, + refinery_schema_history, + settings, + store_migrations, + uploads, + variants, +);