From 153f9cb108c140a86592b757550bdf2d1a8dbd79 Mon Sep 17 00:00:00 2001 From: "a.tolmachev" Date: Sun, 19 Apr 2026 07:36:35 +0000 Subject: [PATCH] registry: type metadata and yaml import timestamps --- ...47dbdad5d055887ef5fabd82552d4fe704f891.json} | 10 +++++----- ...cbd063dc5746ef669f21b0db1b5843e9db22d0.json} | 10 +++++----- apps/admin-api/src/service.rs | 14 +++++++++----- crates/crank-registry/src/model.rs | 17 +++++++++++------ crates/crank-registry/src/postgres/mod.rs | 12 ++++++------ crates/crank-registry/src/postgres/operation.rs | 8 ++++---- .../crank-registry/src/postgres/yaml_import.rs | 6 +++--- 7 files changed, 43 insertions(+), 34 deletions(-) rename .sqlx/{query-da58664742ddda01bd0bb8fccf69c69167b1c4f4868ca5310fbd8f5fdc5cd546.json => query-1b8c77657275ab0ea28e68ae5147dbdad5d055887ef5fabd82552d4fe704f891.json} (74%) rename .sqlx/{query-2907637008db9d3febc5f8f2f79f7f073b35973aad326acfd54970ef0ab2a731.json => query-6ae136d8196f7b259b7e5d054ecbd063dc5746ef669f21b0db1b5843e9db22d0.json} (73%) diff --git a/.sqlx/query-da58664742ddda01bd0bb8fccf69c69167b1c4f4868ca5310fbd8f5fdc5cd546.json b/.sqlx/query-1b8c77657275ab0ea28e68ae5147dbdad5d055887ef5fabd82552d4fe704f891.json similarity index 74% rename from .sqlx/query-da58664742ddda01bd0bb8fccf69c69167b1c4f4868ca5310fbd8f5fdc5cd546.json rename to .sqlx/query-1b8c77657275ab0ea28e68ae5147dbdad5d055887ef5fabd82552d4fe704f891.json index d1994a4..06b97ab 100644 --- a/.sqlx/query-da58664742ddda01bd0bb8fccf69c69167b1c4f4868ca5310fbd8f5fdc5cd546.json +++ b/.sqlx/query-1b8c77657275ab0ea28e68ae5147dbdad5d055887ef5fabd82552d4fe704f891.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "select\n id,\n operation_id,\n version,\n sample_kind,\n storage_ref,\n content_type,\n file_name,\n to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\"\n from operation_samples\n where operation_id = $1 and version = $2\n order by created_at asc", + "query": "select\n id,\n operation_id,\n version,\n sample_kind,\n storage_ref,\n content_type,\n file_name,\n created_at as \"created_at!: time::OffsetDateTime\"\n from operation_samples\n where operation_id = $1 and version = $2\n order by created_at asc", "describe": { "columns": [ { @@ -40,8 +40,8 @@ }, { "ordinal": 7, - "name": "created_at!", - "type_info": "Text" + "name": "created_at!: time::OffsetDateTime", + "type_info": "Timestamptz" } ], "parameters": { @@ -58,8 +58,8 @@ false, false, true, - null + false ] }, - "hash": "da58664742ddda01bd0bb8fccf69c69167b1c4f4868ca5310fbd8f5fdc5cd546" + "hash": "1b8c77657275ab0ea28e68ae5147dbdad5d055887ef5fabd82552d4fe704f891" } diff --git a/.sqlx/query-2907637008db9d3febc5f8f2f79f7f073b35973aad326acfd54970ef0ab2a731.json b/.sqlx/query-6ae136d8196f7b259b7e5d054ecbd063dc5746ef669f21b0db1b5843e9db22d0.json similarity index 73% rename from .sqlx/query-2907637008db9d3febc5f8f2f79f7f073b35973aad326acfd54970ef0ab2a731.json rename to .sqlx/query-6ae136d8196f7b259b7e5d054ecbd063dc5746ef669f21b0db1b5843e9db22d0.json index 251eff4..ff6c9a4 100644 --- a/.sqlx/query-2907637008db9d3febc5f8f2f79f7f073b35973aad326acfd54970ef0ab2a731.json +++ b/.sqlx/query-6ae136d8196f7b259b7e5d054ecbd063dc5746ef669f21b0db1b5843e9db22d0.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "select\n id,\n operation_id,\n version,\n descriptor_kind,\n storage_ref,\n source_name,\n package_index_json,\n to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\"\n from descriptors\n where operation_id = $1 and version = $2\n order by created_at asc", + "query": "select\n id,\n operation_id,\n version,\n descriptor_kind,\n storage_ref,\n source_name,\n package_index_json,\n created_at as \"created_at!: time::OffsetDateTime\"\n from descriptors\n where operation_id = $1 and version = $2\n order by created_at asc", "describe": { "columns": [ { @@ -40,8 +40,8 @@ }, { "ordinal": 7, - "name": "created_at!", - "type_info": "Text" + "name": "created_at!: time::OffsetDateTime", + "type_info": "Timestamptz" } ], "parameters": { @@ -58,8 +58,8 @@ false, true, true, - null + false ] }, - "hash": "2907637008db9d3febc5f8f2f79f7f073b35973aad326acfd54970ef0ab2a731" + "hash": "6ae136d8196f7b259b7e5d054ecbd063dc5746ef669f21b0db1b5843e9db22d0" } diff --git a/apps/admin-api/src/service.rs b/apps/admin-api/src/service.rs index 71f3d4b..ca6b860 100644 --- a/apps/admin-api/src/service.rs +++ b/apps/admin-api/src/service.rs @@ -2924,6 +2924,7 @@ impl AdminService { let services = services_from_descriptor_set_bytes(payload) .map_err(|error| ApiError::validation(error.to_string()))?; let descriptor_id = crank_core::DescriptorId::new(new_prefixed_id("desc")); + let created_at = OffsetDateTime::now_utc(); let storage_ref = self .storage .write_descriptor( @@ -2949,7 +2950,7 @@ impl AdminService { serde_json::to_value(&services) .map_err(|error| ApiError::internal(error.to_string()))?, ), - created_at: now_string()?, + created_at, }, }) .await?; @@ -2982,6 +2983,7 @@ impl AdminService { } let descriptor_id = crank_core::DescriptorId::new(new_prefixed_id("desc")); + let created_at = OffsetDateTime::now_utc(); let storage_ref = self .storage .write_descriptor( @@ -3004,7 +3006,7 @@ impl AdminService { storage_ref, source_name: source_name.map(ToOwned::to_owned), package_index: None, - created_at: now_string()?, + created_at, }, }) .await?; @@ -3074,6 +3076,7 @@ impl AdminService { let services = inspect_wsdl(payload).map_err(|error| ApiError::validation(error.to_string()))?; let descriptor_id = crank_core::DescriptorId::new(new_prefixed_id("desc")); + let created_at = OffsetDateTime::now_utc(); let storage_ref = self .storage .write_descriptor( @@ -3099,7 +3102,7 @@ impl AdminService { serde_json::to_value(&services) .map_err(|error| ApiError::internal(error.to_string()))?, ), - created_at: now_string()?, + created_at, }, }) .await?; @@ -3132,6 +3135,7 @@ impl AdminService { } let descriptor_id = crank_core::DescriptorId::new(new_prefixed_id("desc")); + let created_at = OffsetDateTime::now_utc(); let storage_ref = self .storage .write_descriptor( @@ -3154,7 +3158,7 @@ impl AdminService { storage_ref, source_name: source_name.map(ToOwned::to_owned), package_index: None, - created_at: now_string()?, + created_at, }, }) .await?; @@ -3396,7 +3400,7 @@ impl AdminService { let summary = self.get_operation(workspace_id, operation_id).await?; let version = summary.current_draft_version; let sample_id = SampleId::new(new_prefixed_id("sample")); - let now = now_string()?; + let now = OffsetDateTime::now_utc(); let file_name = match sample_kind { SampleKind::InputJson => "input.json", SampleKind::OutputJson => "output.json", diff --git a/crates/crank-registry/src/model.rs b/crates/crank-registry/src/model.rs index 79116de..823c67e 100644 --- a/crates/crank-registry/src/model.rs +++ b/crates/crank-registry/src/model.rs @@ -261,7 +261,8 @@ pub struct OperationSampleMetadata { pub storage_ref: String, pub content_type: String, pub file_name: Option, - pub created_at: String, + #[serde(with = "time::serde::rfc3339")] + pub created_at: OffsetDateTime, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -283,7 +284,8 @@ pub struct DescriptorMetadata { pub storage_ref: String, pub source_name: Option, pub package_index: Option, - pub created_at: String, + #[serde(with = "time::serde::rfc3339")] + pub created_at: OffsetDateTime, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -304,8 +306,10 @@ pub struct YamlImportJob { pub result_operation_id: Option, pub result_version: Option, pub error_text: Option, - pub created_at: String, - pub finished_at: Option, + #[serde(with = "time::serde::rfc3339")] + pub created_at: OffsetDateTime, + #[serde(with = "time::serde::rfc3339::option")] + pub finished_at: Option, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -314,7 +318,8 @@ pub struct YamlImportJobCompletion { pub result_operation_id: Option, pub result_version: Option, pub error_text: Option, - pub finished_at: String, + #[serde(with = "time::serde::rfc3339")] + pub finished_at: OffsetDateTime, } #[derive(Clone, Debug, PartialEq)] @@ -380,7 +385,7 @@ pub struct CreateYamlImportJobRequest<'a> { pub source_sample_id: Option<&'a SampleId>, pub format_version: &'a str, pub mode: ExportMode, - pub created_at: &'a str, + pub created_at: &'a OffsetDateTime, } #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/crates/crank-registry/src/postgres/mod.rs b/crates/crank-registry/src/postgres/mod.rs index 2222b71..90f2635 100644 --- a/crates/crank-registry/src/postgres/mod.rs +++ b/crates/crank-registry/src/postgres/mod.rs @@ -920,7 +920,7 @@ fn build_sample_metadata( storage_ref: String, content_type: String, file_name: Option, - created_at: String, + created_at: OffsetDateTime, ) -> Result { Ok(OperationSampleMetadata { id: crank_core::SampleId::new(id), @@ -943,7 +943,7 @@ fn build_descriptor_metadata( storage_ref: String, source_name: Option, package_index: Option, - created_at: String, + created_at: OffsetDateTime, ) -> Result { Ok(DescriptorMetadata { id: crank_core::DescriptorId::new(id), @@ -1335,7 +1335,7 @@ mod tests { storage_ref: "file:///tmp/input.json".to_owned(), content_type: "application/json".to_owned(), file_name: Some("input.json".to_owned()), - created_at: "2026-03-25T12:01:00Z".to_owned(), + created_at: timestamp("2026-03-25T12:01:00Z"), }; let descriptor = DescriptorMetadata { id: "descriptor_01".into(), @@ -1345,7 +1345,7 @@ mod tests { storage_ref: "file:///tmp/schema.desc".to_owned(), source_name: Some("schema.desc".to_owned()), package_index: Some(json!({ "crm.v1": ["LeadService"] })), - created_at: "2026-03-25T12:02:00Z".to_owned(), + created_at: timestamp("2026-03-25T12:02:00Z"), }; registry @@ -1436,7 +1436,7 @@ mod tests { source_sample_id: None, format_version: "v1", mode: ExportMode::Portable, - created_at: "2026-03-25T12:00:00Z", + created_at: ×tamp("2026-03-25T12:00:00Z"), }) .await .unwrap(); @@ -1449,7 +1449,7 @@ mod tests { result_operation_id: Some(operation.id.clone()), result_version: Some(2), error_text: None, - finished_at: "2026-03-25T12:05:00Z".to_owned(), + finished_at: timestamp("2026-03-25T12:05:00Z"), }, ) .await diff --git a/crates/crank-registry/src/postgres/operation.rs b/crates/crank-registry/src/postgres/operation.rs index 2457e67..0e8dcca 100644 --- a/crates/crank-registry/src/postgres/operation.rs +++ b/crates/crank-registry/src/postgres/operation.rs @@ -854,7 +854,7 @@ impl PostgresRegistry { .bind(&request.sample.storage_ref) .bind(&request.sample.content_type) .bind(request.sample.file_name.as_deref()) - .bind(&request.sample.created_at) + .bind(request.sample.created_at) .execute(&self.pool) .await?; @@ -875,7 +875,7 @@ impl PostgresRegistry { storage_ref, content_type, file_name, - to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\" + created_at as \"created_at!: time::OffsetDateTime\" from operation_samples where operation_id = $1 and version = $2 order by created_at asc", @@ -941,7 +941,7 @@ impl PostgresRegistry { .bind(&request.descriptor.storage_ref) .bind(request.descriptor.source_name.as_deref()) .bind(serialize_option_json_value(&request.descriptor.package_index)?.map(Json)) - .bind(&request.descriptor.created_at) + .bind(request.descriptor.created_at) .execute(&self.pool) .await?; @@ -962,7 +962,7 @@ impl PostgresRegistry { storage_ref, source_name, package_index_json, - to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\" + created_at as \"created_at!: time::OffsetDateTime\" from descriptors where operation_id = $1 and version = $2 order by created_at asc", diff --git a/crates/crank-registry/src/postgres/yaml_import.rs b/crates/crank-registry/src/postgres/yaml_import.rs index 5a3b3f3..2d21e00 100644 --- a/crates/crank-registry/src/postgres/yaml_import.rs +++ b/crates/crank-registry/src/postgres/yaml_import.rs @@ -60,7 +60,7 @@ impl PostgresRegistry { ) .bind(completion.result_version.map(to_db_version)) .bind(completion.error_text.as_deref()) - .bind(&completion.finished_at) + .bind(completion.finished_at) .execute(&self.pool) .await?; @@ -87,8 +87,8 @@ impl PostgresRegistry { result_operation_id, result_version, error_text, - to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at, - to_char(finished_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as finished_at + created_at, + finished_at from yaml_import_jobs where id = $1", )