From 1059c5f37c3e8d8d00ff52361a3d728f66b3323f Mon Sep 17 00:00:00 2001 From: Nick Gerace Date: Wed, 11 Dec 2024 12:11:54 -0500 Subject: [PATCH] Migrate all remaining IDs to si-id This commit migrates all remaining IDs that I could find to si-id. It adds sea-orm as a dependency to si-id, which will only be used if the IDs use it, though it is now included in the dependency chain. The methodology to finding these was searching for "struct.*Id" and "struct.*Ulid" throughout the codebase. Eventually, it may be beneficial to remove the ulid dependency from all crates except for si-id to see if any hidden ones remain, but this should have covered all of them. This commit is a follow-up to #5099 and #5093. There is potential future work to clean-up ID call sites, which would involve reducing "pub use" statements, but we may not actually want that. In addition, we may also want to restrict the usage of the third party ulid crate throughout the repository and make crates go through si-id, but we may not actually want that either. Because neither of these action items are desirable in the near term, we can call the si-id work done... for now! Signed-off-by: Nick Gerace --- Cargo.lock | 4 +- .../src/workspace_snapshot/vector_clock.rs | 3 +- lib/module-index-server/BUCK | 1 + lib/module-index-server/Cargo.toml | 1 + .../src/models/si_module.rs | 10 +- .../src/models/si_module/module_id.rs | 79 ------- .../src/models/si_module/schema_id.rs | 84 -------- .../src/models/si_module/schema_variant_id.rs | 87 -------- .../src/routes/upsert_module_route.rs | 15 +- lib/si-events-rs/BUCK | 1 - lib/si-events-rs/Cargo.toml | 1 - lib/si-events-rs/src/func_run.rs | 4 +- lib/si-events-rs/src/func_run_log.rs | 52 +---- lib/si-events-rs/src/vector_clock_id.rs | 69 +------ lib/si-id/BUCK | 1 + lib/si-id/Cargo.toml | 1 + lib/si-id/src/conversions.rs | 11 +- lib/si-id/src/lib.rs | 14 +- lib/si-id/src/macros.rs | 193 +++++++++++++++++- lib/si-layer-cache/BUCK | 1 + lib/si-layer-cache/Cargo.toml | 1 + lib/si-layer-cache/src/activities.rs | 47 +---- lib/si-layer-cache/src/event.rs | 27 +-- 23 files changed, 245 insertions(+), 462 deletions(-) delete mode 100644 lib/module-index-server/src/models/si_module/module_id.rs delete mode 100644 lib/module-index-server/src/models/si_module/schema_id.rs delete mode 100644 lib/module-index-server/src/models/si_module/schema_variant_id.rs diff --git a/Cargo.lock b/Cargo.lock index 0907e55ce7..19490dc11e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4209,6 +4209,7 @@ dependencies = [ "serde_json", "si-data-pg", "si-hash", + "si-id", "si-jwt-public-key", "si-pkg", "si-posthog", @@ -6570,7 +6571,6 @@ dependencies = [ "si-id", "strum", "thiserror 1.0.69", - "ulid", "xxhash-rust", ] @@ -6619,6 +6619,7 @@ version = "0.1.0" dependencies = [ "derive_more", "postgres-types", + "sea-orm", "serde", "ulid", ] @@ -6660,6 +6661,7 @@ dependencies = [ "si-data-nats", "si-data-pg", "si-events", + "si-id", "si-runtime", "si-std", "strum", diff --git a/lib/dal/src/workspace_snapshot/vector_clock.rs b/lib/dal/src/workspace_snapshot/vector_clock.rs index 9f75665a2c..143f9e16fc 100644 --- a/lib/dal/src/workspace_snapshot/vector_clock.rs +++ b/lib/dal/src/workspace_snapshot/vector_clock.rs @@ -54,8 +54,7 @@ impl VectorClock { &self, change_set_id_filter: Option, ) -> Option<(VectorClockId, LamportClock)> { - let maybe_change_set_id = change_set_id_filter - .map(|change_set_id| VectorClockChangeSetId::new(change_set_id.into_inner().into())); + let maybe_change_set_id = change_set_id_filter.map(VectorClockChangeSetId::from); self.entries .iter() .filter(|(clock_id, _)| { diff --git a/lib/module-index-server/BUCK b/lib/module-index-server/BUCK index c3745d278f..d548217827 100644 --- a/lib/module-index-server/BUCK +++ b/lib/module-index-server/BUCK @@ -8,6 +8,7 @@ rust_library( "//lib/module-index-types:module-index-types", "//lib/si-data-pg:si-data-pg", "//lib/si-hash:si-hash", + "//lib/si-id:si-id", "//lib/si-jwt-public-key:si-jwt-public-key", "//lib/si-pkg:si-pkg", "//lib/si-posthog-rs:si-posthog", diff --git a/lib/module-index-server/Cargo.toml b/lib/module-index-server/Cargo.toml index 46039d4501..c9a86596e7 100644 --- a/lib/module-index-server/Cargo.toml +++ b/lib/module-index-server/Cargo.toml @@ -14,6 +14,7 @@ buck2-resources = { path = "../../lib/buck2-resources" } module-index-types = { path = "../../lib/module-index-types" } si-data-pg = { path = "../../lib/si-data-pg" } si-hash = { path = "../../lib/si-hash" } +si-id = { path = "../../lib/si-id" } si-jwt-public-key = { path = "../../lib/si-jwt-public-key" } si-pkg = { path = "../../lib/si-pkg" } si-posthog = { path = "../../lib/si-posthog-rs" } diff --git a/lib/module-index-server/src/models/si_module.rs b/lib/module-index-server/src/models/si_module.rs index 8a5e95de58..69fac904f8 100644 --- a/lib/module-index-server/src/models/si_module.rs +++ b/lib/module-index-server/src/models/si_module.rs @@ -3,13 +3,9 @@ use sea_orm::{entity::prelude::*, sea_query, TryGetError}; use serde::{Deserialize, Serialize}; use std::str::FromStr; -pub mod module_id; -pub mod schema_id; -pub mod schema_variant_id; - -pub use module_id::ModuleId; -pub use schema_id::SchemaId; -pub use schema_variant_id::SchemaVariantId; +pub use si_id::ModuleIndexModuleId as ModuleId; +pub use si_id::SchemaId; +pub use si_id::SchemaVariantId; #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/lib/module-index-server/src/models/si_module/module_id.rs b/lib/module-index-server/src/models/si_module/module_id.rs deleted file mode 100644 index b13f6d7a0e..0000000000 --- a/lib/module-index-server/src/models/si_module/module_id.rs +++ /dev/null @@ -1,79 +0,0 @@ -use sea_orm::{entity::prelude::*, sea_query, TryGetError}; -use serde::{Deserialize, Serialize}; -use ulid::Ulid; - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct ModuleId(pub Ulid); - -impl From for Value { - fn from(source: ModuleId) -> Self { - Value::String(Some(Box::new(source.0.to_string()))) - } -} - -impl std::fmt::Display for ModuleId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl TryFrom for ModuleId { - type Error = sea_orm::DbErr; - fn try_from(s: String) -> Result { - Ok(ModuleId( - Ulid::from_string(&s).map_err(|err| DbErr::Type(err.to_string()))?, - )) - } -} - -impl sea_orm::TryFromU64 for ModuleId { - fn try_from_u64(_: u64) -> Result { - Err(sea_orm::DbErr::Exec(sea_orm::RuntimeErr::Internal( - format!("{} cannot be converted from u64", stringify!(ModuleId)), - ))) - } -} - -impl From for String { - fn from(val: ModuleId) -> Self { - val.0.to_string() - } -} - -impl sea_orm::sea_query::Nullable for ModuleId { - fn null() -> sea_orm::Value { - sea_orm::Value::String(None) - } -} - -impl sea_orm::TryGetable for ModuleId { - fn try_get_by(res: &QueryResult, idx: I) -> Result { - let json_str: String = res.try_get_by(idx).map_err(TryGetError::DbErr)?; - Ulid::from_string(&json_str) - .map_err(|e| TryGetError::DbErr(DbErr::Type(e.to_string()))) - .map(ModuleId) - } -} - -impl sea_query::ValueType for ModuleId { - fn try_from(v: Value) -> Result { - match v { - Value::String(Some(x)) => Ok(ModuleId( - Ulid::from_string(&x).map_err(|_| sea_query::ValueTypeErr)?, - )), - _ => Err(sea_query::ValueTypeErr), - } - } - - fn type_name() -> String { - stringify!(ModuleId).to_owned() - } - - fn array_type() -> sea_orm::sea_query::ArrayType { - sea_orm::sea_query::ArrayType::String - } - - fn column_type() -> sea_query::ColumnType { - sea_query::ColumnType::String(StringLen::None) - } -} diff --git a/lib/module-index-server/src/models/si_module/schema_id.rs b/lib/module-index-server/src/models/si_module/schema_id.rs deleted file mode 100644 index 57aa035b1a..0000000000 --- a/lib/module-index-server/src/models/si_module/schema_id.rs +++ /dev/null @@ -1,84 +0,0 @@ -use sea_orm::{entity::prelude::*, sea_query, TryGetError}; -use serde::{Deserialize, Serialize}; -use ulid::Ulid; - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct SchemaId(pub Ulid); - -impl From for Value { - fn from(source: SchemaId) -> Self { - Value::String(Some(Box::new(source.0.to_string()))) - } -} - -impl std::fmt::Display for SchemaId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl TryFrom for SchemaId { - type Error = sea_orm::DbErr; - fn try_from(s: String) -> Result { - Ok(SchemaId( - Ulid::from_string(&s).map_err(|err| DbErr::Type(err.to_string()))?, - )) - } -} - -impl sea_orm::TryFromU64 for SchemaId { - fn try_from_u64(_: u64) -> Result { - Err(sea_orm::DbErr::Exec(sea_orm::RuntimeErr::Internal( - format!("{} cannot be converted from u64", stringify!(SchemaId)), - ))) - } -} - -impl From for String { - fn from(val: SchemaId) -> Self { - val.0.to_string() - } -} - -impl sea_orm::sea_query::Nullable for SchemaId { - fn null() -> sea_orm::Value { - sea_orm::Value::String(None) - } -} - -impl sea_orm::TryGetable for SchemaId { - fn try_get_by(res: &QueryResult, idx: I) -> Result { - let json_str: String = - res.try_get_by(idx) - .map_err(TryGetError::DbErr) - .and_then(|opt: Option| { - opt.ok_or(sea_orm::TryGetError::Null("null".to_string())) - })?; - Ulid::from_string(&json_str) - .map_err(|e| TryGetError::DbErr(DbErr::Type(e.to_string()))) - .map(SchemaId) - } -} - -impl sea_query::ValueType for SchemaId { - fn try_from(v: Value) -> Result { - match v { - Value::String(Some(x)) => Ok(SchemaId( - Ulid::from_string(&x).map_err(|_| sea_query::ValueTypeErr)?, - )), - _ => Err(sea_query::ValueTypeErr), - } - } - - fn type_name() -> String { - stringify!(SchemaId).to_owned() - } - - fn array_type() -> sea_orm::sea_query::ArrayType { - sea_orm::sea_query::ArrayType::String - } - - fn column_type() -> sea_query::ColumnType { - sea_query::ColumnType::String(StringLen::None) - } -} diff --git a/lib/module-index-server/src/models/si_module/schema_variant_id.rs b/lib/module-index-server/src/models/si_module/schema_variant_id.rs deleted file mode 100644 index 77a6fd5669..0000000000 --- a/lib/module-index-server/src/models/si_module/schema_variant_id.rs +++ /dev/null @@ -1,87 +0,0 @@ -use sea_orm::{entity::prelude::*, sea_query, TryGetError}; -use serde::{Deserialize, Serialize}; -use ulid::Ulid; - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct SchemaVariantId(pub Ulid); - -impl From for Value { - fn from(source: SchemaVariantId) -> Self { - Value::String(Some(Box::new(source.0.to_string()))) - } -} - -impl std::fmt::Display for SchemaVariantId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl TryFrom for SchemaVariantId { - type Error = sea_orm::DbErr; - fn try_from(s: String) -> Result { - Ok(SchemaVariantId( - Ulid::from_string(&s).map_err(|err| DbErr::Type(err.to_string()))?, - )) - } -} - -impl sea_orm::TryFromU64 for SchemaVariantId { - fn try_from_u64(_: u64) -> Result { - Err(sea_orm::DbErr::Exec(sea_orm::RuntimeErr::Internal( - format!( - "{} cannot be converted from u64", - stringify!(SchemaVariantId) - ), - ))) - } -} - -impl From for String { - fn from(val: SchemaVariantId) -> Self { - val.0.to_string() - } -} - -impl sea_orm::sea_query::Nullable for SchemaVariantId { - fn null() -> sea_orm::Value { - sea_orm::Value::String(None) - } -} - -impl sea_orm::TryGetable for SchemaVariantId { - fn try_get_by(res: &QueryResult, idx: I) -> Result { - let json_str: String = - res.try_get_by(idx) - .map_err(TryGetError::DbErr) - .and_then(|opt: Option| { - opt.ok_or(sea_orm::TryGetError::Null("null".to_string())) - })?; - Ulid::from_string(&json_str) - .map_err(|e| TryGetError::DbErr(DbErr::Type(e.to_string()))) - .map(SchemaVariantId) - } -} - -impl sea_query::ValueType for SchemaVariantId { - fn try_from(v: Value) -> Result { - match v { - Value::String(Some(x)) => Ok(SchemaVariantId( - Ulid::from_string(&x).map_err(|_| sea_query::ValueTypeErr)?, - )), - _ => Err(sea_query::ValueTypeErr), - } - } - - fn type_name() -> String { - stringify!(SchemaVariantId).to_owned() - } - - fn array_type() -> sea_orm::sea_query::ArrayType { - sea_orm::sea_query::ArrayType::String - } - - fn column_type() -> sea_query::ColumnType { - sea_query::ColumnType::String(StringLen::None) - } -} diff --git a/lib/module-index-server/src/routes/upsert_module_route.rs b/lib/module-index-server/src/routes/upsert_module_route.rs index 5661313027..5ffcd5b08b 100644 --- a/lib/module-index-server/src/routes/upsert_module_route.rs +++ b/lib/module-index-server/src/routes/upsert_module_route.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use axum::{ extract::{multipart::MultipartError, Multipart}, response::{IntoResponse, Response}, @@ -18,7 +20,6 @@ use serde::{Deserialize, Serialize}; use si_pkg::{SiPkg, SiPkgError, SiPkgKind}; use telemetry::prelude::*; use thiserror::Error; -use ulid::Ulid; use crate::{ extract::{Authorization, DbConnection, ExtractedS3Bucket}, @@ -121,11 +122,11 @@ pub async fn upsert_module_route( SiPkgKind::Module => ModuleKind::Module, }; - let new_schema_id = Some(SchemaId(Ulid::new())); + let new_schema_id = Some(SchemaId::new()); let schema_id = match module_kind { ModuleKind::WorkspaceBackup => None, ModuleKind::Module => match module_schema_id { - Some(schema_id_string) => Some(SchemaId(Ulid::from_string(&schema_id_string)?)), + Some(schema_id_string) => Some(SchemaId::from_str(&schema_id_string)?), None => match module_based_on_hash { None => new_schema_id, Some(based_on_hash) => { @@ -156,7 +157,7 @@ pub async fn upsert_module_route( }; if let Some(schema_id) = schema_id { - info!("module gets schema id: {}", schema_id.0); + info!("module gets schema id: {}", schema_id.as_raw_id()); } let schemas: Vec = loaded_module @@ -177,9 +178,9 @@ pub async fn upsert_module_route( let schema_variant_id = match module_kind { ModuleKind::WorkspaceBackup => None, ModuleKind::Module => match module_schema_variant_id { - Some(schema_variant_id_string) => Some(SchemaVariantId(Ulid::from_string( - &schema_variant_id_string, - )?)), + Some(schema_variant_id_string) => { + Some(SchemaVariantId::from_str(&schema_variant_id_string)?) + } _ => None, }, }; diff --git a/lib/si-events-rs/BUCK b/lib/si-events-rs/BUCK index a586c69c13..33dd3ff81d 100644 --- a/lib/si-events-rs/BUCK +++ b/lib/si-events-rs/BUCK @@ -21,7 +21,6 @@ rust_library( "//third-party/rust:serde_json", "//third-party/rust:strum", "//third-party/rust:thiserror", - "//third-party/rust:ulid", "//third-party/rust:xxhash-rust", ], srcs = glob([ diff --git a/lib/si-events-rs/Cargo.toml b/lib/si-events-rs/Cargo.toml index ee87ef01cd..037d4ca110 100644 --- a/lib/si-events-rs/Cargo.toml +++ b/lib/si-events-rs/Cargo.toml @@ -23,5 +23,4 @@ serde = { workspace = true } serde_json = { workspace = true } strum = { workspace = true } thiserror = { workspace = true } -ulid = { workspace = true } xxhash-rust = { workspace = true } diff --git a/lib/si-events-rs/src/func_run.rs b/lib/si-events-rs/src/func_run.rs index d7ab5db935..5255a168d0 100644 --- a/lib/si-events-rs/src/func_run.rs +++ b/lib/si-events-rs/src/func_run.rs @@ -157,9 +157,9 @@ pub struct FuncRun { #[builder(default)] schema_name: Option, #[builder(default)] - action_or_func_id: Option, + action_or_func_id: Option, #[builder(default)] - prototype_id: Option, + prototype_id: Option, #[builder(default)] action_kind: Option, #[builder(default)] diff --git a/lib/si-events-rs/src/func_run_log.rs b/lib/si-events-rs/src/func_run_log.rs index 338f7f0dfe..2f09969647 100644 --- a/lib/si-events-rs/src/func_run_log.rs +++ b/lib/si-events-rs/src/func_run_log.rs @@ -1,59 +1,9 @@ -use std::str::FromStr; - use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use ulid::{Ulid, ULID_LEN}; use crate::{FuncRunId, Tenancy}; -#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct FuncRunLogId(Ulid); - -impl FuncRunLogId { - pub fn new() -> FuncRunLogId { - FuncRunLogId(Ulid::new()) - } - - pub fn array_to_str<'buf>(&self, buf: &'buf mut [u8; ULID_LEN]) -> &'buf mut str { - self.0.array_to_str(buf) - } - - pub fn into_inner(self) -> Ulid { - self.0 - } -} - -impl From for Ulid { - fn from(id: FuncRunLogId) -> Self { - id.0 - } -} - -impl Default for FuncRunLogId { - fn default() -> Self { - Self::new() - } -} - -impl FromStr for FuncRunLogId { - type Err = ulid::DecodeError; - - fn from_str(s: &str) -> Result { - Ok(Self(Ulid::from_str(s)?)) - } -} - -impl From for FuncRunLogId { - fn from(value: ulid::Ulid) -> Self { - Self(value) - } -} - -impl std::fmt::Display for FuncRunLogId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } -} +pub use si_id::FuncRunLogId; /// A one-to-one mapping of cyclone's "OutputStream" type. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] diff --git a/lib/si-events-rs/src/vector_clock_id.rs b/lib/si-events-rs/src/vector_clock_id.rs index b4fa0dcd92..540b5c1f8e 100644 --- a/lib/si-events-rs/src/vector_clock_id.rs +++ b/lib/si-events-rs/src/vector_clock_id.rs @@ -1,68 +1,7 @@ -use serde::{Deserialize, Serialize}; - use crate::ulid::Ulid; -#[derive(Serialize, Deserialize, Hash, PartialEq, Eq, Clone, Copy, Debug)] -pub struct VectorClockChangeSetId(Ulid); - -impl VectorClockChangeSetId { - pub fn new(ulid: Ulid) -> Self { - Self(ulid) - } - - pub fn into_inner(self) -> Ulid { - self.0 - } -} - -impl From for VectorClockChangeSetId { - fn from(value: ulid::Ulid) -> Self { - Self(value.into()) - } -} - -impl From for VectorClockChangeSetId { - fn from(value: Ulid) -> Self { - Self(value) - } -} - -impl std::fmt::Display for VectorClockChangeSetId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -#[derive(Serialize, Deserialize, Hash, PartialEq, Eq, Clone, Copy, Debug)] -pub struct VectorClockActorId(Ulid); - -impl VectorClockActorId { - pub fn new(ulid: Ulid) -> Self { - Self(ulid) - } - - pub fn into_inner(self) -> Ulid { - self.0 - } -} - -impl From for VectorClockActorId { - fn from(value: Ulid) -> Self { - Self(value) - } -} - -impl From for VectorClockActorId { - fn from(value: ulid::Ulid) -> Self { - Self(value.into()) - } -} - -impl std::fmt::Display for VectorClockActorId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} +pub use si_id::VectorClockActorId; +pub use si_id::VectorClockChangeSetId; #[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)] pub struct VectorClockId { @@ -166,8 +105,8 @@ mod tests { let actor_ulid = Ulid::from_string(actor_text).expect("make actor from string"); let vector_clock_id = VectorClockId::new( - VectorClockChangeSetId(change_set_ulid), - VectorClockActorId(actor_ulid), + VectorClockChangeSetId::from(change_set_ulid), + VectorClockActorId::from(actor_ulid), ); let expected = format!("(ChangeSet({cs_text}), Actor({actor_text}))"); diff --git a/lib/si-id/BUCK b/lib/si-id/BUCK index 224ffcd199..4bf1642f35 100644 --- a/lib/si-id/BUCK +++ b/lib/si-id/BUCK @@ -5,6 +5,7 @@ rust_library( deps = [ "//third-party/rust:derive_more", "//third-party/rust:postgres-types", + "//third-party/rust:sea-orm", "//third-party/rust:serde", "//third-party/rust:ulid", ], diff --git a/lib/si-id/Cargo.toml b/lib/si-id/Cargo.toml index 9007e02268..de1fab72c9 100644 --- a/lib/si-id/Cargo.toml +++ b/lib/si-id/Cargo.toml @@ -11,5 +11,6 @@ publish.workspace = true [dependencies] derive_more = { workspace = true } postgres-types = { workspace = true } +sea-orm = { workspace = true } serde = { workspace = true } ulid = { workspace = true } diff --git a/lib/si-id/src/conversions.rs b/lib/si-id/src/conversions.rs index b8a2077d44..36259de123 100644 --- a/lib/si-id/src/conversions.rs +++ b/lib/si-id/src/conversions.rs @@ -1,4 +1,7 @@ -use crate::{AttributeValueId, PropId, PropertyEditorPropId, PropertyEditorValueId}; +use crate::{ + AttributeValueId, ChangeSetId, PropId, PropertyEditorPropId, PropertyEditorValueId, + VectorClockChangeSetId, +}; impl From for PropertyEditorPropId { fn from(prop_id: PropId) -> Self { @@ -23,3 +26,9 @@ impl From for AttributeValueId { Self::from(::ulid::Ulid::from(id)) } } + +impl From for VectorClockChangeSetId { + fn from(id: ChangeSetId) -> Self { + Self::from(::ulid::Ulid::from(id)) + } +} diff --git a/lib/si-id/src/lib.rs b/lib/si-id/src/lib.rs index 2f231eb6ff..fefb0a7bc8 100644 --- a/lib/si-id/src/lib.rs +++ b/lib/si-id/src/lib.rs @@ -30,8 +30,11 @@ pub(crate) mod macros; pub(crate) mod conversions; pub mod ulid; +pub use ::ulid as ulid_upstream; + // Please keep these alphabetically sorted! id!(ActionPrototypeId); +id!(ActivityId); id!(AttributePrototypeArgumentId); id!(AttributePrototypeId); id!(AuthenticationPrototypeId); @@ -39,9 +42,11 @@ id!(DeprecatedVectorClockId); id!(EventSessionId); id!(FuncArgumentId); id!(FuncExecutionPk); +id!(FuncRunLogId); id!(GeometryId); id!(HistoryEventPk); id!(InputSocketId); +id!(LayeredEventId); id!(ManagementPrototypeId); id!(ModuleId); id!(NaxumApiTypesRequestId); @@ -52,6 +57,8 @@ id!(PropertyEditorValueId); id!(SecretId); id!(StaticArgumentValueId); id!(ValidationOutputId); +id!(VectorClockActorId); +id!(VectorClockChangeSetId); id!(ViewId); id!(WorkspaceSnapshotNodeId); @@ -62,12 +69,15 @@ id_with_pg_types!(ChangeSetId); id_with_pg_types!(ComponentId); id_with_pg_types!(FuncId); id_with_pg_types!(FuncRunId); -id_with_pg_types!(SchemaId); id_with_pg_types!(UserPk); id_with_pg_types!(WorkspaceIntegrationId); // Please keep these alphabetically sorted! -id_with_none!(SchemaVariantId); +id_with_pg_and_sea_orm_types!(ModuleIndexModuleId); +id_with_pg_and_sea_orm_types!(SchemaId); + +// Please keep these alphabetically sorted! +id_with_none_and_sea_orm_types!(SchemaVariantId); // Please keep these alphabetically sorted! id_with_none_and_pg_types!(AttributeValueId); diff --git a/lib/si-id/src/macros.rs b/lib/si-id/src/macros.rs index 15f53b7769..af33bbd084 100644 --- a/lib/si-id/src/macros.rs +++ b/lib/si-id/src/macros.rs @@ -68,12 +68,135 @@ macro_rules! id_with_pg_types { }; } +/// Provides PostgreSQL type conversion and SeaORM implementations in addition to standard [`id!`] functionality. +macro_rules! id_with_pg_and_sea_orm_types { + ( + $(#[$($attrs:tt)*])* + $name:ident + ) => { + do_not_use_directly_id_inner!( + $(#[$($attrs)*])* + $name + ); + + impl<'a> postgres_types::FromSql<'a> for $name { + fn from_sql( + ty: &postgres_types::Type, + raw: &'a [u8], + ) -> Result> { + let id: String = postgres_types::FromSql::from_sql(ty, raw)?; + Ok(Self(::ulid::Ulid::from_string(&id)?)) + } + + fn accepts(ty: &postgres_types::Type) -> bool { + ty == &postgres_types::Type::BPCHAR + || ty.kind() == &postgres_types::Kind::Domain(postgres_types::Type::BPCHAR) + } + } + + impl postgres_types::ToSql for $name { + fn to_sql( + &self, + ty: &postgres_types::Type, + out: &mut postgres_types::private::BytesMut, + ) -> Result> + where + Self: Sized, + { + postgres_types::ToSql::to_sql(&self.0.to_string(), ty, out) + } + + fn accepts(ty: &postgres_types::Type) -> bool + where + Self: Sized, + { + ty == &postgres_types::Type::BPCHAR + || ty.kind() == &postgres_types::Kind::Domain(postgres_types::Type::BPCHAR) + } + + fn to_sql_checked( + &self, + ty: &postgres_types::Type, + out: &mut postgres_types::private::BytesMut, + ) -> Result> { + postgres_types::ToSql::to_sql(&self.0.to_string(), ty, out) + } + } + + impl From<$name> for sea_orm::Value { + fn from(source: $name) -> Self { + sea_orm::Value::String(Some(Box::new(source.0.to_string()))) + } + } + + impl TryFrom for $name { + type Error = sea_orm::DbErr; + fn try_from(s: String) -> Result { + Ok($name( + ::ulid::Ulid::from_string(&s).map_err(|err| sea_orm::DbErr::Type(err.to_string()))?, + )) + } + } + + impl sea_orm::TryFromU64 for $name { + fn try_from_u64(_: u64) -> Result { + Err(sea_orm::DbErr::Exec(sea_orm::RuntimeErr::Internal( + format!("{} cannot be converted from u64", stringify!($name)), + ))) + } + } + + impl sea_orm::sea_query::Nullable for $name { + fn null() -> sea_orm::Value { + sea_orm::Value::String(None) + } + } + + impl sea_orm::TryGetable for $name { + fn try_get_by(res: &sea_orm::QueryResult, idx: I) -> Result { + let json_str: String = + res.try_get_by(idx) + .map_err(sea_orm::TryGetError::DbErr) + .and_then(|opt: Option| { + opt.ok_or(sea_orm::TryGetError::Null("null".to_string())) + })?; + ::ulid::Ulid::from_string(&json_str) + .map_err(|e| sea_orm::TryGetError::DbErr(sea_orm::DbErr::Type(e.to_string()))) + .map($name) + } + } + + impl sea_orm::sea_query::ValueType for $name { + fn try_from(v: sea_orm::Value) -> Result { + match v { + sea_orm::Value::String(Some(x)) => Ok($name( + ::ulid::Ulid::from_string(&x).map_err(|_| sea_orm::sea_query::ValueTypeErr)?, + )), + _ => Err(sea_orm::sea_query::ValueTypeErr), + } + } + + fn type_name() -> String { + stringify!($name).to_owned() + } + + fn array_type() -> sea_orm::sea_query::ArrayType { + sea_orm::sea_query::ArrayType::String + } + + fn column_type() -> sea_orm::sea_query::ColumnType { + sea_orm::sea_query::ColumnType::String(sea_orm::entity::prelude::StringLen::None) + } + } + }; +} + /// **Deprecated:** this macro provides additional functionality for using the "nil" ID on top of the standard `id!` -/// macro. +/// macro. It also adds support for SeaORM type conversions. /// /// This absolutely should not be used for any new IDs. Nick will be mad. No, I'm not writing this in third /// person, why do you ask? -macro_rules! id_with_none { +macro_rules! id_with_none_and_sea_orm_types { ( $(#[$($attrs:tt)*])* $name:ident @@ -93,6 +216,72 @@ macro_rules! id_with_none { /// The "nil" value for this ID. pub const NONE: Self = Self(::ulid::Ulid::nil()); } + + impl From<$name> for sea_orm::Value { + fn from(source: $name) -> Self { + sea_orm::Value::String(Some(Box::new(source.0.to_string()))) + } + } + + impl TryFrom for $name { + type Error = sea_orm::DbErr; + fn try_from(s: String) -> Result { + Ok($name( + ::ulid::Ulid::from_string(&s).map_err(|err| sea_orm::DbErr::Type(err.to_string()))?, + )) + } + } + + impl sea_orm::TryFromU64 for $name { + fn try_from_u64(_: u64) -> Result { + Err(sea_orm::DbErr::Exec(sea_orm::RuntimeErr::Internal( + format!("{} cannot be converted from u64", stringify!($name)), + ))) + } + } + + impl sea_orm::sea_query::Nullable for $name { + fn null() -> sea_orm::Value { + sea_orm::Value::String(None) + } + } + + impl sea_orm::TryGetable for $name { + fn try_get_by(res: &sea_orm::QueryResult, idx: I) -> Result { + let json_str: String = + res.try_get_by(idx) + .map_err(sea_orm::TryGetError::DbErr) + .and_then(|opt: Option| { + opt.ok_or(sea_orm::TryGetError::Null("null".to_string())) + })?; + ::ulid::Ulid::from_string(&json_str) + .map_err(|e| sea_orm::TryGetError::DbErr(sea_orm::DbErr::Type(e.to_string()))) + .map($name) + } + } + + impl sea_orm::sea_query::ValueType for $name { + fn try_from(v: sea_orm::Value) -> Result { + match v { + sea_orm::Value::String(Some(x)) => Ok($name( + ::ulid::Ulid::from_string(&x).map_err(|_| sea_orm::sea_query::ValueTypeErr)?, + )), + _ => Err(sea_orm::sea_query::ValueTypeErr), + } + } + + fn type_name() -> String { + stringify!($name).to_owned() + } + + fn array_type() -> sea_orm::sea_query::ArrayType { + sea_orm::sea_query::ArrayType::String + } + + fn column_type() -> sea_orm::sea_query::ColumnType { + sea_orm::sea_query::ColumnType::String(sea_orm::entity::prelude::StringLen::None) + } + } }; } diff --git a/lib/si-layer-cache/BUCK b/lib/si-layer-cache/BUCK index 2514d66b92..ccba57b790 100644 --- a/lib/si-layer-cache/BUCK +++ b/lib/si-layer-cache/BUCK @@ -10,6 +10,7 @@ rust_library( "//lib/si-data-nats:si-data-nats", "//lib/si-data-pg:si-data-pg", "//lib/si-events-rs:si-events", + "//lib/si-id:si-id", "//lib/si-runtime-rs:si-runtime", "//lib/si-std:si-std", "//lib/telemetry-rs:telemetry", diff --git a/lib/si-layer-cache/Cargo.toml b/lib/si-layer-cache/Cargo.toml index 6e83ce1734..3c718b20be 100644 --- a/lib/si-layer-cache/Cargo.toml +++ b/lib/si-layer-cache/Cargo.toml @@ -12,6 +12,7 @@ publish.workspace = true si-data-nats = { path = "../../lib/si-data-nats" } si-data-pg = { path = "../../lib/si-data-pg" } si-events = { path = "../../lib/si-events-rs" } +si-id = { path = "../../lib/si-id" } si-runtime = { path = "../../lib/si-runtime-rs" } si-std = { path = "../../lib/si-std" } telemetry = { path = "../../lib/telemetry-rs" } diff --git a/lib/si-layer-cache/src/activities.rs b/lib/si-layer-cache/src/activities.rs index 22197e2549..ee8f4f1c0b 100644 --- a/lib/si-layer-cache/src/activities.rs +++ b/lib/si-layer-cache/src/activities.rs @@ -1,5 +1,5 @@ use std::time::Duration; -use std::{collections::HashMap, fmt, str::FromStr, sync::Arc}; +use std::{collections::HashMap, sync::Arc}; use futures::StreamExt; use serde::{Deserialize, Serialize}; @@ -14,7 +14,7 @@ use tokio::sync::{ Mutex, }; use tokio_util::{sync::CancellationToken, task::TaskTracker}; -use ulid::{Ulid, ULID_LEN}; +use ulid::Ulid; use crate::{ db::serialize, @@ -44,48 +44,7 @@ pub mod test; //pub static SENT_BROADCAST_ERROR_COUNTER: AtomicI32 = AtomicI32::new(0); const MAX_BYTES: i64 = 1024 * 1024; // mirrors settings in Synadia NATs -#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct ActivityId(Ulid); - -impl ActivityId { - pub fn new() -> ActivityId { - ActivityId(Ulid::new()) - } - - pub fn array_to_str<'buf>(&self, buf: &'buf mut [u8; ULID_LEN]) -> &'buf mut str { - self.0.array_to_str(buf) - } - - pub fn into_inner(self) -> Ulid { - self.0 - } -} - -impl Default for ActivityId { - fn default() -> Self { - Self::new() - } -} - -impl FromStr for ActivityId { - type Err = ulid::DecodeError; - - fn from_str(s: &str) -> Result { - Ok(Self(Ulid::from_str(s)?)) - } -} - -impl From for ActivityId { - fn from(value: ulid::Ulid) -> Self { - Self(value) - } -} - -impl fmt::Display for ActivityId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} +pub use si_id::ActivityId; #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct Activity { diff --git a/lib/si-layer-cache/src/event.rs b/lib/si-layer-cache/src/event.rs index f0738cda23..0e98f8ff18 100644 --- a/lib/si-layer-cache/src/event.rs +++ b/lib/si-layer-cache/src/event.rs @@ -60,32 +60,7 @@ impl LayeredEventMetadata { } } -#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct LayeredEventId(Ulid); - -impl Default for LayeredEventId { - fn default() -> Self { - Self::new() - } -} - -impl LayeredEventId { - pub fn new() -> Self { - LayeredEventId(Ulid::new()) - } - - pub fn into_inner(self) -> Ulid { - self.0 - } -} - -impl std::str::FromStr for LayeredEventId { - type Err = ulid::DecodeError; - - fn from_str(s: &str) -> Result { - Ok(Self(Ulid::from_str(s)?)) - } -} +pub use si_id::LayeredEventId; #[remain::sorted] #[derive(AsRefStr, Debug, Serialize, Deserialize)]