diff --git a/Cargo.lock b/Cargo.lock index 32b4cddcb2..890a3176e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3552,6 +3552,7 @@ dependencies = [ "async-trait", "bincode", "bytes 1.7.1", + "chrono", "criterion", "fastrand 2.1.0", "golem-api-grpc", @@ -3560,6 +3561,7 @@ dependencies = [ "golem-wasm-ast", "http 0.2.12", "prost", + "prost-types", "serde 1.0.207", "sqlx", "tap", @@ -3576,9 +3578,9 @@ dependencies = [ [[package]] name = "golem-examples" -version = "1.0.0-rc2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ac60c107db14e5f91abe5d68bbf02349f2cb856de14bd9c76b18ae5f9f9e58e" +checksum = "cdf804c2fba657a45213ab5d3e2460c9ed7dfd4d0e74d4472e4a1aa04c25afa2" dependencies = [ "Inflector", "cargo_metadata", @@ -3655,6 +3657,7 @@ dependencies = [ "num-traits 0.2.19", "poem-openapi", "proptest", + "prost-types", "rand 0.8.5", "serde 1.0.207", "serde_json", @@ -3747,9 +3750,9 @@ dependencies = [ [[package]] name = "golem-wasm-ast" -version = "1.0.0-rc1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770844a7ec2727fcef6dad6f11283a99682f10c81985f1ec2c75828316076b94" +checksum = "eb5a7ea3b63c2b1bc04c7de835d1c74bb40343211879af4d1d866cb8a7b51a61" dependencies = [ "bincode", "leb128", @@ -3767,9 +3770,9 @@ dependencies = [ [[package]] name = "golem-wasm-rpc" -version = "1.0.0-rc1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91951471a6504b3649e9687a32971dbd768f2027dcab052145809502f31454fc" +checksum = "ae6a6fc80c3ad7bf4849f104a7614e5216890f48d131fa799aba5be639713d45" dependencies = [ "arbitrary", "async-recursion", @@ -3791,9 +3794,9 @@ dependencies = [ [[package]] name = "golem-wasm-rpc-stubgen" -version = "1.0.0-rc1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "491cf02dde768a310d7ba4907b072bbbcb93ed7bb703146733d3e3a908635676" +checksum = "ac8729de93db67776d2b6c75d987eff101de891e8f167087eb53d32402183eb0" dependencies = [ "anyhow", "cargo-component", @@ -3824,9 +3827,9 @@ dependencies = [ [[package]] name = "golem-wit" -version = "1.0.0-rc1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44357f9814854f8f672c77c63a1fce2b0258ad6f36115a3773a189976848635e" +checksum = "419a91ba9038ca4b0d18378d5f3d4631377df436b3982dae0891503b86b2914e" [[package]] name = "golem-worker-executor" @@ -4003,6 +4006,7 @@ dependencies = [ "async-trait", "bincode", "bytes 1.7.1", + "chrono", "criterion", "derive_more", "fastrand 2.1.0", diff --git a/golem-api-grpc/proto/golem/component/component.proto b/golem-api-grpc/proto/golem/component/component.proto index 9dd5c06088..ab899b684c 100644 --- a/golem-api-grpc/proto/golem/component/component.proto +++ b/golem-api-grpc/proto/golem/component/component.proto @@ -5,6 +5,7 @@ package golem.component; import "golem/common/project_id.proto"; import "golem/component/component_metadata.proto"; import "golem/component/versioned_component_id.proto"; +import "google/protobuf/timestamp.proto"; message Component { VersionedComponentId versioned_component_id = 1; @@ -12,4 +13,5 @@ message Component { uint64 component_size = 5; ComponentMetadata metadata = 6; golem.common.ProjectId project_id = 7; + google.protobuf.Timestamp created_at = 8; } diff --git a/golem-cli/src/model/component.rs b/golem-cli/src/model/component.rs index 4a2ed9628f..864f6d73d7 100644 --- a/golem-cli/src/model/component.rs +++ b/golem-cli/src/model/component.rs @@ -21,6 +21,7 @@ pub struct Component { pub component_size: u64, pub metadata: ComponentMetadata, pub project_id: Option, + pub created_at: chrono::DateTime, } impl From for Component { @@ -30,6 +31,7 @@ impl From for Component { component_name, component_size, metadata, + created_at, } = value; Component { @@ -38,6 +40,7 @@ impl From for Component { component_size, metadata, project_id: None, + created_at, } } } diff --git a/golem-cli/src/model/invoke_result_view.rs b/golem-cli/src/model/invoke_result_view.rs index 6828696fb7..56811ebc0a 100644 --- a/golem-cli/src/model/invoke_result_view.rs +++ b/golem-cli/src/model/invoke_result_view.rs @@ -97,6 +97,7 @@ impl InvokeResultView { #[cfg(test)] mod tests { + use chrono::Utc; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::protobuf::TypeAnnotatedValue as RootTypeAnnotatedValue; use golem_wasm_rpc::protobuf::TypedTuple; @@ -156,6 +157,7 @@ mod tests { memories: vec![], }, project_id: None, + created_at: Utc::now(), }; InvokeResultView::try_parse_or_json( diff --git a/golem-component-service-base/Cargo.toml b/golem-component-service-base/Cargo.toml index 46184f7e01..2912be0621 100644 --- a/golem-component-service-base/Cargo.toml +++ b/golem-component-service-base/Cargo.toml @@ -15,8 +15,10 @@ anyhow = { workspace = true } async-trait = { workspace = true } bincode = { workspace = true } bytes = { workspace = true } +chrono = { workspace = true } http_02 = { workspace = true } prost = { workspace = true } +prost-types = { workspace = true } serde = { workspace = true } sqlx = { workspace = true, features = [ "runtime-tokio", diff --git a/golem-component-service-base/src/model.rs b/golem-component-service-base/src/model.rs index 6a1f80aa3f..25429c8839 100644 --- a/golem-component-service-base/src/model.rs +++ b/golem-component-service-base/src/model.rs @@ -1,6 +1,7 @@ use golem_common::model::component_metadata::ComponentMetadata; use golem_service_base::model::{ComponentName, VersionedComponentId}; use serde::{Deserialize, Serialize}; +use std::time::SystemTime; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Component { @@ -9,6 +10,7 @@ pub struct Component { pub component_name: ComponentName, pub component_size: u64, pub metadata: ComponentMetadata, + pub created_at: chrono::DateTime, } impl Component { @@ -31,6 +33,7 @@ impl From> for golem_service_base::model::Compon component_name: value.component_name, component_size: value.component_size, metadata: value.metadata, + created_at: value.created_at, } } } @@ -43,6 +46,9 @@ impl From> for golem_api_grpc::proto::golem::com component_size: value.component_size, metadata: Some(value.metadata.into()), project_id: None, + created_at: Some(prost_types::Timestamp::from(SystemTime::from( + value.created_at, + ))), } } } diff --git a/golem-component-service-base/src/repo/component.rs b/golem-component-service-base/src/repo/component.rs index 46a85eccea..1a4b331fca 100644 --- a/golem-component-service-base/src/repo/component.rs +++ b/golem-component-service-base/src/repo/component.rs @@ -35,6 +35,7 @@ pub struct ComponentRecord { pub size: i32, pub version: i64, pub metadata: Vec, + pub created_at: chrono::DateTime, } impl TryFrom for Component @@ -56,6 +57,7 @@ where component_size: value.size as u64, metadata, versioned_component_id, + created_at: value.created_at, }) } } @@ -84,6 +86,7 @@ where size: value.component_size as i32, version: value.versioned_component_id.version as i64, metadata: metadata.into(), + created_at: value.created_at, }) } } @@ -167,15 +170,16 @@ impl ComponentRepo for DbComponentRepo { sqlx::query( r#" INSERT INTO component_versions - (component_id, version, size, metadata) + (component_id, version, size, metadata, created_at) VALUES - ($1, $2, $3, $4) + ($1, $2, $3, $4, $5) "#, ) .bind(component.component_id) .bind(component.version) .bind(component.size) .bind(component.metadata.clone()) + .bind(component.created_at) .execute(&mut *transaction) .await?; @@ -193,7 +197,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.component_id = $1 @@ -214,7 +219,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.namespace = $1 @@ -238,7 +244,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.component_id = $1 @@ -264,7 +271,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.component_id = $1 AND cv.version = $2 @@ -290,7 +298,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.namespace = $1 AND c.name = $2 @@ -384,15 +393,16 @@ impl ComponentRepo for DbComponentRepo { sqlx::query( r#" INSERT INTO component_versions - (component_id, version, size, metadata) + (component_id, version, size, metadata, created_at) VALUES - ($1, $2, $3, $4) + ($1, $2, $3, $4, $5) "#, ) .bind(component.component_id) .bind(component.version) .bind(component.size) .bind(component.metadata.clone()) + .bind(component.created_at) .execute(&mut *transaction) .await?; @@ -410,7 +420,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at::timestamptz AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.component_id = $1 @@ -431,7 +442,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at::timestamptz AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.namespace = $1 @@ -455,7 +467,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at::timestamptz AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.component_id = $1 @@ -481,7 +494,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at::timestamptz AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.component_id = $1 AND cv.version = $2 @@ -507,7 +521,8 @@ impl ComponentRepo for DbComponentRepo { c.component_id AS component_id, cv.version AS version, cv.size AS size, - cv.metadata AS metadata + cv.metadata AS metadata, + cv.created_at::timestamptz AS created_at FROM components c JOIN component_versions cv ON c.component_id = cv.component_id WHERE c.namespace = $1 AND c.name = $2 diff --git a/golem-component-service-base/src/service/component.rs b/golem-component-service-base/src/service/component.rs index 316185b890..673d2b3361 100644 --- a/golem-component-service-base/src/service/component.rs +++ b/golem-component-service-base/src/service/component.rs @@ -18,6 +18,7 @@ use std::sync::Arc; use crate::service::component_compilation::ComponentCompilationService; use crate::service::component_processor::process_component; use async_trait::async_trait; +use chrono::Utc; use golem_common::model::component_metadata::ComponentProcessingError; use golem_common::model::ComponentId; use tap::TapFallible; @@ -82,6 +83,7 @@ where component_name: component_name.clone(), component_size: data.len() as u64, metadata, + created_at: Utc::now(), versioned_component_id, }) } @@ -235,7 +237,7 @@ where namespace: &Namespace, ) -> Result, ComponentError> { info!(namespace = %namespace, "Update component"); - + let created_at = Utc::now(); let metadata = process_component(&data).map_err(ComponentError::ComponentProcessingError)?; @@ -266,6 +268,7 @@ where let component = Component { component_size, metadata, + created_at, ..next_component }; let record = component @@ -607,6 +610,7 @@ impl ComponentService component_id: component_id.clone(), version: 0, }, + created_at: Utc::now(), }; Ok(fake_component) @@ -631,6 +635,7 @@ impl ComponentService component_id: component_id.clone(), version: 0, }, + created_at: Utc::now(), }; Ok(fake_component) diff --git a/golem-service-base/Cargo.toml b/golem-service-base/Cargo.toml index ad075a28d1..f90c2796cb 100644 --- a/golem-service-base/Cargo.toml +++ b/golem-service-base/Cargo.toml @@ -29,6 +29,7 @@ humantime-serde = { workspace = true } hyper = { workspace = true } num-traits = { workspace = true } poem-openapi = { workspace = true } +prost-types = { workspace = true } rand = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/golem-service-base/src/model.rs b/golem-service-base/src/model.rs index 96f1110148..9a65880803 100644 --- a/golem-service-base/src/model.rs +++ b/golem-service-base/src/model.rs @@ -20,6 +20,7 @@ use golem_common::model::{ use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use poem_openapi::{Enum, NewType, Object, Union}; use serde::{Deserialize, Serialize}; +use std::time::SystemTime; use std::{collections::HashMap, fmt::Display, fmt::Formatter}; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Object)] @@ -1500,6 +1501,7 @@ pub struct Component { pub component_name: ComponentName, pub component_size: u64, pub metadata: ComponentMetadata, + pub created_at: chrono::DateTime, } impl TryFrom for Component { @@ -1508,6 +1510,11 @@ impl TryFrom for Component { fn try_from( value: golem_api_grpc::proto::golem::component::Component, ) -> Result { + let created_at = value + .created_at + .ok_or("Missing created_at") + .and_then(|t| SystemTime::try_from(t).map_err(|_| "Failed to convert timestamp"))?; + Ok(Self { versioned_component_id: value .versioned_component_id @@ -1516,6 +1523,7 @@ impl TryFrom for Component { component_name: ComponentName(value.component_name), component_size: value.component_size, metadata: value.metadata.ok_or("Missing metadata")?.try_into()?, + created_at: created_at.into(), }) } } @@ -1528,6 +1536,9 @@ impl From for golem_api_grpc::proto::golem::component::Component { component_size: value.component_size, metadata: Some(value.metadata.into()), project_id: None, + created_at: Some(prost_types::Timestamp::from(SystemTime::from( + value.created_at, + ))), } } } diff --git a/golem-worker-service-base/Cargo.toml b/golem-worker-service-base/Cargo.toml index 19d7fea185..96f8993aec 100644 --- a/golem-worker-service-base/Cargo.toml +++ b/golem-worker-service-base/Cargo.toml @@ -21,6 +21,7 @@ anyhow = { workspace = true } async-trait = { workspace = true } bincode = { workspace = true } bytes = { workspace = true } +chrono = { workspace = true } derive_more = { workspace = true } figment = { workspace = true } futures = { workspace = true } diff --git a/golem-worker-service-base/src/service/component/default.rs b/golem-worker-service-base/src/service/component/default.rs index 719ab9a0ba..5698419e75 100644 --- a/golem-worker-service-base/src/service/component/default.rs +++ b/golem-worker-service-base/src/service/component/default.rs @@ -1,4 +1,5 @@ use async_trait::async_trait; +use chrono::Utc; use http::Uri; use tonic::transport::Channel; @@ -215,6 +216,7 @@ impl ComponentServiceNoop { producers: vec![], memories: vec![], }, + created_at: Utc::now(), } } } diff --git a/golem-worker-service-base/tests/services_tests.rs b/golem-worker-service-base/tests/services_tests.rs index ea588665b5..317cc3a85f 100644 --- a/golem-worker-service-base/tests/services_tests.rs +++ b/golem-worker-service-base/tests/services_tests.rs @@ -28,6 +28,7 @@ mod tests { }; use std::sync::Arc; + use chrono::Utc; use testcontainers::clients::Cli; use testcontainers::{Container, RunnableImage}; use testcontainers_modules::postgres::Postgres; @@ -139,6 +140,7 @@ mod tests { producers: vec![], memories: vec![], }, + created_at: Utc::now() } } diff --git a/openapi/golem-service.yaml b/openapi/golem-service.yaml index 245d618069..4c565fec29 100644 --- a/openapi/golem-service.yaml +++ b/openapi/golem-service.yaml @@ -3758,11 +3758,15 @@ components: format: uint64 metadata: $ref: '#/components/schemas/ComponentMetadata' + createdAt: + type: string + format: date-time required: - versionedComponentId - componentName - componentSize - metadata + - createdAt ComponentMetadata: type: object properties: