From bd7a02410d554286fe9becd1b1b88ba4fbb57140 Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Wed, 20 Mar 2024 15:08:03 +0100 Subject: [PATCH] Get/set oplog index host functions (#250) * Extended Golem WIT and unified oplog index to be u64 everywhere * Fix tests * Format * Get/set oplog index implementation and test * Fix worker leak * Fixed log entry gathering in tests * Fixes * Removed debug prints * Updated golem-wit submodule * Update OpenAPI * Update golem-wit * Renamed Marker to NoOp * Refactorings, keeping deleted regions in worker status record, recomputing from oplog when needed * Clippy * Updated jump test * Renames and log improvements * Fixes * Performance fix * Fix * Rebuild --- Cargo.lock | 23 +- .../golem/worker/complete_parameters.proto | 2 +- .../proto/golem/worker/promise_id.proto | 2 +- golem-common/Cargo.toml | 1 + golem-common/src/{model.rs => model/mod.rs} | 395 +----- golem-common/src/model/oplog.rs | 385 ++++++ golem-common/src/model/regions.rs | 240 ++++ golem-common/src/retries.rs | 8 +- golem-service-base/src/model.rs | 4 +- golem-worker-executor-base/Cargo.toml | 2 +- .../src/durable_host/blobstore/container.rs | 2 +- .../src/durable_host/blobstore/mod.rs | 2 +- .../src/durable_host/cli/environment.rs | 2 +- .../durable_host/clocks/monotonic_clock.rs | 2 +- .../src/durable_host/clocks/wall_clock.rs | 2 +- .../src/durable_host/filesystem/preopens.rs | 2 +- .../src/durable_host/filesystem/types.rs | 2 +- .../src/durable_host/golem/mod.rs | 58 +- .../src/durable_host/http/types.rs | 4 +- .../src/durable_host/io/streams.rs | 2 +- .../src/durable_host/keyvalue/eventual.rs | 2 +- .../durable_host/keyvalue/eventual_batch.rs | 2 +- .../src/durable_host/mod.rs | 136 +- .../src/durable_host/random/insecure.rs | 2 +- .../src/durable_host/random/insecure_seed.rs | 2 +- .../src/durable_host/random/random.rs | 2 +- .../src/durable_host/serialized.rs | 2 +- .../durable_host/sockets/ip_name_lookup.rs | 2 +- .../src/durable_host/wasm_rpc/mod.rs | 7 +- golem-worker-executor-base/src/error.rs | 7 + golem-worker-executor-base/src/grpc.rs | 5 +- golem-worker-executor-base/src/invocation.rs | 42 +- golem-worker-executor-base/src/model.rs | 8 +- .../src/preview2/mod.rs | 2 +- .../src/services/compiled_template.rs | 5 +- .../src/services/invocation_key.rs | 2 +- .../src/services/oplog.rs | 14 +- .../src/services/promise.rs | 8 +- .../src/services/recovery.rs | 23 +- .../src/services/worker.rs | 67 +- .../src/wasi_host/mod.rs | 2 - golem-worker-executor-base/src/worker.rs | 98 +- golem-worker-executor-base/src/workerctx.rs | 4 +- .../tests/common/mod.rs | 110 +- golem-worker-executor-base/tests/lib.rs | 1 + .../tests/transactions.rs | 95 ++ golem-worker-executor/src/context.rs | 8 +- .../src/tokeniser/cursor.rs | 1 - golem-worker-service/src/service/worker.rs | 6 +- openapi/golem-service.yaml | 4 +- .../http-client/wit/deps/golem/golem-host.wit | 77 +- test-templates/promise.wasm | Bin 14325 -> 14381 bytes test-templates/promise/cargo.toml | 1 + .../promise/wit/deps/golem/golem-host.wit | 77 +- .../promise/wit/deps/wasm-rpc/wasm-rpc.wit | 54 + test-templates/promise/wit/promise.wit | 2 +- test-templates/runtime-service.wasm | Bin 14236 -> 488642 bytes test-templates/runtime-service/Cargo.lock | 1212 ++++++++++++++++- test-templates/runtime-service/cargo.toml | 1 + test-templates/runtime-service/src/lib.rs | 63 + .../wit/deps/golem/golem-host.wit | 76 +- .../runtime-service/wit/runtime.wit | 3 +- 62 files changed, 2732 insertions(+), 643 deletions(-) rename golem-common/src/{model.rs => model/mod.rs} (67%) create mode 100644 golem-common/src/model/oplog.rs create mode 100644 golem-common/src/model/regions.rs create mode 100644 golem-worker-executor-base/tests/transactions.rs create mode 100644 test-templates/promise/wit/deps/wasm-rpc/wasm-rpc.wit diff --git a/Cargo.lock b/Cargo.lock index 9db8a9085a..215232278f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2635,6 +2635,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "gen_ops" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304de19db7028420975a296ab0fcbbc8e69438c4ed254a1e41e2a7f37d5f0e0a" + [[package]] name = "generic-array" version = "0.14.7" @@ -2812,6 +2818,7 @@ dependencies = [ "prometheus", "prost 0.12.3", "rand 0.8.5", + "range-set-blaze", "serde", "serde_json", "tokio", @@ -3029,9 +3036,9 @@ dependencies = [ [[package]] name = "golem-wit" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce8a760c192419ae1e55fcef20470a248bbd2e19135ae13b6886ddb8619d142" +checksum = "b3263c22aa93cb043f2990a460547669627af71379833003d5605f86d970b301" [[package]] name = "golem-worker-executor" @@ -5650,6 +5657,18 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "range-set-blaze" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8421b5d459262eabbe49048d362897ff3e3830b44eac6cfe341d6acb2f0f13d2" +dependencies = [ + "gen_ops", + "itertools 0.12.1", + "num-integer", + "num-traits", +] + [[package]] name = "rayon" version = "1.8.1" diff --git a/golem-api-grpc/proto/golem/worker/complete_parameters.proto b/golem-api-grpc/proto/golem/worker/complete_parameters.proto index 539595d05e..6e1571bf1a 100644 --- a/golem-api-grpc/proto/golem/worker/complete_parameters.proto +++ b/golem-api-grpc/proto/golem/worker/complete_parameters.proto @@ -4,6 +4,6 @@ package golem.worker; message CompleteParameters { - int32 oplog_idx = 1; + uint64 oplog_idx = 1; bytes data = 2; } diff --git a/golem-api-grpc/proto/golem/worker/promise_id.proto b/golem-api-grpc/proto/golem/worker/promise_id.proto index 26c0b870b5..da96ea7376 100644 --- a/golem-api-grpc/proto/golem/worker/promise_id.proto +++ b/golem-api-grpc/proto/golem/worker/promise_id.proto @@ -6,5 +6,5 @@ import "golem/worker/worker_id.proto"; message PromiseId { WorkerId worker_id = 1; - int32 oplog_idx = 2; + uint64 oplog_idx = 2; } diff --git a/golem-common/Cargo.toml b/golem-common/Cargo.toml index 98a45e9aba..974d1023e0 100644 --- a/golem-common/Cargo.toml +++ b/golem-common/Cargo.toml @@ -29,6 +29,7 @@ poem-openapi = { workspace = true } prometheus = { workspace = true } prost = { workspace = true } rand = "0.8.5" +range-set-blaze = "0.1.16" serde = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } diff --git a/golem-common/src/model.rs b/golem-common/src/model/mod.rs similarity index 67% rename from golem-common/src/model.rs rename to golem-common/src/model/mod.rs index 4f34f95f9e..6b42ff1b3f 100644 --- a/golem-common/src/model.rs +++ b/golem-common/src/model/mod.rs @@ -25,20 +25,19 @@ use bincode::enc::write::Writer; use bincode::enc::Encoder; use bincode::error::{DecodeError, EncodeError}; use bincode::{BorrowDecode, Decode, Encode}; -use bytes::Bytes; use derive_more::FromStr; use poem_openapi::registry::{MetaSchema, MetaSchemaRef}; use poem_openapi::types::{ParseFromJSON, ParseFromParameter, ParseResult, ToJSON}; use poem_openapi::{Enum, Object}; -use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize, Serializer}; use serde_json::Value; use uuid::Uuid; +use crate::model::regions::DeletedRegions; use crate::newtype_uuid; -use crate::serialization::{ - deserialize_with_version, serialize, try_deserialize, SERIALIZATION_VERSION_V1, -}; + +pub mod oplog; +pub mod regions; newtype_uuid!( TemplateId, @@ -238,7 +237,7 @@ impl TryFrom for WorkerId { pub struct PromiseId { #[serde(rename = "instance_id")] pub worker_id: WorkerId, - pub oplog_idx: i32, + pub oplog_idx: u64, } impl PromiseId { @@ -509,7 +508,6 @@ pub struct WorkerMetadata { } impl WorkerMetadata { - #[allow(unused)] // TODO pub fn default(worker_id: VersionedWorkerId, account_id: AccountId) -> WorkerMetadata { WorkerMetadata { worker_id, @@ -521,16 +519,22 @@ impl WorkerMetadata { } } +/// Contains status information about a worker according to a given oplog index. +/// This status is just cached information, all fields must be computable by the oplog alone. +/// By having an associated oplog_idx, the cached information can be used together with the +/// tail of the oplog to determine the actual status of the worker. #[derive(Clone, Debug, Serialize, Deserialize, Encode, Decode)] pub struct WorkerStatusRecord { pub status: WorkerStatus, - pub oplog_idx: i32, + pub deleted_regions: DeletedRegions, + pub oplog_idx: u64, } impl Default for WorkerStatusRecord { fn default() -> Self { WorkerStatusRecord { status: WorkerStatus::Idle, + deleted_regions: DeletedRegions::new(), oplog_idx: 0, } } @@ -607,29 +611,6 @@ impl From for i32 { } } -impl TryFrom for WorkerMetadata { - type Error = String; - - fn try_from( - value: golem_api_grpc::proto::golem::worker::WorkerMetadata, - ) -> Result { - let worker_id: WorkerId = value.worker_id.ok_or("Missing worker_id")?.try_into()?; - Ok(Self { - worker_id: VersionedWorkerId { - worker_id, - template_version: value.template_version, - }, - args: value.args, - env: value.env.into_iter().collect(), - account_id: value.account_id.ok_or("Missing account_id")?.into(), - last_known_status: WorkerStatusRecord { - status: value.status.try_into()?, - oplog_idx: -1, - }, - }) - } -} - #[derive( Clone, Debug, @@ -732,187 +713,6 @@ impl Display for AccountId { } } -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Encode, Decode)] -pub enum OplogEntry { - ImportedFunctionInvoked { - timestamp: Timestamp, - function_name: String, - response: Vec, - wrapped_function_type: WrappedFunctionType, - }, - ExportedFunctionInvoked { - timestamp: Timestamp, - function_name: String, - request: Vec, - invocation_key: Option, - calling_convention: Option, - }, - ExportedFunctionCompleted { - timestamp: Timestamp, - response: Vec, - consumed_fuel: i64, - }, - CreatePromise { - timestamp: Timestamp, - promise_id: PromiseId, - }, - CompletePromise { - timestamp: Timestamp, - promise_id: PromiseId, - data: Vec, - }, - Suspend { - timestamp: Timestamp, - }, - Error { - timestamp: Timestamp, - }, - Debug { - timestamp: Timestamp, - message: String, - }, -} - -impl OplogEntry { - pub fn imported_function_invoked( - timestamp: Timestamp, - function_name: String, - response: &R, - wrapped_function_type: WrappedFunctionType, - ) -> Result { - let serialized_response = serialize(response)?.to_vec(); - - Ok(OplogEntry::ImportedFunctionInvoked { - timestamp, - function_name, - response: serialized_response, - wrapped_function_type, - }) - } - - pub fn exported_function_invoked( - timestamp: Timestamp, - function_name: String, - request: &R, - invocation_key: Option, - calling_convention: Option, - ) -> Result { - let serialized_request = serialize(request)?.to_vec(); - Ok(OplogEntry::ExportedFunctionInvoked { - timestamp, - function_name, - request: serialized_request, - invocation_key, - calling_convention, - }) - } - - pub fn exported_function_completed( - timestamp: Timestamp, - response: &R, - consumed_fuel: i64, - ) -> Result { - let serialized_response = serialize(response)?.to_vec(); - Ok(OplogEntry::ExportedFunctionCompleted { - timestamp, - response: serialized_response, - consumed_fuel, - }) - } - - pub fn response(&self) -> Result, String> { - match &self { - OplogEntry::ImportedFunctionInvoked { response, .. } => { - let response_bytes: Bytes = Bytes::copy_from_slice(response); - - // In the v1 serialization format we did not have version prefix in the payloads. - // We can assume though that if the payload starts with 2, it is serialized with the - // v2 format because neither JSON nor protobuf (the two payload formats used in v1 for payloads) - // start with 2 (This was verified with a simple test ValProtobufPrefixByteValidation). - // So if the first byte is not 1 or 2 we assume it is a v1 format and deserialize it as JSON. - match try_deserialize(&response_bytes)? { - Some(result) => Ok(Some(result)), - None => Ok(Some(deserialize_with_version( - &response_bytes, - SERIALIZATION_VERSION_V1, - )?)), - } - } - OplogEntry::ExportedFunctionCompleted { response, .. } => { - let response_bytes: Bytes = Bytes::copy_from_slice(response); - - // See the comment above for the explanation of this logic - match try_deserialize(&response_bytes)? { - Some(result) => Ok(Some(result)), - None => Ok(Some(deserialize_with_version( - &response_bytes, - SERIALIZATION_VERSION_V1, - )?)), - } - } - _ => Ok(None), - } - } - - pub fn payload_as_val_array( - &self, - ) -> Result>, String> { - // This is a special case of a possible generic request() accessor, because in v1 the only - // data type we serialized was Vec and it was done in a special way (every element serialized - // via protobuf separately, then an array of byte arrays serialized into JSON) - match &self { - OplogEntry::ExportedFunctionInvoked { - function_name, - request, - .. - } => { - let request_bytes: Bytes = Bytes::copy_from_slice(request); - self.try_decode_val_array_payload(function_name, &request_bytes) - } - OplogEntry::ExportedFunctionCompleted { response, .. } => { - let response_bytes: Bytes = Bytes::copy_from_slice(response); - self.try_decode_val_array_payload("?", &response_bytes) - } - _ => Ok(None), - } - } - - fn try_decode_val_array_payload( - &self, - function_name: &str, - payload: &Bytes, - ) -> Result>, String> { - match try_deserialize(payload)? { - Some(result) => Ok(Some(result)), - None => { - let deserialized_array: Vec> = serde_json::from_slice(payload) - .unwrap_or_else(|err| { - panic!( - "Failed to deserialize oplog payload: {:?}: {err}", - std::str::from_utf8(payload).unwrap_or("???") - ) - }); - let function_input = deserialized_array - .iter() - .map(|serialized_value| { - ::decode(serialized_value.as_slice()) - .unwrap_or_else(|err| panic!("Failed to deserialize function input {:?} for {function_name}: {err}", serialized_value)) - }) - .collect::>(); - Ok(Some(function_input)) - } - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Encode, Decode)] -pub enum WrappedFunctionType { - ReadLocal, - WriteLocal, - ReadRemote, - WriteRemote, -} - #[derive(Debug, PartialEq, Eq, Clone)] pub struct ParsedFunctionName { pub interface: Option, @@ -976,13 +776,11 @@ pub fn parse_function_name(name: &str) -> ParsedFunctionName { #[cfg(test)] mod tests { - use crate::model::{parse_function_name, AccountId}; - use crate::model::{CallingConvention, InvocationKey, Timestamp}; - use crate::model::{OplogEntry, WrappedFunctionType}; use bincode::{Decode, Encode}; - use golem_wasm_rpc::protobuf::{val, Val, ValResult}; use serde::{Deserialize, Serialize}; + use crate::model::{parse_function_name, AccountId}; + #[test] fn parse_function_name_global() { let parsed = parse_function_name("run-example"); @@ -1104,169 +902,4 @@ mod tests { let json = serde_json::to_string(&example).unwrap(); assert_eq!(json, "{\"account_id\":\"account-1\"}"); } - - #[test] - fn oplog_entry_imported_function_invoked_payload_roundtrip() { - let timestamp = Timestamp::now_utc(); - let entry = OplogEntry::imported_function_invoked( - timestamp, - "function_name".to_string(), - &("example payload".to_string()), - WrappedFunctionType::ReadLocal, - ) - .unwrap(); - - if let OplogEntry::ImportedFunctionInvoked { response, .. } = &entry { - assert_eq!(response.len(), 17); - } else { - unreachable!() - } - - let response = entry.response::().unwrap().unwrap(); - - assert_eq!(response, "example payload"); - } - - #[test] - fn oplog_entry_imported_function_invoked_payload_v1() { - let timestamp = Timestamp::now_utc(); - let entry = OplogEntry::ImportedFunctionInvoked { - timestamp, - function_name: "function_name".to_string(), - response: serde_json::to_vec("example payload").unwrap(), - wrapped_function_type: WrappedFunctionType::ReadLocal, - }; - - let response = entry.response::().unwrap().unwrap(); - - assert_eq!(response, "example payload"); - } - - #[test] - fn oplog_entry_exported_function_invoked_payload_roundtrip() { - let timestamp = Timestamp::now_utc(); - - let val1 = Val { - val: Some(val::Val::Result(Box::new(ValResult { - discriminant: 0, - value: Some(Box::new(Val { - val: Some(val::Val::U64(10)), - })), - }))), - }; - let entry = OplogEntry::exported_function_invoked( - timestamp, - "function_name".to_string(), - &vec![val1.clone()], - Some(InvocationKey { - value: "invocation_key".to_string(), - }), - Some(CallingConvention::Stdio), - ) - .unwrap(); - - if let OplogEntry::ExportedFunctionInvoked { request, .. } = &entry { - assert_eq!(request.len(), 9); - } else { - unreachable!() - } - - let request = entry.payload_as_val_array().unwrap().unwrap(); - - assert_eq!(request, vec![val1]); - } - - #[test] - fn oplog_entry_exported_function_invoked_payload_v1() { - let timestamp = Timestamp::now_utc(); - - let val1 = Val { - val: Some(val::Val::Result(Box::new(ValResult { - discriminant: 0, - value: Some(Box::new(Val { - val: Some(val::Val::U64(10)), - })), - }))), - }; - let val1_bytes = prost::Message::encode_to_vec(&val1); - let request_bytes = serde_json::to_vec(&vec![val1_bytes]).unwrap(); - - let entry = OplogEntry::ExportedFunctionInvoked { - timestamp, - function_name: "function_name".to_string(), - request: request_bytes, - invocation_key: Some(InvocationKey { - value: "invocation_key".to_string(), - }), - calling_convention: Some(CallingConvention::Stdio), - }; - - let request = entry.payload_as_val_array().unwrap().unwrap(); - assert_eq!(request, vec![val1]); - } - - #[test] - fn oplog_entry_exported_function_completed_roundtrip() { - let timestamp = Timestamp::now_utc(); - - let val1 = Val { - val: Some(val::Val::Result(Box::new(ValResult { - discriminant: 0, - value: Some(Box::new(Val { - val: Some(val::Val::U64(10)), - })), - }))), - }; - let val2 = Val { - val: Some(val::Val::String("something".to_string())), - }; - - let entry = OplogEntry::exported_function_completed( - timestamp, - &vec![val1.clone(), val2.clone()], - 1_000_000_000, - ) - .unwrap(); - - if let OplogEntry::ExportedFunctionCompleted { response, .. } = &entry { - assert_eq!(response.len(), 21); - } else { - unreachable!() - } - - let response = entry.payload_as_val_array().unwrap().unwrap(); - - assert_eq!(response, vec![val1, val2]); - } - - #[test] - fn oplog_entry_exported_function_completed_v1() { - let timestamp = Timestamp::now_utc(); - - let val1 = Val { - val: Some(val::Val::Result(Box::new(ValResult { - discriminant: 0, - value: Some(Box::new(Val { - val: Some(val::Val::U64(10)), - })), - }))), - }; - let val1_bytes = prost::Message::encode_to_vec(&val1); - let val2 = Val { - val: Some(val::Val::String("something".to_string())), - }; - let val2_bytes = prost::Message::encode_to_vec(&val2); - - let response_bytes = serde_json::to_vec(&vec![val1_bytes, val2_bytes]).unwrap(); - - let entry = OplogEntry::ExportedFunctionCompleted { - timestamp, - response: response_bytes, - consumed_fuel: 1_000_000_000, - }; - - let response = entry.payload_as_val_array().unwrap().unwrap(); - - assert_eq!(response, vec![val1, val2]); - } } diff --git a/golem-common/src/model/oplog.rs b/golem-common/src/model/oplog.rs new file mode 100644 index 0000000000..bd41115483 --- /dev/null +++ b/golem-common/src/model/oplog.rs @@ -0,0 +1,385 @@ +use crate::model::regions::OplogRegion; +use crate::model::{CallingConvention, InvocationKey, PromiseId, Timestamp}; +use crate::serialization::{ + deserialize_with_version, serialize, try_deserialize, SERIALIZATION_VERSION_V1, +}; +use bincode::{Decode, Encode}; +use bytes::Bytes; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Encode, Decode)] +pub enum OplogEntry { + /// The worker invoked a host function + ImportedFunctionInvoked { + timestamp: Timestamp, + function_name: String, + response: Vec, + wrapped_function_type: WrappedFunctionType, + }, + /// The worker has been invoked + ExportedFunctionInvoked { + timestamp: Timestamp, + function_name: String, + request: Vec, + invocation_key: Option, + calling_convention: Option, + }, + /// The worker has completed an invocation + ExportedFunctionCompleted { + timestamp: Timestamp, + response: Vec, + consumed_fuel: i64, + }, + /// Promise created + CreatePromise { + timestamp: Timestamp, + promise_id: PromiseId, + }, + /// Promise completed + CompletePromise { + timestamp: Timestamp, + promise_id: PromiseId, + data: Vec, + }, + /// Worker suspended + Suspend { timestamp: Timestamp }, + /// Worker failed + Error { timestamp: Timestamp }, + /// Debug log entry + Debug { + timestamp: Timestamp, + message: String, + }, + /// Marker entry added when get-oplog-index is called from the worker, to make the jumping behavior + /// more predictable. + NoOp { timestamp: Timestamp }, + /// The worker needs to recover up to the given target oplog index and continue running from + /// the source oplog index from there + /// `jump` is an oplog region representing that from the end of that region we want to go back to the start and + /// ignore all recorded operations in between. + Jump { + timestamp: Timestamp, + jump: OplogRegion, + }, +} + +impl OplogEntry { + pub fn imported_function_invoked( + timestamp: Timestamp, + function_name: String, + response: &R, + wrapped_function_type: WrappedFunctionType, + ) -> Result { + let serialized_response = serialize(response)?.to_vec(); + + Ok(OplogEntry::ImportedFunctionInvoked { + timestamp, + function_name, + response: serialized_response, + wrapped_function_type, + }) + } + + pub fn exported_function_invoked( + timestamp: Timestamp, + function_name: String, + request: &R, + invocation_key: Option, + calling_convention: Option, + ) -> Result { + let serialized_request = serialize(request)?.to_vec(); + Ok(OplogEntry::ExportedFunctionInvoked { + timestamp, + function_name, + request: serialized_request, + invocation_key, + calling_convention, + }) + } + + pub fn exported_function_completed( + timestamp: Timestamp, + response: &R, + consumed_fuel: i64, + ) -> Result { + let serialized_response = serialize(response)?.to_vec(); + Ok(OplogEntry::ExportedFunctionCompleted { + timestamp, + response: serialized_response, + consumed_fuel, + }) + } + + pub fn response(&self) -> Result, String> { + match &self { + OplogEntry::ImportedFunctionInvoked { response, .. } => { + let response_bytes: Bytes = Bytes::copy_from_slice(response); + + // In the v1 serialization format we did not have version prefix in the payloads. + // We can assume though that if the payload starts with 2, it is serialized with the + // v2 format because neither JSON nor protobuf (the two payload formats used in v1 for payloads) + // start with 2 (This was verified with a simple test ValProtobufPrefixByteValidation). + // So if the first byte is not 1 or 2 we assume it is a v1 format and deserialize it as JSON. + match try_deserialize(&response_bytes)? { + Some(result) => Ok(Some(result)), + None => Ok(Some(deserialize_with_version( + &response_bytes, + SERIALIZATION_VERSION_V1, + )?)), + } + } + OplogEntry::ExportedFunctionCompleted { response, .. } => { + let response_bytes: Bytes = Bytes::copy_from_slice(response); + + // See the comment above for the explanation of this logic + match try_deserialize(&response_bytes)? { + Some(result) => Ok(Some(result)), + None => Ok(Some(deserialize_with_version( + &response_bytes, + SERIALIZATION_VERSION_V1, + )?)), + } + } + _ => Ok(None), + } + } + + pub fn payload_as_val_array( + &self, + ) -> Result>, String> { + // This is a special case of a possible generic request() accessor, because in v1 the only + // data type we serialized was Vec and it was done in a special way (every element serialized + // via protobuf separately, then an array of byte arrays serialized into JSON) + match &self { + OplogEntry::ExportedFunctionInvoked { + function_name, + request, + .. + } => { + let request_bytes: Bytes = Bytes::copy_from_slice(request); + self.try_decode_val_array_payload(function_name, &request_bytes) + } + OplogEntry::ExportedFunctionCompleted { response, .. } => { + let response_bytes: Bytes = Bytes::copy_from_slice(response); + self.try_decode_val_array_payload("?", &response_bytes) + } + _ => Ok(None), + } + } + + fn try_decode_val_array_payload( + &self, + function_name: &str, + payload: &Bytes, + ) -> Result>, String> { + match try_deserialize(payload)? { + Some(result) => Ok(Some(result)), + None => { + let deserialized_array: Vec> = serde_json::from_slice(payload) + .unwrap_or_else(|err| { + panic!( + "Failed to deserialize oplog payload: {:?}: {err}", + std::str::from_utf8(payload).unwrap_or("???") + ) + }); + let function_input = deserialized_array + .iter() + .map(|serialized_value| { + ::decode(serialized_value.as_slice()) + .unwrap_or_else(|err| panic!("Failed to deserialize function input {:?} for {function_name}: {err}", serialized_value)) + }) + .collect::>(); + Ok(Some(function_input)) + } + } + } + + pub fn jump(timestamp: Timestamp, jump: OplogRegion) -> OplogEntry { + OplogEntry::Jump { timestamp, jump } + } + + pub fn nop(timestamp: Timestamp) -> OplogEntry { + OplogEntry::NoOp { timestamp } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Encode, Decode)] +pub enum WrappedFunctionType { + ReadLocal, + WriteLocal, + ReadRemote, + WriteRemote, +} + +#[cfg(test)] +mod tests { + use super::{OplogEntry, WrappedFunctionType}; + use crate::model::{CallingConvention, InvocationKey, Timestamp}; + use golem_wasm_rpc::protobuf::{val, Val, ValResult}; + + #[test] + fn oplog_entry_imported_function_invoked_payload_roundtrip() { + let timestamp = Timestamp::now_utc(); + let entry = OplogEntry::imported_function_invoked( + timestamp, + "function_name".to_string(), + &("example payload".to_string()), + WrappedFunctionType::ReadLocal, + ) + .unwrap(); + + if let OplogEntry::ImportedFunctionInvoked { response, .. } = &entry { + assert_eq!(response.len(), 17); + } else { + unreachable!() + } + + let response = entry.response::().unwrap().unwrap(); + + assert_eq!(response, "example payload"); + } + + #[test] + fn oplog_entry_imported_function_invoked_payload_v1() { + let timestamp = Timestamp::now_utc(); + let entry = OplogEntry::ImportedFunctionInvoked { + timestamp, + function_name: "function_name".to_string(), + response: serde_json::to_vec("example payload").unwrap(), + wrapped_function_type: WrappedFunctionType::ReadLocal, + }; + + let response = entry.response::().unwrap().unwrap(); + + assert_eq!(response, "example payload"); + } + + #[test] + fn oplog_entry_exported_function_invoked_payload_roundtrip() { + let timestamp = Timestamp::now_utc(); + + let val1 = Val { + val: Some(val::Val::Result(Box::new(ValResult { + discriminant: 0, + value: Some(Box::new(Val { + val: Some(val::Val::U64(10)), + })), + }))), + }; + let entry = OplogEntry::exported_function_invoked( + timestamp, + "function_name".to_string(), + &vec![val1.clone()], + Some(InvocationKey { + value: "invocation_key".to_string(), + }), + Some(CallingConvention::Stdio), + ) + .unwrap(); + + if let OplogEntry::ExportedFunctionInvoked { request, .. } = &entry { + assert_eq!(request.len(), 9); + } else { + unreachable!() + } + + let request = entry.payload_as_val_array().unwrap().unwrap(); + + assert_eq!(request, vec![val1]); + } + + #[test] + fn oplog_entry_exported_function_invoked_payload_v1() { + let timestamp = Timestamp::now_utc(); + + let val1 = Val { + val: Some(val::Val::Result(Box::new(ValResult { + discriminant: 0, + value: Some(Box::new(Val { + val: Some(val::Val::U64(10)), + })), + }))), + }; + let val1_bytes = prost::Message::encode_to_vec(&val1); + let request_bytes = serde_json::to_vec(&vec![val1_bytes]).unwrap(); + + let entry = OplogEntry::ExportedFunctionInvoked { + timestamp, + function_name: "function_name".to_string(), + request: request_bytes, + invocation_key: Some(InvocationKey { + value: "invocation_key".to_string(), + }), + calling_convention: Some(CallingConvention::Stdio), + }; + + let request = entry.payload_as_val_array().unwrap().unwrap(); + assert_eq!(request, vec![val1]); + } + + #[test] + fn oplog_entry_exported_function_completed_roundtrip() { + let timestamp = Timestamp::now_utc(); + + let val1 = Val { + val: Some(val::Val::Result(Box::new(ValResult { + discriminant: 0, + value: Some(Box::new(Val { + val: Some(val::Val::U64(10)), + })), + }))), + }; + let val2 = Val { + val: Some(val::Val::String("something".to_string())), + }; + + let entry = OplogEntry::exported_function_completed( + timestamp, + &vec![val1.clone(), val2.clone()], + 1_000_000_000, + ) + .unwrap(); + + if let OplogEntry::ExportedFunctionCompleted { response, .. } = &entry { + assert_eq!(response.len(), 21); + } else { + unreachable!() + } + + let response = entry.payload_as_val_array().unwrap().unwrap(); + + assert_eq!(response, vec![val1, val2]); + } + + #[test] + fn oplog_entry_exported_function_completed_v1() { + let timestamp = Timestamp::now_utc(); + + let val1 = Val { + val: Some(val::Val::Result(Box::new(ValResult { + discriminant: 0, + value: Some(Box::new(Val { + val: Some(val::Val::U64(10)), + })), + }))), + }; + let val1_bytes = prost::Message::encode_to_vec(&val1); + let val2 = Val { + val: Some(val::Val::String("something".to_string())), + }; + let val2_bytes = prost::Message::encode_to_vec(&val2); + + let response_bytes = serde_json::to_vec(&vec![val1_bytes, val2_bytes]).unwrap(); + + let entry = OplogEntry::ExportedFunctionCompleted { + timestamp, + response: response_bytes, + consumed_fuel: 1_000_000_000, + }; + + let response = entry.payload_as_val_array().unwrap().unwrap(); + + assert_eq!(response, vec![val1, val2]); + } +} diff --git a/golem-common/src/model/regions.rs b/golem-common/src/model/regions.rs new file mode 100644 index 0000000000..8a053b8148 --- /dev/null +++ b/golem-common/src/model/regions.rs @@ -0,0 +1,240 @@ +// Copyright 2024 Golem Cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::collections::btree_map::{IntoValues, Values}; +use std::collections::BTreeMap; +use std::fmt::{Display, Formatter}; +use std::ops::Bound::{Included, Unbounded}; +use std::ops::RangeInclusive; + +use bincode::{Decode, Encode}; +use range_set_blaze::RangeSetBlaze; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Encode, Decode)] +pub struct OplogRegion { + pub start: u64, + pub end: u64, +} + +impl OplogRegion { + pub fn contains(&self, target: u64) -> bool { + target > self.end && target <= self.start + } + + pub fn union(&self, other: &OplogRegion) -> Option { + if self.contains(other.start) || other.contains(self.start) { + Some(OplogRegion { + start: self.start.min(other.start), + end: self.end.max(other.end), + }) + } else { + None + } + } + + pub fn from_range(range: RangeInclusive) -> OplogRegion { + OplogRegion { + start: *range.start(), + end: *range.end(), + } + } + + pub fn to_range(&self) -> RangeInclusive { + self.start..=self.end + } +} + +impl Display for OplogRegion { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "<{} => {}>", self.start, self.end) + } +} + +/// Temporary builder for building up a `DeletedRegions` structure using an efficient data +/// structure for merging ranges as they are added. +pub struct DeletedRegionsBuilder { + regions: RangeSetBlaze, +} + +impl Default for DeletedRegionsBuilder { + fn default() -> Self { + Self::new() + } +} + +impl DeletedRegionsBuilder { + pub fn new() -> Self { + Self { + regions: RangeSetBlaze::new(), + } + } + + pub fn from_regions(regions: impl IntoIterator) -> Self { + Self { + regions: RangeSetBlaze::from_iter(regions.into_iter().map(|region| region.to_range())), + } + } + + /// Adds a new region to the list of deleted regions + pub fn add(&mut self, region: OplogRegion) { + self.regions.ranges_insert(region.to_range()); + } + + pub fn build(self) -> DeletedRegions { + DeletedRegions::from_regions(self.regions.into_ranges().map(OplogRegion::from_range)) + } +} + +/// Structure holding all the regions deleted from the oplog by jumps +#[derive(Clone, Debug, Serialize, Deserialize, Encode, Decode)] +pub struct DeletedRegions { + regions: BTreeMap, +} + +impl Default for DeletedRegions { + fn default() -> Self { + Self::new() + } +} + +impl DeletedRegions { + /// Constructs an empty set of deleted regions + pub fn new() -> Self { + Self { + regions: BTreeMap::new(), + } + } + + /// Initializes from known list of deleted oplog regions + pub fn from_regions(regions: impl IntoIterator) -> Self { + Self { + regions: BTreeMap::from_iter(regions.into_iter().map(|region| (region.start, region))), + } + } + + /// Adds a new region to the list of deleted regions + pub fn add(&mut self, region: OplogRegion) { + // We rebuild the map to make sure overlapping regions are properly merged + let mut builder = DeletedRegionsBuilder::from_regions(self.regions.clone().into_values()); + builder.add(region); + self.regions = builder.build().regions; + } + + /// Returns the list of deleted regions + pub fn regions(&self) -> Values<'_, u64, OplogRegion> { + self.regions.values() + } + + /// Becomes the list of deleted regions + pub fn into_regions(self) -> IntoValues { + self.regions.into_values() + } + + /// Gets the next deleted region after, possibly including, the given oplog index. + /// Returns None if there are no more deleted regions. + pub fn find_next_deleted_region(&self, from: u64) -> Option { + self.regions + .range((Included(from), Unbounded)) + .next() + .map(|(_, region)| region.clone()) + } + + pub fn is_in_deleted_region(&self, oplog_index: u64) -> bool { + self.regions + .values() + .any(|region| region.contains(oplog_index)) + } +} + +impl Display for DeletedRegions { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "[{}]", + self.regions + .values() + .map(|region| region.to_string()) + .collect::>() + .join(", ") + ) + } +} + +#[cfg(test)] +mod tests { + use crate::model::regions::{DeletedRegionsBuilder, OplogRegion}; + + #[test] + pub fn builder_from_overlapping_ranges() { + let mut builder = DeletedRegionsBuilder::new(); + builder.add(OplogRegion { start: 2, end: 8 }); + builder.add(OplogRegion { start: 2, end: 14 }); + builder.add(OplogRegion { start: 20, end: 22 }); + let deleted_regions = builder.build(); + + assert_eq!( + deleted_regions.into_regions().collect::>(), + vec![ + OplogRegion { start: 2, end: 14 }, + OplogRegion { start: 20, end: 22 }, + ] + ); + } + + #[test] + pub fn builder_from_initial_state() { + let mut builder = DeletedRegionsBuilder::from_regions(vec![ + OplogRegion { start: 2, end: 8 }, + OplogRegion { start: 20, end: 22 }, + ]); + + builder.add(OplogRegion { start: 20, end: 24 }); + builder.add(OplogRegion { start: 30, end: 40 }); + + let deleted_regions = builder.build(); + + assert_eq!( + deleted_regions.into_regions().collect::>(), + vec![ + OplogRegion { start: 2, end: 8 }, + OplogRegion { start: 20, end: 24 }, + OplogRegion { start: 30, end: 40 }, + ] + ); + } + + #[test] + pub fn find_next_deleted_region() { + let deleted_regions = DeletedRegionsBuilder::from_regions(vec![ + OplogRegion { start: 2, end: 8 }, + OplogRegion { start: 20, end: 22 }, + ]) + .build(); + + assert_eq!( + deleted_regions.find_next_deleted_region(0), + Some(OplogRegion { start: 2, end: 8 }) + ); + assert_eq!( + deleted_regions.find_next_deleted_region(2), + Some(OplogRegion { start: 2, end: 8 }) + ); + assert_eq!( + deleted_regions.find_next_deleted_region(8), + Some(OplogRegion { start: 20, end: 22 }) + ); + assert_eq!(deleted_regions.find_next_deleted_region(22), None); + } +} diff --git a/golem-common/src/retries.rs b/golem-common/src/retries.rs index f49ceaca27..cf76df9d51 100644 --- a/golem-common/src/retries.rs +++ b/golem-common/src/retries.rs @@ -26,14 +26,14 @@ use crate::metrics::external_calls::{ /// Returns the delay to be waited before the next retry attempt. /// To be called after a failed attempt, with the number of attempts so far. /// Returns None if the maximum number of attempts has been reached. -pub fn get_delay(config: &RetryConfig, attempts: u32) -> Option { +pub fn get_delay(config: &RetryConfig, attempts: u64) -> Option { // Exponential backoff algorithm inspired by fred::pool::ReconnectPolicy::Exponential - if attempts >= config.max_attempts { + if attempts >= (config.max_attempts as u64) { return None; } let base_delay = (config.multiplier as u64) - .saturating_pow(attempts - 1) + .saturating_pow(attempts.saturating_sub(1).try_into().unwrap_or(0)) .saturating_mul(config.min_delay.as_millis() as u64); let delay = Duration::from_millis(std::cmp::min( @@ -130,7 +130,7 @@ mod tests { ) } - fn capture_delays(config: &RetryConfig, attempts: &mut u32, delays: &mut Vec) { + fn capture_delays(config: &RetryConfig, attempts: &mut u64, delays: &mut Vec) { loop { *attempts += 1; let delay = super::get_delay(config, *attempts); diff --git a/golem-service-base/src/model.rs b/golem-service-base/src/model.rs index b03277cd2c..45d30089d2 100644 --- a/golem-service-base/src/model.rs +++ b/golem-service-base/src/model.rs @@ -1964,7 +1964,7 @@ impl From for golem_api_grpc::proto::golem::worker::Versioned #[serde(rename_all = "camelCase")] #[oai(rename_all = "camelCase")] pub struct CompleteParameters { - pub oplog_idx: i32, + pub oplog_idx: u64, pub data: Vec, } @@ -1984,7 +1984,7 @@ impl From for golem_api_grpc::proto::golem::worker::Complete #[oai(rename_all = "camelCase")] pub struct PromiseId { pub worker_id: WorkerId, - pub oplog_idx: i32, + pub oplog_idx: u64, } impl TryFrom for PromiseId { diff --git a/golem-worker-executor-base/Cargo.toml b/golem-worker-executor-base/Cargo.toml index 0d33ff0cfc..5070bff107 100644 --- a/golem-worker-executor-base/Cargo.toml +++ b/golem-worker-executor-base/Cargo.toml @@ -42,7 +42,7 @@ fs-set-times = "0.20.1" futures = { workspace = true } futures-util = { workspace = true } gethostname = "0.4.3" -golem-wit = "0.1.0" +golem-wit = "0.2.0" http = { workspace = true } http_02 = { package = "http", version = "0.2.11" } http-body = "1.0.0" # keep in sync with wasmtime diff --git a/golem-worker-executor-base/src/durable_host/blobstore/container.rs b/golem-worker-executor-base/src/durable_host/blobstore/container.rs index 56bfd70c43..26766bce8e 100644 --- a/golem-worker-executor-base/src/durable_host/blobstore/container.rs +++ b/golem-worker-executor-base/src/durable_host/blobstore/container.rs @@ -13,7 +13,7 @@ // limitations under the License. use async_trait::async_trait; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::preview2::WasiView; diff --git a/golem-worker-executor-base/src/durable_host/blobstore/mod.rs b/golem-worker-executor-base/src/durable_host/blobstore/mod.rs index db90999130..96bf23556b 100644 --- a/golem-worker-executor-base/src/durable_host/blobstore/mod.rs +++ b/golem-worker-executor-base/src/durable_host/blobstore/mod.rs @@ -16,7 +16,7 @@ pub mod container; pub mod types; use async_trait::async_trait; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::preview2::WasiView; diff --git a/golem-worker-executor-base/src/durable_host/cli/environment.rs b/golem-worker-executor-base/src/durable_host/cli/environment.rs index d784285f4c..34912ab642 100644 --- a/golem-worker-executor-base/src/durable_host/cli/environment.rs +++ b/golem-worker-executor-base/src/durable_host/cli/environment.rs @@ -18,7 +18,7 @@ use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::wasi::cli::environment::Host; #[async_trait] diff --git a/golem-worker-executor-base/src/durable_host/clocks/monotonic_clock.rs b/golem-worker-executor-base/src/durable_host/clocks/monotonic_clock.rs index 1782d77dc4..58a708b21f 100644 --- a/golem-worker-executor-base/src/durable_host/clocks/monotonic_clock.rs +++ b/golem-worker-executor-base/src/durable_host/clocks/monotonic_clock.rs @@ -19,7 +19,7 @@ use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::wasi::clocks::monotonic_clock::{ Duration, Host, Instant, Pollable, }; diff --git a/golem-worker-executor-base/src/durable_host/clocks/wall_clock.rs b/golem-worker-executor-base/src/durable_host/clocks/wall_clock.rs index 6ab8bceaf0..44b99e88f7 100644 --- a/golem-worker-executor-base/src/durable_host/clocks/wall_clock.rs +++ b/golem-worker-executor-base/src/durable_host/clocks/wall_clock.rs @@ -18,7 +18,7 @@ use crate::durable_host::serialized::{SerializableDateTime, SerializableError}; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::wasi::clocks::wall_clock::{Datetime, Host}; #[async_trait] diff --git a/golem-worker-executor-base/src/durable_host/filesystem/preopens.rs b/golem-worker-executor-base/src/durable_host/filesystem/preopens.rs index 64611d8f82..6d9d4eb073 100644 --- a/golem-worker-executor-base/src/durable_host/filesystem/preopens.rs +++ b/golem-worker-executor-base/src/durable_host/filesystem/preopens.rs @@ -20,7 +20,7 @@ use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::wasi::filesystem::preopens::{Descriptor, Host}; #[async_trait] diff --git a/golem-worker-executor-base/src/durable_host/filesystem/types.rs b/golem-worker-executor-base/src/durable_host/filesystem/types.rs index bcd9aa9529..ff8b4072c2 100644 --- a/golem-worker-executor-base/src/durable_host/filesystem/types.rs +++ b/golem-worker-executor-base/src/durable_host/filesystem/types.rs @@ -28,7 +28,7 @@ use crate::durable_host::serialized::{ use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::clocks::wall_clock::Datetime; use wasmtime_wasi::preview2::bindings::filesystem::types::{ Advice, Descriptor, DescriptorFlags, DescriptorStat, DescriptorType, DirectoryEntry, diff --git a/golem-worker-executor-base/src/durable_host/golem/mod.rs b/golem-worker-executor-base/src/durable_host/golem/mod.rs index 9381d37837..9031889523 100644 --- a/golem-worker-executor-base/src/durable_host/golem/mod.rs +++ b/golem-worker-executor-base/src/durable_host/golem/mod.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use anyhow::anyhow; use async_trait::async_trait; use tracing::debug; use uuid::Uuid; @@ -21,8 +22,11 @@ use crate::durable_host::DurableWorkerCtx; use crate::metrics::wasm::record_host_function_call; use crate::model::InterruptKind; use crate::preview2::golem; +use crate::preview2::golem::api::host::OplogIndex; use crate::workerctx::WorkerCtx; -use golem_common::model::{PromiseId, TemplateId, WorkerId}; +use golem_common::model::oplog::OplogEntry; +use golem_common::model::regions::OplogRegion; +use golem_common::model::{PromiseId, TemplateId, Timestamp, WorkerId}; #[async_trait] impl golem::api::host::Host for DurableWorkerCtx { @@ -82,6 +86,58 @@ impl golem::api::host::Host for DurableWorkerCtx { ); Ok(golem::rpc::types::Uri { value: uri.value }) } + + async fn get_oplog_index(&mut self) -> anyhow::Result { + record_host_function_call("golem::api", "get_oplog_index"); + let result = self.private_state.oplog_idx; + if self.is_live() { + self.set_oplog_entry(OplogEntry::nop(Timestamp::now_utc())) + .await; + } else { + let _ = self.get_oplog_entry_marker().await?; + } + Ok(result) + } + + async fn set_oplog_index(&mut self, oplog_idx: OplogIndex) -> anyhow::Result<()> { + record_host_function_call("golem::api", "set_oplog_index"); + let jump_source = self.private_state.oplog_idx; + let jump_target = oplog_idx; + if jump_target > jump_source { + Err(anyhow!( + "Attempted to jump forward in oplog to index {jump_target} from {jump_source}" + )) + } else if self + .private_state + .deleted_regions + .is_in_deleted_region(jump_target) + { + Err(anyhow!( + "Attempted to jump to a deleted region in oplog to index {jump_target} from {jump_source}" + )) + } else if self.is_live() { + let jump = OplogRegion { + start: jump_target, + end: jump_source, + }; + + // Write an oplog entry with the new jump and then restart the worker + self.private_state.deleted_regions.add(jump.clone()); + self.set_oplog_entry(OplogEntry::jump(Timestamp::now_utc(), jump)) + .await; + self.commit_oplog().await; + + debug!( + "Interrupting live execution of {} for jumping from {jump_source} to {jump_target}", + self.worker_id + ); + Err(InterruptKind::Jump.into()) + } else { + // In replay mode we never have to do anything here + debug!("Ignoring replayed set_oplog_index for {}", self.worker_id); + Ok(()) + } + } } impl From for golem::api::host::WorkerId { diff --git a/golem-worker-executor-base/src/durable_host/http/types.rs b/golem-worker-executor-base/src/durable_host/http/types.rs index e70faf66c5..8e0ad1c895 100644 --- a/golem-worker-executor-base/src/durable_host/http/types.rs +++ b/golem-worker-executor-base/src/durable_host/http/types.rs @@ -20,7 +20,6 @@ use http::{HeaderName, HeaderValue}; use std::collections::HashMap; use std::str::FromStr; -use tracing::info; use wasmtime::component::Resource; use wasmtime_wasi::preview2::subscribe; @@ -33,7 +32,7 @@ use crate::durable_host::http::serialized::{ }; use crate::durable_host::serialized::SerializableError; use crate::workerctx::WorkerCtx; -use golem_common::model::{OplogEntry, WrappedFunctionType}; +use golem_common::model::oplog::{OplogEntry, WrappedFunctionType}; use wasmtime_wasi_http::bindings::wasi::http::types::{ Duration, ErrorCode, FieldKey, FieldValue, Fields, FutureIncomingResponse, FutureTrailers, HeaderError, Headers, Host, HostFields, HostFutureIncomingResponse, HostFutureTrailers, @@ -267,7 +266,6 @@ impl HostRequestOptions for DurableWorkerCtx { ms: Option, ) -> anyhow::Result> { record_host_function_call("http::types::request_options", "set_connect_timeout_ms"); - info!("set_connect_timeout {ms:?}"); HostRequestOptions::set_connect_timeout(&mut self.as_wasi_http_view(), self_, ms) } diff --git a/golem-worker-executor-base/src/durable_host/io/streams.rs b/golem-worker-executor-base/src/durable_host/io/streams.rs index d056cf5a3c..613b8ca0bb 100644 --- a/golem-worker-executor-base/src/durable_host/io/streams.rs +++ b/golem-worker-executor-base/src/durable_host/io/streams.rs @@ -21,7 +21,7 @@ use crate::durable_host::serialized::SerializableStreamError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::wasi::io::streams::{ Host, HostInputStream, HostOutputStream, InputStream, OutputStream, Pollable, }; diff --git a/golem-worker-executor-base/src/durable_host/keyvalue/eventual.rs b/golem-worker-executor-base/src/durable_host/keyvalue/eventual.rs index 4e573559a9..bcaedb2f15 100644 --- a/golem-worker-executor-base/src/durable_host/keyvalue/eventual.rs +++ b/golem-worker-executor-base/src/durable_host/keyvalue/eventual.rs @@ -13,7 +13,7 @@ // limitations under the License. use async_trait::async_trait; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::preview2::WasiView; diff --git a/golem-worker-executor-base/src/durable_host/keyvalue/eventual_batch.rs b/golem-worker-executor-base/src/durable_host/keyvalue/eventual_batch.rs index ecb797a56c..c8afdd5834 100644 --- a/golem-worker-executor-base/src/durable_host/keyvalue/eventual_batch.rs +++ b/golem-worker-executor-base/src/durable_host/keyvalue/eventual_batch.rs @@ -13,7 +13,7 @@ // limitations under the License. use async_trait::async_trait; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::preview2::{ResourceTableError, WasiView}; diff --git a/golem-worker-executor-base/src/durable_host/mod.rs b/golem-worker-executor-base/src/durable_host/mod.rs index 93d96f5d42..4ebc5b1051 100644 --- a/golem-worker-executor-base/src/durable_host/mod.rs +++ b/golem-worker-executor-base/src/durable_host/mod.rs @@ -24,7 +24,7 @@ use std::string::FromUtf8Error; use std::sync::{Arc, RwLock}; use std::time::{Duration, Instant}; -use crate::error::{is_interrupt, is_suspend, GolemError}; +use crate::error::{is_interrupt, is_jump, is_suspend, GolemError}; use crate::invocation::invoke_worker; use crate::model::{CurrentResourceLimits, ExecutionStatus, InterruptKind, WorkerConfig}; use crate::services::active_workers::ActiveWorkers; @@ -46,11 +46,12 @@ use async_trait::async_trait; use bincode::{Decode, Encode}; use bytes::Bytes; use cap_std::ambient_authority; +use golem_common::model::oplog::{OplogEntry, WrappedFunctionType}; +use golem_common::model::regions::{DeletedRegions, OplogRegion}; use golem_common::model::{ AccountId, CallingConvention, InvocationKey, PromiseId, Timestamp, VersionedWorkerId, WorkerId, WorkerMetadata, WorkerStatus, }; -use golem_common::model::{OplogEntry, WrappedFunctionType}; use golem_wasm_rpc::wasmtime::ResourceStore; use golem_wasm_rpc::{Uri, Value}; use serde::de::DeserializeOwned; @@ -73,6 +74,7 @@ use crate::services::rpc::Rpc; use crate::services::scheduler::SchedulerService; use crate::services::HasOplogService; use crate::wasi_host; +use crate::worker::calculate_last_known_status; pub mod blobstore; mod cli; @@ -119,6 +121,10 @@ impl DurableWorkerCtx { self.private_state.commit_oplog().await } + async fn get_oplog_entry_marker(&mut self) -> Result<(), GolemError> { + self.private_state.get_oplog_entry_marker().await + } + async fn get_oplog_entry_imported_function_invoked<'de, R>(&mut self) -> Result where R: Decode + DeserializeOwned, @@ -206,8 +212,7 @@ impl DurableWorkerCtx { |e| GolemError::runtime(format!("Failed to create temporary directory: {e}")), )?); debug!( - "Created temporary file system root for {:?} at {:?}", - worker_id, + "Created temporary file system root for {worker_id} at {:?}", temp_dir.path() ); let root_dir = cap_std::fs::Dir::open_ambient_dir(temp_dir.path(), ambient_authority()) @@ -215,6 +220,11 @@ impl DurableWorkerCtx { let oplog_size = oplog_service.get_size(&worker_id.worker_id).await; + debug!( + "Worker {} initialized with deleted regions {}", + worker_id, worker_config.deleted_regions + ); + let stdio = ManagedStandardIo::new(worker_id.worker_id.clone(), invocation_key_service.clone()); let stdin = ManagedStdIn::from_standard_io(stdio.clone()).await; @@ -263,6 +273,10 @@ impl DurableWorkerCtx { rpc, resources: HashMap::new(), last_resource_id: 0, + deleted_regions: worker_config.deleted_regions.clone(), + next_deleted_region: worker_config + .deleted_regions + .find_next_deleted_region(0), }, temp_dir, execution_status, @@ -295,7 +309,7 @@ impl DurableWorkerCtx { DurableWorkerCtxWasiHttpView(self) } - pub async fn create_promise(&self, oplog_idx: i32) -> PromiseId { + pub async fn create_promise(&self, oplog_idx: u64) -> PromiseId { self.public_state .promise_service .create(&self.worker_id.worker_id, oplog_idx) @@ -373,7 +387,12 @@ impl DurableWorkerCtx { let oplog_idx = self.private_state.oplog_idx; self.private_state .worker_service - .update_status(&self.worker_id.worker_id, status, oplog_idx) + .update_status( + &self.worker_id.worker_id, + status, + self.private_state.deleted_regions.clone(), + oplog_idx, + ) .await } @@ -718,8 +737,9 @@ impl InvocationHooks for DurableWorkerCtx { let is_interrupt = is_interrupt(error); let is_suspend = is_suspend(error); + let is_jump = is_jump(error); - if is_live_after && !is_interrupt && !is_suspend { + if is_live_after && !is_interrupt && !is_suspend && !is_jump { self.set_oplog_entry(OplogEntry::Error { timestamp: Timestamp::now_utc(), }) @@ -750,12 +770,16 @@ impl InvocationHooks for DurableWorkerCtx { let is_interrupt = is_interrupt(error); let is_suspend = is_suspend(error); + let is_jump = is_jump(error); + match decision { RecoveryDecision::None => { if is_interrupt { Ok(WorkerStatus::Interrupted) } else if is_suspend { Ok(WorkerStatus::Suspended) + } else if is_jump { + Ok(WorkerStatus::Running) } else { Ok(WorkerStatus::Failed) } @@ -804,7 +828,10 @@ impl InvocationHooks for DurableWorkerCtx { } } - debug!("Function finished with {:?}", output); + debug!( + "Function {}/{full_function_name} finished with {:?}", + self.worker_id, output + ); // Return indicating that it is done Ok(Some(output)) @@ -843,17 +870,23 @@ impl> ExternalOperations for Dur this: &T, worker_id: &WorkerId, status: WorkerStatus, - ) { - let last_oplog_idx = last_oplog_idx(this, worker_id).await; + ) -> Result<(), GolemError> { + let latest_status = calculate_last_known_status(this, worker_id).await?; this.worker_service() - .update_status(worker_id, status, last_oplog_idx) + .update_status( + worker_id, + status, + latest_status.deleted_regions, + latest_status.oplog_idx, + ) .await; + Ok(()) } async fn get_worker_retry_count + Send + Sync>( this: &T, worker_id: &WorkerId, - ) -> u32 { + ) -> u64 { trailing_error_count(this, worker_id).await } @@ -884,7 +917,7 @@ impl> ExternalOperations for Dur instance: &Instance, store: &mut (impl AsContextMut + Send), ) -> Result<(), GolemError> { - debug!("Starting prepare_instance for {}", worker_id); + debug!("Starting prepare_instance for {worker_id}"); let start = Instant::now(); let mut count = 0; let result = loop { @@ -944,7 +977,7 @@ impl> ExternalOperations for Dur }; record_resume_worker(start.elapsed()); record_number_of_replayed_functions(count); - debug!("Finished prepare_instance for {}", worker_id); + debug!("Finished prepare_instance for {worker_id}"); result } @@ -967,14 +1000,14 @@ impl> ExternalOperations for Dur async fn on_shard_assignment_changed + Send + Sync>( this: &T, ) -> Result<(), anyhow::Error> { - info!("Recovering instances"); + info!("Recovering workers"); - let instances = this.worker_service().get_running_workers_in_shards().await; + let workers = this.worker_service().get_running_workers_in_shards().await; - debug!("Recovering running instances: {:?}", instances); + debug!("Recovering running workers: {:?}", workers); - for instance in instances { - let worker_id = instance.worker_id; + for worker in workers { + let worker_id = worker.worker_id; let previous_tries = Self::get_worker_retry_count(this, &worker_id.worker_id).await; let decision = this .recovery_management() @@ -986,16 +1019,16 @@ impl> ExternalOperations for Dur ); } - info!("Finished recovering instances"); + info!("Finished recovering workers"); Ok(()) } } -async fn last_oplog_idx(this: &T, worker_id: &WorkerId) -> i32 { +async fn last_oplog_idx(this: &T, worker_id: &WorkerId) -> u64 { this.oplog_service().get_size(worker_id).await } -async fn trailing_error_count(this: &T, worker_id: &WorkerId) -> u32 { +async fn trailing_error_count(this: &T, worker_id: &WorkerId) -> u64 { let mut idx = this.oplog_service().get_size(worker_id).await; let mut count = 0; if idx == 0 { @@ -1022,8 +1055,8 @@ async fn trailing_error_count(this: &T, worker_id: &WorkerId pub struct PrivateDurableWorkerState { buffer: VecDeque, - oplog_idx: i32, - oplog_size: i32, + oplog_idx: u64, + oplog_size: u64, oplog_service: Arc, promise_service: Arc, scheduler_service: Arc, @@ -1040,6 +1073,8 @@ pub struct PrivateDurableWorkerState { pub rpc: Arc, resources: HashMap, last_resource_id: u64, + deleted_regions: DeletedRegions, + next_deleted_region: Option, } impl PrivateDurableWorkerState { @@ -1053,11 +1088,11 @@ impl PrivateDurableWorkerState { self.oplog_service.append(worker_id, &arrays).await } - pub async fn get_oplog_size(&mut self) -> i32 { + pub async fn get_oplog_size(&mut self) -> u64 { self.oplog_service.get_size(&self.worker_id).await } - pub async fn read_oplog(&self, idx: i32, n: i32) -> Vec { + pub async fn read_oplog(&self, idx: u64, n: u64) -> Vec { self.oplog_service.read(&self.worker_id, idx, n).await } @@ -1083,12 +1118,55 @@ impl PrivateDurableWorkerState { pub async fn get_oplog_entry(&mut self) -> OplogEntry { assert!(self.is_replay()); + let oplog_entries = self.read_oplog(self.oplog_idx, 1).await; let oplog_entry = oplog_entries[0].clone(); - self.oplog_idx += 1; + + let update_next_deleted_region = match &self.next_deleted_region { + Some(region) if region.start == self.oplog_idx => { + let target = region.end + 1; + debug!( + "Worker {} reached deleted region at {}, jumping to {} (oplog size: {})", + self.worker_id, self.oplog_idx, target, self.oplog_size + ); + self.oplog_idx = target; + true + } + _ => { + self.oplog_idx += 1; + false + } + }; + + if update_next_deleted_region { + self.next_deleted_region = self + .deleted_regions + .find_next_deleted_region(self.oplog_idx); + } + oplog_entry } + async fn get_oplog_entry_marker(&mut self) -> Result<(), GolemError> { + loop { + let oplog_entry = self.get_oplog_entry().await; + match oplog_entry { + OplogEntry::NoOp { .. } => { + break Ok(()); + } + OplogEntry::Suspend { .. } => (), + OplogEntry::Error { .. } => (), + OplogEntry::Debug { message, .. } => debug!("Debug: {}", message), + _ => { + break Err(GolemError::unexpected_oplog_entry( + "NoOp", + format!("{:?}", oplog_entry), + )); + } + } + } + } + async fn get_oplog_entry_imported_function_invoked<'de, R>(&mut self) -> Result where R: Decode + DeserializeOwned, @@ -1212,7 +1290,7 @@ impl PrivateDurableWorkerState { } /// Consumes Suspend and Error entries which are hints for the server to decide whether to - /// keep workers in memory or allow them to rerun etc but contain no actionable information + /// keep workers in memory or allow them to rerun etc., but contain no actionable information /// during replay async fn consume_hint_entries(&mut self) { loop { @@ -1275,7 +1353,7 @@ impl PrivateDurableWorkerState { } /// Counts the number of Error entries that are at the end of the oplog. This equals to the number of retries that have been attempted. - pub async fn trailing_error_count(&self) -> u32 { + pub async fn trailing_error_count(&self) -> u64 { trailing_error_count(self, &self.worker_id).await } } diff --git a/golem-worker-executor-base/src/durable_host/random/insecure.rs b/golem-worker-executor-base/src/durable_host/random/insecure.rs index 99096d7e85..fc694a9145 100644 --- a/golem-worker-executor-base/src/durable_host/random/insecure.rs +++ b/golem-worker-executor-base/src/durable_host/random/insecure.rs @@ -18,7 +18,7 @@ use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::wasi::random::insecure::Host; #[async_trait] diff --git a/golem-worker-executor-base/src/durable_host/random/insecure_seed.rs b/golem-worker-executor-base/src/durable_host/random/insecure_seed.rs index 4f4a738434..bb3e72f149 100644 --- a/golem-worker-executor-base/src/durable_host/random/insecure_seed.rs +++ b/golem-worker-executor-base/src/durable_host/random/insecure_seed.rs @@ -18,7 +18,7 @@ use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::wasi::random::insecure_seed::Host; #[async_trait] diff --git a/golem-worker-executor-base/src/durable_host/random/random.rs b/golem-worker-executor-base/src/durable_host/random/random.rs index 3bb3dca9ac..a0e809aa73 100644 --- a/golem-worker-executor-base/src/durable_host/random/random.rs +++ b/golem-worker-executor-base/src/durable_host/random/random.rs @@ -18,7 +18,7 @@ use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::wasi::random::random::Host; #[async_trait] diff --git a/golem-worker-executor-base/src/durable_host/serialized.rs b/golem-worker-executor-base/src/durable_host/serialized.rs index ce4f3b2281..bb57672258 100644 --- a/golem-worker-executor-base/src/durable_host/serialized.rs +++ b/golem-worker-executor-base/src/durable_host/serialized.rs @@ -595,7 +595,7 @@ mod tests { } fn promiseid_strat() -> impl Strategy { - (workerid_strat(), any::()).prop_map(|(worker_id, oplog_idx)| PromiseId { + (workerid_strat(), any::()).prop_map(|(worker_id, oplog_idx)| PromiseId { worker_id, oplog_idx, }) diff --git a/golem-worker-executor-base/src/durable_host/sockets/ip_name_lookup.rs b/golem-worker-executor-base/src/durable_host/sockets/ip_name_lookup.rs index 6024b375ea..e83cfee343 100644 --- a/golem-worker-executor-base/src/durable_host/sockets/ip_name_lookup.rs +++ b/golem-worker-executor-base/src/durable_host/sockets/ip_name_lookup.rs @@ -19,7 +19,7 @@ use crate::durable_host::serialized::{SerializableError, SerializableIpAddresses use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::WrappedFunctionType; +use golem_common::model::oplog::WrappedFunctionType; use wasmtime_wasi::preview2::bindings::sockets::network::ErrorCode; use wasmtime_wasi::preview2::bindings::wasi::sockets::ip_name_lookup::{ Host, HostResolveAddressStream, IpAddress, Network, Pollable, ResolveAddressStream, diff --git a/golem-worker-executor-base/src/durable_host/wasm_rpc/mod.rs b/golem-worker-executor-base/src/durable_host/wasm_rpc/mod.rs index 72141b4963..95b14fec9d 100644 --- a/golem-worker-executor-base/src/durable_host/wasm_rpc/mod.rs +++ b/golem-worker-executor-base/src/durable_host/wasm_rpc/mod.rs @@ -19,7 +19,8 @@ use crate::services::rpc::{RpcDemand, RpcError}; use crate::workerctx::WorkerCtx; use anyhow::anyhow; use async_trait::async_trait; -use golem_common::model::{TemplateId, WorkerId, WrappedFunctionType}; +use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::{TemplateId, WorkerId}; use golem_wasm_rpc::golem::rpc::types::Uri; use golem_wasm_rpc::{HostWasmRpc, WasmRpcEntry, WitValue}; use std::str::FromStr; @@ -82,11 +83,11 @@ impl HostWasmRpc for DurableWorkerCtx { match result { Ok(result) => { - debug!("RPC result: {result:?}"); + debug!("RPC result for {}: {result:?}", self.worker_id); Ok(Ok(result)) } Err(err) => { - error!("RPC error: {err}"); + error!("RPC error for {}: {err}", self.worker_id); match err { RpcError::ProtocolError { details } => { Ok(Err(golem_wasm_rpc::RpcError::ProtocolError(details))) diff --git a/golem-worker-executor-base/src/error.rs b/golem-worker-executor-base/src/error.rs index d4ba131ea8..e5bf270bea 100644 --- a/golem-worker-executor-base/src/error.rs +++ b/golem-worker-executor-base/src/error.rs @@ -740,3 +740,10 @@ pub fn is_suspend(error: &anyhow::Error) -> bool { .downcast_ref::() .map_or(false, |kind| *kind == InterruptKind::Suspend) } + +pub fn is_jump(error: &anyhow::Error) -> bool { + error + .root_cause() + .downcast_ref::() + .map_or(false, |kind| *kind == InterruptKind::Jump) +} diff --git a/golem-worker-executor-base/src/grpc.rs b/golem-worker-executor-base/src/grpc.rs index f9f16ec99f..4a621839e5 100644 --- a/golem-worker-executor-base/src/grpc.rs +++ b/golem-worker-executor-base/src/grpc.rs @@ -172,7 +172,6 @@ impl + UsesAllDeps + Send + Sync + worker_id: &common_model::WorkerId, metadata: &Option, ) -> Result { - debug!("validate_worker_status for {worker_id}"); let worker_status = Ctx::get_assumed_worker_status(self, worker_id, metadata).await; match worker_status { @@ -410,11 +409,11 @@ impl + UsesAllDeps + Send + Sync + } WorkerStatus::Suspended => { debug!("Marking suspended worker {worker_id} as interrupted"); - Ctx::set_worker_status(self, &worker_id, WorkerStatus::Interrupted).await; + Ctx::set_worker_status(self, &worker_id, WorkerStatus::Interrupted).await?; } WorkerStatus::Retrying => { debug!("Marking worker {worker_id} scheduled to be retried as interrupted"); - Ctx::set_worker_status(self, &worker_id, WorkerStatus::Interrupted).await; + Ctx::set_worker_status(self, &worker_id, WorkerStatus::Interrupted).await?; } WorkerStatus::Running => { let worker_state = Worker::get_or_create_with_config( diff --git a/golem-worker-executor-base/src/invocation.rs b/golem-worker-executor-base/src/invocation.rs index a4be6447ea..2dedc93438 100644 --- a/golem-worker-executor-base/src/invocation.rs +++ b/golem-worker-executor-base/src/invocation.rs @@ -22,7 +22,7 @@ use tracing::{debug, error, warn}; use wasmtime::component::{Func, Val}; use wasmtime::{AsContextMut, StoreContextMut}; -use crate::error::{is_interrupt, is_suspend, GolemError}; +use crate::error::{is_interrupt, is_jump, is_suspend, GolemError}; use crate::metrics::wasm::{record_invocation, record_invocation_consumption}; use crate::workerctx::{FuelManagement, WorkerCtx}; @@ -49,14 +49,12 @@ pub async fn invoke_worker( let mut store = store.as_context_mut(); let worker_id = store.data().worker_id().clone(); - debug!("invoke_worker_impl: {worker_id}/{full_function_name}"); + debug!("invoke_worker: {worker_id}/{full_function_name}"); if let Some(invocation_key) = &store.data().get_current_invocation_key().await { store.data_mut().resume_invocation_key(invocation_key).await } - debug!("invoke_worker_impl_or_fail: {worker_id}/{full_function_name}"); - let result = invoke_or_fail( &worker_id, full_function_name.clone(), @@ -69,7 +67,7 @@ pub async fn invoke_worker( .await; debug!( - "invoke_worker_impl_or_fail: {worker_id}/{full_function_name} resulted in {:?}", + "invoke_or_fail: {worker_id}/{full_function_name} resulted in {:?}", result ); @@ -81,7 +79,7 @@ pub async fn invoke_worker( match invocation_key { Some(invocation_key) => { debug!( - "Storing interrupted status for invocation key {:?}", + "Storing interrupted status for invocation key {:?} in {worker_id}/{full_function_name}", &invocation_key ); store @@ -99,12 +97,16 @@ pub async fn invoke_worker( // this invocation was suspended and expected to be resumed by an external call or schedule record_invocation(was_live_before, "suspended"); false + } else if is_jump(&err) { + // the worker needs to be restarted in order to jump to the past, but otherwise continues running + record_invocation(was_live_before, "jump"); + false } else { // this invocation failed it won't be retried later match invocation_key { Some(invocation_key) => { debug!( - "Storing failed result for invocation key {:?}", + "Storing failed result for invocation key {:?} in {worker_id}/{full_function_name}", &invocation_key ); store @@ -300,7 +302,10 @@ async fn invoke( call_exported_function(&mut store, function, params, context).await?; for resource in resources_to_drop { - debug!("Dropping passed owned resources {:?}", resource); + debug!( + "Dropping passed owned resources {:?} in {context}", + resource + ); resource.resource_drop_async(&mut store).await?; } @@ -313,7 +318,7 @@ async fn invoke( output.push(result_value); } - store_results(&mut store, &output).await; + store_results(&mut store, &output, context).await; Ok(InvokeResult { exited: false, @@ -349,7 +354,7 @@ async fn invoke( let stdout = store.data_mut().finish_capturing_stdout().await.ok(); let output: Vec = vec![Value::String(stdout.unwrap_or("".to_string()))]; - store_results(&mut store, &output).await; + store_results(&mut store, &output, context).await; Ok(InvokeResult { exited, @@ -360,10 +365,14 @@ async fn invoke( } } -async fn store_results<'a, Ctx: WorkerCtx>(store: &mut StoreContextMut<'a, Ctx>, output: &[Value]) { +async fn store_results<'a, Ctx: WorkerCtx>( + store: &mut StoreContextMut<'a, Ctx>, + output: &[Value], + context: &str, +) { if let Some(invocation_key) = store.data().get_current_invocation_key().await { debug!( - "Storing successful results for invocation key {:?}", + "Storing successful results for invocation key {:?} in {context}", &invocation_key ); @@ -372,7 +381,7 @@ async fn store_results<'a, Ctx: WorkerCtx>(store: &mut StoreContextMut<'a, Ctx>, .confirm_invocation_key(&invocation_key, Ok(output.to_vec())) .await; } else { - debug!("No invocation key"); + debug!("No invocation key for {context}"); } } @@ -414,7 +423,7 @@ async fn drop_resource( } let output = Vec::new(); - store_results(&mut store, &output).await; + store_results(&mut store, &output, context).await; Ok(InvokeResult { exited: false, @@ -456,7 +465,10 @@ async fn call_exported_function( .data_mut() .return_fuel(current_fuel_level as i64) .await?; - debug!("fuel consumed for call: {}", consumed_fuel_for_call); + debug!( + "fuel consumed for call {context}: {}", + consumed_fuel_for_call + ); record_invocation_consumption(consumed_fuel_for_call); Ok((result.map(|_| results), consumed_fuel_for_call)) diff --git a/golem-worker-executor-base/src/model.rs b/golem-worker-executor-base/src/model.rs index 3c45c414af..a0d0df76be 100644 --- a/golem-worker-executor-base/src/model.rs +++ b/golem-worker-executor-base/src/model.rs @@ -17,6 +17,7 @@ use std::error::Error; use std::fmt::{Debug, Display, Formatter}; use std::sync::Arc; +use golem_common::model::regions::DeletedRegions; use golem_common::model::{ShardAssignment, ShardId, VersionedWorkerId, WorkerId}; use serde::{Deserialize, Serialize}; @@ -45,6 +46,7 @@ pub enum InterruptKind { Interrupt, Restart, Suspend, + Jump, } impl Display for InterruptKind { @@ -53,18 +55,20 @@ impl Display for InterruptKind { InterruptKind::Interrupt => write!(f, "Interrupted via the Golem API"), InterruptKind::Restart => write!(f, "Simulated crash via the Golem API"), InterruptKind::Suspend => write!(f, "Suspended"), + InterruptKind::Jump => write!(f, "Jumping back in time"), } } } impl Error for InterruptKind {} -/// Worker-specific configuration. These values are used to initialize the worker and they can +/// Worker-specific configuration. These values are used to initialize the worker, and they can /// be different for each worker. #[derive(Clone, Debug)] pub struct WorkerConfig { pub args: Vec, pub env: Vec<(String, String)>, + pub deleted_regions: DeletedRegions, } impl WorkerConfig { @@ -72,6 +76,7 @@ impl WorkerConfig { versioned_worker_id: VersionedWorkerId, worker_args: Vec, mut worker_env: Vec<(String, String)>, + deleted_regions: DeletedRegions, ) -> WorkerConfig { let worker_name = versioned_worker_id.worker_id.worker_name.clone(); let template_id = versioned_worker_id.worker_id.template_id; @@ -82,6 +87,7 @@ impl WorkerConfig { WorkerConfig { args: worker_args, env: worker_env, + deleted_regions, } } } diff --git a/golem-worker-executor-base/src/preview2/mod.rs b/golem-worker-executor-base/src/preview2/mod.rs index 68ec0c84a1..7ee3dc10a7 100644 --- a/golem-worker-executor-base/src/preview2/mod.rs +++ b/golem-worker-executor-base/src/preview2/mod.rs @@ -15,7 +15,7 @@ wasmtime::component::bindgen!({ path: "golem-wit/wit", interfaces: " - import golem:api/host; + import golem:api/host@0.2.0; import wasi:blobstore/blobstore; import wasi:blobstore/container; diff --git a/golem-worker-executor-base/src/services/compiled_template.rs b/golem-worker-executor-base/src/services/compiled_template.rs index e7a2efbfd7..e09348b0ed 100644 --- a/golem-worker-executor-base/src/services/compiled_template.rs +++ b/golem-worker-executor-base/src/services/compiled_template.rs @@ -62,7 +62,10 @@ pub async fn configured( aws_config::defaults(BehaviorVersion::v2023_11_09()).region(Region::new(region)); let sdk_config = if let Some(endpoint_url) = &config.aws_endpoint_url { - info!("The endpoint urls is {}", &endpoint_url); + info!( + "The AWS endpoint urls for compiled template service is {}", + &endpoint_url + ); sdk_config_base.endpoint_url(endpoint_url).load().await } else { sdk_config_base.load().await diff --git a/golem-worker-executor-base/src/services/invocation_key.rs b/golem-worker-executor-base/src/services/invocation_key.rs index e9185b79ea..d74c29d2c1 100644 --- a/golem-worker-executor-base/src/services/invocation_key.rs +++ b/golem-worker-executor-base/src/services/invocation_key.rs @@ -212,7 +212,7 @@ impl InvocationKeyService for InvocationKeyServiceDefault { worker_id: &WorkerId, key: &InvocationKey, ) -> LookupResult { - debug!("wait_for_confirmation {key:?}"); + debug!("wait_for_confirmation for {worker_id}: {key:?}"); loop { match self.lookup_key(worker_id, key) { LookupResult::Invalid => break LookupResult::Invalid, diff --git a/golem-worker-executor-base/src/services/oplog.rs b/golem-worker-executor-base/src/services/oplog.rs index d1d411f8fb..59ce0f65e0 100644 --- a/golem-worker-executor-base/src/services/oplog.rs +++ b/golem-worker-executor-base/src/services/oplog.rs @@ -19,7 +19,7 @@ use bytes::Bytes; use fred::prelude::RedisValue; use fred::types::RedisKey; use golem_common::metrics::redis::record_redis_serialized_size; -use golem_common::model::OplogEntry; +use golem_common::model::oplog::OplogEntry; use golem_common::model::WorkerId; use golem_common::redis::RedisPool; @@ -29,11 +29,11 @@ use crate::metrics::oplog::record_oplog_call; pub trait OplogService { async fn append(&self, worker_id: &WorkerId, arrays: &[OplogEntry]); - async fn get_size(&self, worker_id: &WorkerId) -> i32; + async fn get_size(&self, worker_id: &WorkerId) -> u64; async fn delete(&self, worker_id: &WorkerId); - async fn read(&self, worker_id: &WorkerId, idx: i32, n: i32) -> Vec; + async fn read(&self, worker_id: &WorkerId, idx: u64, n: u64) -> Vec; } #[derive(Clone, Debug)] @@ -109,7 +109,7 @@ impl OplogService for OplogServiceDefault { } } - async fn get_size(&self, worker_id: &WorkerId) -> i32 { + async fn get_size(&self, worker_id: &WorkerId) -> u64 { record_oplog_call("get_size"); let key = get_oplog_redis_key(worker_id); @@ -137,7 +137,7 @@ impl OplogService for OplogServiceDefault { }); } - async fn read(&self, worker_id: &WorkerId, idx: i32, n: i32) -> Vec { + async fn read(&self, worker_id: &WorkerId, idx: u64, n: u64) -> Vec { record_oplog_call("read"); let key = get_oplog_redis_key(worker_id); @@ -200,7 +200,7 @@ impl OplogService for OplogServiceMock { unimplemented!() } - async fn get_size(&self, _worker_id: &WorkerId) -> i32 { + async fn get_size(&self, _worker_id: &WorkerId) -> u64 { unimplemented!() } @@ -208,7 +208,7 @@ impl OplogService for OplogServiceMock { unimplemented!() } - async fn read(&self, _worker_id: &WorkerId, _idx: i32, _n: i32) -> Vec { + async fn read(&self, _worker_id: &WorkerId, _idx: u64, _n: u64) -> Vec { unimplemented!() } } diff --git a/golem-worker-executor-base/src/services/promise.rs b/golem-worker-executor-base/src/services/promise.rs index 650c56fea4..41ad5faa41 100644 --- a/golem-worker-executor-base/src/services/promise.rs +++ b/golem-worker-executor-base/src/services/promise.rs @@ -37,7 +37,7 @@ use crate::services::golem_config::PromisesConfig; /// Service implementing creation, completion and polling of promises #[async_trait] pub trait PromiseService { - async fn create(&self, worker_id: &WorkerId, oplog_idx: i32) -> PromiseId; + async fn create(&self, worker_id: &WorkerId, oplog_idx: u64) -> PromiseId; async fn wait_for(&self, promise_id: PromiseId) -> Result, GolemError>; @@ -90,7 +90,7 @@ impl PromiseServiceRedis { #[async_trait] impl PromiseService for PromiseServiceRedis { - async fn create(&self, worker_id: &WorkerId, oplog_idx: i32) -> PromiseId { + async fn create(&self, worker_id: &WorkerId, oplog_idx: u64) -> PromiseId { let promise_id = PromiseId { worker_id: worker_id.clone(), oplog_idx, @@ -294,7 +294,7 @@ impl PromiseServiceInMemory { #[async_trait] impl PromiseService for PromiseServiceInMemory { - async fn create(&self, worker_id: &WorkerId, oplog_idx: i32) -> PromiseId { + async fn create(&self, worker_id: &WorkerId, oplog_idx: u64) -> PromiseId { let promise_id = PromiseId { worker_id: worker_id.clone(), oplog_idx, @@ -382,7 +382,7 @@ impl PromiseServiceMock { #[cfg(any(feature = "mocks", test))] #[async_trait] impl PromiseService for PromiseServiceMock { - async fn create(&self, _worker_id: &WorkerId, _oplog_idx: i32) -> PromiseId { + async fn create(&self, _worker_id: &WorkerId, _oplog_idx: u64) -> PromiseId { unimplemented!() } diff --git a/golem-worker-executor-base/src/services/recovery.rs b/golem-worker-executor-base/src/services/recovery.rs index ada4c98f1a..014c79958f 100644 --- a/golem-worker-executor-base/src/services/recovery.rs +++ b/golem-worker-executor-base/src/services/recovery.rs @@ -48,13 +48,13 @@ pub trait RecoveryManagement { async fn schedule_recovery_for_error( &self, worker_id: &VersionedWorkerId, - previous_tries: u32, + previous_tries: u64, current_error: &anyhow::Error, ) -> RecoveryDecision; async fn schedule_recovery_on_startup( &self, worker_id: &VersionedWorkerId, - previous_tries: u32, + previous_tries: u64, ) -> RecoveryDecision; } @@ -280,13 +280,14 @@ impl RecoveryManagementDefault { fn get_recovery_decision_for_error( &self, - previous_tries: u32, + previous_tries: u64, current_error: &anyhow::Error, ) -> RecoveryDecision { match current_error.root_cause().downcast_ref::() { Some(InterruptKind::Interrupt) => RecoveryDecision::None, Some(InterruptKind::Suspend) => RecoveryDecision::None, Some(InterruptKind::Restart) => RecoveryDecision::Immediate, + Some(InterruptKind::Jump) => RecoveryDecision::Immediate, None => match Ctx::is_exit(current_error) { Some(_) => RecoveryDecision::None, None => match current_error.root_cause().downcast_ref::() { @@ -307,8 +308,8 @@ impl RecoveryManagementDefault { } } - fn get_recovery_decision_on_startup(&self, previous_tries: u32) -> RecoveryDecision { - if previous_tries < self.golem_config.retry.max_attempts { + fn get_recovery_decision_on_startup(&self, previous_tries: u64) -> RecoveryDecision { + if previous_tries < (self.golem_config.retry.max_attempts as u64) { RecoveryDecision::Immediate } else { RecoveryDecision::None @@ -401,7 +402,7 @@ impl RecoveryManagement for RecoveryManagementDefault { async fn schedule_recovery_for_error( &self, worker_id: &VersionedWorkerId, - previous_tries: u32, + previous_tries: u64, current_error: &anyhow::Error, ) -> RecoveryDecision { self.schedule_recovery( @@ -414,7 +415,7 @@ impl RecoveryManagement for RecoveryManagementDefault { async fn schedule_recovery_on_startup( &self, worker_id: &VersionedWorkerId, - previous_tries: u32, + previous_tries: u64, ) -> RecoveryDecision { self.schedule_recovery( worker_id, @@ -476,7 +477,7 @@ impl RecoveryManagement for RecoveryManagementMock { async fn schedule_recovery_for_error( &self, _worker_id: &VersionedWorkerId, - _previous_tries: u32, + _previous_tries: u64, _current_error: &anyhow::Error, ) -> RecoveryDecision { unimplemented!() @@ -485,7 +486,7 @@ impl RecoveryManagement for RecoveryManagementMock { async fn schedule_recovery_on_startup( &self, _worker_id: &VersionedWorkerId, - _previous_tries: u32, + _previous_tries: u64, ) -> RecoveryDecision { unimplemented!() } @@ -681,14 +682,14 @@ mod tests { _this: &T, _worker_id: &WorkerId, _status: WorkerStatus, - ) { + ) -> Result<(), GolemError> { unimplemented!() } async fn get_worker_retry_count + Send + Sync>( _this: &T, _worker_id: &WorkerId, - ) -> u32 { + ) -> u64 { unimplemented!() } diff --git a/golem-worker-executor-base/src/services/worker.rs b/golem-worker-executor-base/src/services/worker.rs index 76a314de46..7ec3032c24 100644 --- a/golem-worker-executor-base/src/services/worker.rs +++ b/golem-worker-executor-base/src/services/worker.rs @@ -19,9 +19,10 @@ use bytes::Bytes; use dashmap::DashMap; use fred::prelude::*; use golem_common::metrics::redis::record_redis_serialized_size; +use golem_common::model::regions::DeletedRegions; use golem_common::model::{ShardId, WorkerId, WorkerMetadata, WorkerStatus, WorkerStatusRecord}; use golem_common::redis::RedisPool; -use tracing::{debug, error}; +use tracing::debug; use crate::error::GolemError; use crate::metrics::workers::record_worker_call; @@ -41,7 +42,13 @@ pub trait WorkerService { async fn enumerate(&self) -> Vec; - async fn update_status(&self, worker_id: &WorkerId, status: WorkerStatus, oplog_idx: i32); + async fn update_status( + &self, + worker_id: &WorkerId, + status: WorkerStatus, + deleted_regions: DeletedRegions, + oplog_idx: u64, + ); } pub fn configured( @@ -113,7 +120,7 @@ impl WorkerService for WorkerServiceRedis { record_redis_serialized_size("instance", "details", details_value.len()); - let old_details_value: Option = self + let _ = self .redis .with("instance", "add") .set( @@ -127,23 +134,10 @@ impl WorkerService for WorkerServiceRedis { .unwrap_or_else(|err| { panic!("failed to set worker metadata for {details_key} in Redis: {err}") }); - - let metadata = match old_details_value { - Some(old_details_value) => { - if details_value == old_details_value { - Ok(()) - } else { - error!("Trying to activate existing worker {worker_id} with different metadata: {:?} vs {:?}", old_details_value, details_value); - Err(GolemError::WorkerAlreadyExists { - worker_id: worker_id.clone(), - }) - } - } - None => { - debug!("add_worker for {worker_id} succeeded"); - Ok(()) - } - }; + // NOTE: we used to check here if the old and new metadata values are equivalent but this no longer works + // because of the worker status record which may be recalculated from latest oplog entries. This + // is not a problem though because soon by https://github.com/golemcloud/golem/issues/238 the static + // part will no longer be stored in Redis. let status_key = get_worker_status_redis_key(worker_id); let status_value = self @@ -204,7 +198,7 @@ impl WorkerService for WorkerServiceRedis { ) }); - metadata + Ok(()) } async fn get(&self, worker_id: &WorkerId) -> Option { @@ -325,12 +319,19 @@ impl WorkerService for WorkerServiceRedis { self.enum_workers_at_key(key).await } - async fn update_status(&self, worker_id: &WorkerId, status: WorkerStatus, oplog_idx: i32) { + async fn update_status( + &self, + worker_id: &WorkerId, + status: WorkerStatus, + deleted_regions: DeletedRegions, + oplog_idx: u64, + ) { record_worker_call("update_status"); let status_key = get_worker_status_redis_key(worker_id); let status_value = WorkerStatusRecord { status: status.clone(), + deleted_regions, oplog_idx, }; let serialized_status_value = self.redis.serialize(&status_value).unwrap_or_else(|err| { @@ -458,9 +459,19 @@ impl WorkerService for WorkerServiceInMemory { self.workers.iter().map(|i| i.clone()).collect() } - async fn update_status(&self, worker_id: &WorkerId, status: WorkerStatus, oplog_idx: i32) { + async fn update_status( + &self, + worker_id: &WorkerId, + status: WorkerStatus, + deleted_regions: DeletedRegions, + oplog_idx: u64, + ) { self.workers.entry(worker_id.clone()).and_modify(|worker| { - worker.last_known_status = WorkerStatusRecord { status, oplog_idx } + worker.last_known_status = WorkerStatusRecord { + status, + deleted_regions, + oplog_idx, + } }); } } @@ -505,7 +516,13 @@ impl WorkerService for WorkerServiceMock { unimplemented!() } - async fn update_status(&self, _worker_id: &WorkerId, _status: WorkerStatus, _oplog_idx: i32) { + async fn update_status( + &self, + _worker_id: &WorkerId, + _status: WorkerStatus, + _deleted_regions: DeletedRegions, + _oplog_idx: u64, + ) { unimplemented!() } } diff --git a/golem-worker-executor-base/src/wasi_host/mod.rs b/golem-worker-executor-base/src/wasi_host/mod.rs index 2652705613..66ac89d2bd 100644 --- a/golem-worker-executor-base/src/wasi_host/mod.rs +++ b/golem-worker-executor-base/src/wasi_host/mod.rs @@ -17,7 +17,6 @@ use std::time::Duration; use cap_std::fs::Dir; -use tracing::debug; use wasmtime::component::Linker; use wasmtime::Engine; use wasmtime_wasi::preview2::bindings::wasi; @@ -139,7 +138,6 @@ where F: FnOnce(WasiCtx, ResourceTable) -> T, { let table = ResourceTable::new(); - debug!("Creating WASI context, root directory is {:?}", root_dir); let wasi = WasiCtxBuilder::new() .args(args) .envs(env) diff --git a/golem-worker-executor-base/src/worker.rs b/golem-worker-executor-base/src/worker.rs index dbee94ee98..8587f30e2e 100644 --- a/golem-worker-executor-base/src/worker.rs +++ b/golem-worker-executor-base/src/worker.rs @@ -20,9 +20,11 @@ use std::time::Instant; use async_mutex::Mutex; use bytes::Bytes; use golem_common::cache::PendingOrFinal; +use golem_common::model::oplog::OplogEntry; +use golem_common::model::regions::{DeletedRegions, DeletedRegionsBuilder}; use golem_common::model::{ AccountId, CallingConvention, InvocationKey, VersionedWorkerId, WorkerId, WorkerMetadata, - WorkerStatusRecord, + WorkerStatus, WorkerStatusRecord, }; use golem_wasm_rpc::Value; use tokio::sync::broadcast::Receiver; @@ -36,7 +38,7 @@ use crate::model::{ExecutionStatus, InterruptKind, WorkerConfig}; use crate::services::golem_config::GolemConfig; use crate::services::invocation_key::LookupResult; use crate::services::worker_event::{WorkerEventService, WorkerEventServiceDefault}; -use crate::services::{HasAll, HasInvocationKeyService}; +use crate::services::{HasAll, HasInvocationKeyService, HasOplogService, HasWorkerService}; use crate::workerctx::{PublicWorkerIo, WorkerCtx}; /// Worker is one active wasmtime instance representing a Golem worker with its corresponding @@ -114,7 +116,11 @@ impl Worker { args: worker_args.clone(), env: worker_env.clone(), account_id, - last_known_status: WorkerStatusRecord::default(), + last_known_status: calculate_last_known_status( + this, + &versioned_worker_id.worker_id, + ) + .await?, }; this.worker_service().add(&worker_metadata).await?; @@ -137,7 +143,12 @@ impl Worker { this.rpc(), this.extra_deps(), this.config(), - WorkerConfig::new(worker_metadata.worker_id.clone(), worker_args, worker_env), + WorkerConfig::new( + worker_metadata.worker_id.clone(), + worker_args, + worker_env, + worker_metadata.last_known_status.deleted_regions.clone(), + ), execution_status.clone(), ) .await?; @@ -146,10 +157,11 @@ impl Worker { let mut store = Store::new(&this.engine(), context); store.set_epoch_deadline(this.config().limits.epoch_ticks); - store.epoch_deadline_callback(|mut store| { + let worker_id_clone = versioned_worker_id.worker_id.clone(); + store.epoch_deadline_callback(move |mut store| { let current_level = store.get_fuel().unwrap_or(0); if store.data().is_out_of_fuel(current_level as i64) { - debug!("ran out of fuel, borrowing more"); + debug!("{worker_id_clone} ran out of fuel, borrowing more"); store.data_mut().borrow_fuel_sync(); } @@ -167,7 +179,7 @@ impl Worker { let instance_pre = this.linker().instantiate_pre(&component).map_err(|e| { GolemError::worker_creation_failed( worker_id.clone(), - format!("Failed to pre-instantiate component: {e}"), + format!("Failed to pre-instantiate worker {worker_id}: {e}"), ) })?; @@ -177,7 +189,7 @@ impl Worker { .map_err(|e| { GolemError::worker_creation_failed( worker_id.clone(), - format!("Failed to instantiate component: {e}"), + format!("Failed to instantiate worker {worker_id}: {e}"), ) })?; @@ -595,8 +607,9 @@ pub async fn invoke_and_await( where T: HasInvocationKeyService, { + let worker_id = worker.metadata.worker_id.worker_id.clone(); match invoke( - worker.clone(), + worker, this, invocation_key.clone(), calling_convention, @@ -608,18 +621,20 @@ where Some(Ok(output)) => Ok(output), Some(Err(err)) => Err(err), None => { - let worker_id = &worker.metadata.worker_id.worker_id; let invocation_key = invocation_key.expect("missing invocation key for invoke-and-await"); - debug!("Waiting for invocation key {} to complete", invocation_key); + debug!( + "Waiting for invocation key {} to complete for {worker_id}", + invocation_key + ); let result = this .invocation_key_service() - .wait_for_confirmation(worker_id, &invocation_key) + .wait_for_confirmation(&worker_id, &invocation_key) .await; debug!( - "Invocation key {} lookup result: {:?}", + "Invocation key {} lookup result for {worker_id}: {:?}", invocation_key, result ); match result { @@ -636,3 +651,60 @@ where } } } + +/// Gets the last cached worker status record and the new oplog entries and calculates the new worker status. +pub async fn calculate_last_known_status( + this: &T, + worker_id: &WorkerId, +) -> Result +where + T: HasOplogService + HasWorkerService, +{ + let last_known = this + .worker_service() + .get(worker_id) + .await + .map(|metadata| metadata.last_known_status.clone()) + .unwrap_or_default(); + + let last_oplog_index = this.oplog_service().get_size(worker_id).await; + if last_known.oplog_idx == last_oplog_index { + Ok(last_known) + } else { + let new_entries = this + .oplog_service() + .read( + worker_id, + last_known.oplog_idx, + last_oplog_index - last_known.oplog_idx, + ) + .await; + + let status = calculate_latest_worker_status(&last_known.status, &new_entries); + let deleted_regions = calculate_deleted_regions(last_known.deleted_regions, &new_entries); + + Ok(WorkerStatusRecord { + oplog_idx: last_oplog_index, + status, + deleted_regions, + }) + } +} + +fn calculate_latest_worker_status( + _initial: &WorkerStatus, + _entries: &[OplogEntry], +) -> WorkerStatus { + // TODO: this is currently not 100% accurate because we don't have an Interrupted oplog entry, see https://github.com/golemcloud/golem/issues/239 + WorkerStatus::Running +} + +fn calculate_deleted_regions(initial: DeletedRegions, entries: &[OplogEntry]) -> DeletedRegions { + let mut builder = DeletedRegionsBuilder::from_regions(initial.into_regions()); + for entry in entries { + if let OplogEntry::Jump { jump, .. } = entry { + builder.add(jump.clone()); + } + } + builder.build() +} diff --git a/golem-worker-executor-base/src/workerctx.rs b/golem-worker-executor-base/src/workerctx.rs index c6de8efb83..c0d028c133 100644 --- a/golem-worker-executor-base/src/workerctx.rs +++ b/golem-worker-executor-base/src/workerctx.rs @@ -286,13 +286,13 @@ pub trait ExternalOperations { this: &T, worker_id: &WorkerId, status: WorkerStatus, - ); + ) -> Result<(), GolemError>; /// Gets how many times the worker has been retried to recover from an error. async fn get_worker_retry_count + Send + Sync>( this: &T, worker_id: &WorkerId, - ) -> u32; + ) -> u64; /// Gets a best-effort current worker status without activating the worker async fn get_assumed_worker_status + Send + Sync>( diff --git a/golem-worker-executor-base/tests/common/mod.rs b/golem-worker-executor-base/tests/common/mod.rs index d002ccd1e4..f232fad192 100644 --- a/golem-worker-executor-base/tests/common/mod.rs +++ b/golem-worker-executor-base/tests/common/mod.rs @@ -31,7 +31,8 @@ use golem_api_grpc::proto::golem::workerexecutor::{ InvokeWorkerRequest, ResumeWorkerRequest, }; use golem_common::model::{ - AccountId, InvocationKey, TemplateId, VersionedWorkerId, WorkerId, WorkerMetadata, WorkerStatus, + AccountId, InvocationKey, TemplateId, VersionedWorkerId, WorkerId, WorkerMetadata, + WorkerStatus, WorkerStatusRecord, }; use golem_worker_executor_base::error::GolemError; use golem_worker_executor_base::services::golem_config::{ @@ -72,11 +73,13 @@ use golem_worker_executor_base::workerctx::{ use golem_worker_executor_base::Bootstrap; use serde_json::Value as JsonValue; use tokio::runtime::Handle; +use tokio::select; use tokio::sync::mpsc::UnboundedReceiver; use tokio::task::JoinHandle; use golem::api; use golem_common::config::RedisConfig; +use golem_common::model::regions::DeletedRegions; use golem_worker_executor_base::preview2::golem; use golem_worker_executor_base::services::rpc::{ DirectWorkerInvocationRpc, RemoteInvocationRpc, Rpc, @@ -243,9 +246,29 @@ impl TestWorkerExecutor { match response.result { None => panic!("No response from connect_worker"), - Some(get_worker_metadata_response::Result::Success(metadata)) => { - Some(metadata.try_into().unwrap()) - } + Some(get_worker_metadata_response::Result::Success(metadata)) => Some(WorkerMetadata { + worker_id: VersionedWorkerId { + worker_id: metadata + .worker_id + .expect("no worker_id") + .clone() + .try_into() + .expect("invalid worker_id"), + template_version: metadata.template_version, + }, + args: metadata.args.clone(), + env: metadata + .env + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect::>(), + account_id: metadata.account_id.expect("no account_id").clone().into(), + last_known_status: WorkerStatusRecord { + oplog_idx: 0, + status: metadata.status.try_into().expect("invalid status"), + deleted_regions: DeletedRegions::new(), + }, + }), Some(get_worker_metadata_response::Result::Failure(WorkerExecutionError { error: Some(worker_execution_error::Error::WorkerNotFound(_)), })) => None, @@ -499,6 +522,66 @@ impl TestWorkerExecutor { rx } + pub async fn capture_output_forever( + &self, + worker_id: &WorkerId, + ) -> ( + UnboundedReceiver>, + tokio::sync::oneshot::Sender<()>, + ) { + let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); + let mut cloned_client = self.client.clone(); + let worker_id = worker_id.clone(); + let (abort_tx, mut abort_rx) = tokio::sync::oneshot::channel(); + tokio::spawn(async move { + let mut abort = false; + while !abort { + let mut response = cloned_client + .connect_worker(ConnectWorkerRequest { + worker_id: Some(worker_id.clone().into()), + account_id: Some( + AccountId { + value: "test-account".to_string(), + } + .into(), + ), + account_limits: None, + }) + .await + .expect("Failed to connect worker") + .into_inner(); + + loop { + select! { + msg = response.message() => { + match msg { + Ok(Some(event)) => { + debug!("Received event: {:?}", event); + tx.send(Some(event)).expect("Failed to send event"); + } + Ok(None) => { + break; + } + Err(e) => { + panic!("Failed to get message: {:?}", e); + } + } + } + _ = (&mut abort_rx) => { + abort = true; + break; + } + } + } + } + + tx.send(None).expect("Failed to send event"); + debug!("Finished receiving events"); + }); + + (rx, abort_tx) + } + pub async fn capture_output_with_termination( &self, worker_id: &WorkerId, @@ -757,6 +840,17 @@ pub fn stdout_event(s: &str) -> LogEvent { } } +pub fn stdout_event_starting_with(event: &LogEvent, s: &str) -> bool { + if let LogEvent { + event: Some(log_event::Event::Stdout(StdOutLog { message })), + } = event + { + message.starts_with(s) + } else { + false + } +} + pub fn stderr_event(s: &str) -> LogEvent { LogEvent { event: Some(log_event::Event::Stderr(StdErrLog { @@ -966,8 +1060,8 @@ impl FuelManagement for TestWorkerCtx { fn borrow_fuel_sync(&mut self) {} - async fn return_fuel(&mut self, current_level: i64) -> Result { - Ok(current_level) + async fn return_fuel(&mut self, _current_level: i64) -> Result { + Ok(0) } } @@ -979,14 +1073,14 @@ impl ExternalOperations for TestWorkerCtx { this: &T, worker_id: &WorkerId, status: WorkerStatus, - ) { + ) -> Result<(), GolemError> { DurableWorkerCtx::::set_worker_status(this, worker_id, status).await } async fn get_worker_retry_count + Send + Sync>( this: &T, worker_id: &WorkerId, - ) -> u32 { + ) -> u64 { DurableWorkerCtx::::get_worker_retry_count(this, worker_id).await } diff --git a/golem-worker-executor-base/tests/lib.rs b/golem-worker-executor-base/tests/lib.rs index 20c1b80812..50d44d1364 100644 --- a/golem-worker-executor-base/tests/lib.rs +++ b/golem-worker-executor-base/tests/lib.rs @@ -20,6 +20,7 @@ pub mod guest_languages; pub mod keyvalue; pub mod rpc; pub mod scalability; +pub mod transactions; pub mod wasi; #[allow(dead_code)] diff --git a/golem-worker-executor-base/tests/transactions.rs b/golem-worker-executor-base/tests/transactions.rs new file mode 100644 index 0000000000..b2858e3f81 --- /dev/null +++ b/golem-worker-executor-base/tests/transactions.rs @@ -0,0 +1,95 @@ +use crate::common; +use assert2::check; +use http_02::{Response, StatusCode}; +use std::collections::HashMap; +use std::net::SocketAddr; +use std::path::Path; +use std::sync::{Arc, Mutex}; +use tonic::transport::Body; +use warp::Filter; + +#[tokio::test] +async fn jump() { + let context = common::TestContext::new(); + let mut executor = common::start(&context).await.unwrap(); + + let host_http_port = context.host_http_port(); + + let http_server = tokio::spawn(async move { + let call_count_per_step = Arc::new(Mutex::new(HashMap::::new())); + let route = warp::path("step") + .and(warp::path::param()) + .and(warp::get()) + .map(move |step: u64| { + let mut steps = call_count_per_step.lock().unwrap(); + let step_count = steps.entry(step).and_modify(|e| *e += 1).or_insert(0); + + println!("step: {step} occurrence {step_count}"); + + match &step_count { + 0 => Response::builder() + .status(StatusCode::OK) + .body(Body::from("true")) + .unwrap(), + _ => Response::builder() + .status(StatusCode::OK) + .body(Body::from("false")) + .unwrap(), + } + }); + + warp::serve(route) + .run( + format!("0.0.0.0:{}", host_http_port) + .parse::() + .unwrap(), + ) + .await; + }); + + let template_id = executor.store_template(Path::new("../test-templates/runtime-service.wasm")); + + let mut env = HashMap::new(); + env.insert("PORT".to_string(), context.host_http_port().to_string()); + + let worker_id = executor + .try_start_worker_versioned(&template_id, 0, "runtime-service-jump", vec![], env) + .await + .unwrap(); + + let (rx, abort_capture) = executor.capture_output_forever(&worker_id).await; + + let result = executor + .invoke_and_await(&worker_id, "golem:it/api/jump", vec![]) + .await + .unwrap(); + + drop(executor); + http_server.abort(); + + abort_capture.send(()).unwrap(); + let mut events = common::drain_connection(rx).await; + events.retain(|e| match e { + Some(e) => { + !common::stdout_event_starting_with(e, "Sending") + && !common::stdout_event_starting_with(e, "Received") + } + None => false, + }); + + println!("events: {:?}", events); + + check!(result == vec![common::val_u64(5)]); + check!( + events + == vec![ + Some(common::stdout_event("started: 0\n")), + Some(common::stdout_event("second: 2\n")), + Some(common::stdout_event("second: 2\n")), + Some(common::stdout_event("third: 3\n")), + Some(common::stdout_event("fourth: 4\n")), + Some(common::stdout_event("fourth: 4\n")), + Some(common::stdout_event("fifth: 5\n")), + ] + ); +} diff --git a/golem-worker-executor/src/context.rs b/golem-worker-executor/src/context.rs index fc9a29bfcc..a8aabbe348 100644 --- a/golem-worker-executor/src/context.rs +++ b/golem-worker-executor/src/context.rs @@ -77,8 +77,8 @@ impl FuelManagement for Context { fn borrow_fuel_sync(&mut self) {} - async fn return_fuel(&mut self, current_level: i64) -> Result { - Ok(current_level) + async fn return_fuel(&mut self, _current_level: i64) -> Result { + Ok(0) } } @@ -90,14 +90,14 @@ impl ExternalOperations for Context { this: &T, worker_id: &WorkerId, status: WorkerStatus, - ) { + ) -> Result<(), GolemError> { DurableWorkerCtx::::set_worker_status(this, worker_id, status).await } async fn get_worker_retry_count + Send + Sync>( this: &T, worker_id: &WorkerId, - ) -> u32 { + ) -> u64 { DurableWorkerCtx::::get_worker_retry_count(this, worker_id).await } diff --git a/golem-worker-service-base/src/tokeniser/cursor.rs b/golem-worker-service-base/src/tokeniser/cursor.rs index d9030b8293..8e769e235d 100644 --- a/golem-worker-service-base/src/tokeniser/cursor.rs +++ b/golem-worker-service-base/src/tokeniser/cursor.rs @@ -185,7 +185,6 @@ impl TokenCursor { #[cfg(test)] mod tests { use super::*; - use crate::tokeniser::tokenizer::Tokenizer; #[test] fn capture_string_test() { diff --git a/golem-worker-service/src/service/worker.rs b/golem-worker-service/src/service/worker.rs index de90aeadb8..4b3ad5c1e0 100644 --- a/golem-worker-service/src/service/worker.rs +++ b/golem-worker-service/src/service/worker.rs @@ -174,7 +174,7 @@ pub trait WorkerService { async fn complete_promise( &self, worker_id: &WorkerId, - oplog_id: i32, + oplog_id: u64, data: Vec, ) -> Result; @@ -766,7 +766,7 @@ impl WorkerService for WorkerServiceDefault { async fn complete_promise( &self, worker_id: &WorkerId, - oplog_id: i32, + oplog_id: u64, data: Vec, ) -> Result { let promise_id = PromiseId { @@ -1024,7 +1024,7 @@ impl WorkerService for WorkerServiceNoOp { async fn complete_promise( &self, _worker_id: &WorkerId, - _oplog_id: i32, + _oplog_id: u64, _data: Vec, ) -> Result { Ok(true) diff --git a/openapi/golem-service.yaml b/openapi/golem-service.yaml index a2adb257f3..ac455981dd 100644 --- a/openapi/golem-service.yaml +++ b/openapi/golem-service.yaml @@ -1352,7 +1352,7 @@ components: properties: oplogIdx: type: integer - format: int32 + format: uint64 data: type: array items: @@ -1885,7 +1885,7 @@ components: $ref: '#/components/schemas/WorkerId' oplogIdx: type: integer - format: int32 + format: uint64 required: - workerId - oplogIdx diff --git a/test-templates/http-client/wit/deps/golem/golem-host.wit b/test-templates/http-client/wit/deps/golem/golem-host.wit index a26997abe7..b5c3d4668b 100644 --- a/test-templates/http-client/wit/deps/golem/golem-host.wit +++ b/test-templates/http-client/wit/deps/golem/golem-host.wit @@ -1,46 +1,63 @@ -package golem:api; +package golem:api@0.2.0; +/// The Golem host API provides low level access to Golem specific features such as promises and control over +/// the durability and transactional guarantees the executor provides. interface host { + use golem:rpc/types@0.1.0.{uri}; - record promise-id { - worker-id: worker-id, - oplog-idx: s32, - } + /// An index into the persistent log storing all performed operations of a worker + type oplog-index = u64; - record worker-id { - template-id: template-id, - worker-name: string - } + /// A promise ID is a value that can be passed to an external Golem API to complete that promise + /// from an arbitrary external source, while Golem workers can await for this completion. + record promise-id { + worker-id: worker-id, + oplog-idx: oplog-index, + } - - record template-id { - uuid: uuid, - } + /// Represents a Golem worker + record worker-id { + template-id: template-id, + worker-name: string + } - record uuid { - high-bits: u64, - low-bits: u64 - } - - record account-id { - account-name: string - } - record uri { - uri: string - } + /// Represents a Golem template + record template-id { + uuid: uuid, + } - golem-create-promise: func() -> promise-id; + /// UUID + record uuid { + high-bits: u64, + low-bits: u64 + } - golem-await-promise: func(promise-id: promise-id) -> list; + /// Create a new promise + golem-create-promise: func() -> promise-id; - golem-complete-promise: func(promise-id: promise-id, data: list) -> bool; + /// Suspends execution until the given promise gets completed, and returns the payload passed to + /// the promise completion. + golem-await-promise: func(promise-id: promise-id) -> list; - golem-delete-promise: func(promise-id: promise-id) -> (); + /// Completes the given promise with the given payload. Returns true if the promise was completed, false + /// if the promise was already completed. The payload is passed to the worker that is awaiting the promise. + golem-complete-promise: func(promise-id: promise-id, data: list) -> bool; - get-self-uri: func(function-name: string) -> uri; + /// Deletes the given promise + golem-delete-promise: func(promise-id: promise-id) -> (); + + /// Returns a Golem worker URI that can be used to invoke a given function on the current worker + get-self-uri: func(function-name: string) -> uri; + + /// Returns the current position in the persistent op log + get-oplog-index: func() -> oplog-index; + + /// Makes the current worker travel back in time and continue execution from the given position in the persistent + /// op log. + set-oplog-index: func(oplog-idx: oplog-index) -> (); } world golem-host { - import host; + import host; } \ No newline at end of file diff --git a/test-templates/promise.wasm b/test-templates/promise.wasm index 0eafb8041d4343fbaf3ce67836e3ffb4d5828f2c..4ecc66786e7ccc2d8c0da43b1745e5df7034ce1a 100755 GIT binary patch delta 376 zcmeyGzqWvnA+b1@mw}Oi{Ualz6aPfMOs8@d2JZZVocwg%%)FG;3T6g2#v&%p^8BLg z)FR!?6jn~CWJ(1)3jIiF5zusT zQS371jJKFHnKuVBbsI5Gnta~`WYRa2GNu;B$+@P|p&3jJMnFGh7NsVa=wh=UBB+~O tl$uzQstffRqaj{BlP{X;0Im6F+QZ_-#K;74-Q=ZalGt6i`K*}+BLG-raC!g$ delta 374 zcmZ2m@HL;0A+b1@mw}Oi{T?Hu6YoU6O#LDz&hq@C?9?LN%oJA6{DPePbResuiiLrz zpeR2#vp5yVWoBSwbYNg$XJMFJz$hBS$iY}p%jm#}q=KD+lZ8PzJwGQkS2wXdF|$M$ zs+*CEOPG<74=iJqSdgiokzZWG%D{Lh9pn~91_lO36V3$2dWHnHy1M%M`pE{2nu0z| zXc~aliu0q3&0)O7q`|bgf~ng`qLm4593K<1anhz`78NXciMgo^!b0UhcO~cN7Ubup z=9O3#XJqCw#xODHWag!07NsVa=%Tt(cXA=4h$N#n4(Z9vW;%>O_nP%Ex=h|{W{mE> J&8+4ci~#EzZ)N}h diff --git a/test-templates/promise/cargo.toml b/test-templates/promise/cargo.toml index 5852a08d7c..717e4e5eec 100644 --- a/test-templates/promise/cargo.toml +++ b/test-templates/promise/cargo.toml @@ -22,3 +22,4 @@ path = "wit" [package.metadata.component.target.dependencies] "golem:api" = { path = "wit/deps/golem" } +"golem:rpc" = { path = "wit/deps/wasm-rpc" } \ No newline at end of file diff --git a/test-templates/promise/wit/deps/golem/golem-host.wit b/test-templates/promise/wit/deps/golem/golem-host.wit index a26997abe7..b5c3d4668b 100644 --- a/test-templates/promise/wit/deps/golem/golem-host.wit +++ b/test-templates/promise/wit/deps/golem/golem-host.wit @@ -1,46 +1,63 @@ -package golem:api; +package golem:api@0.2.0; +/// The Golem host API provides low level access to Golem specific features such as promises and control over +/// the durability and transactional guarantees the executor provides. interface host { + use golem:rpc/types@0.1.0.{uri}; - record promise-id { - worker-id: worker-id, - oplog-idx: s32, - } + /// An index into the persistent log storing all performed operations of a worker + type oplog-index = u64; - record worker-id { - template-id: template-id, - worker-name: string - } + /// A promise ID is a value that can be passed to an external Golem API to complete that promise + /// from an arbitrary external source, while Golem workers can await for this completion. + record promise-id { + worker-id: worker-id, + oplog-idx: oplog-index, + } - - record template-id { - uuid: uuid, - } + /// Represents a Golem worker + record worker-id { + template-id: template-id, + worker-name: string + } - record uuid { - high-bits: u64, - low-bits: u64 - } - - record account-id { - account-name: string - } - record uri { - uri: string - } + /// Represents a Golem template + record template-id { + uuid: uuid, + } - golem-create-promise: func() -> promise-id; + /// UUID + record uuid { + high-bits: u64, + low-bits: u64 + } - golem-await-promise: func(promise-id: promise-id) -> list; + /// Create a new promise + golem-create-promise: func() -> promise-id; - golem-complete-promise: func(promise-id: promise-id, data: list) -> bool; + /// Suspends execution until the given promise gets completed, and returns the payload passed to + /// the promise completion. + golem-await-promise: func(promise-id: promise-id) -> list; - golem-delete-promise: func(promise-id: promise-id) -> (); + /// Completes the given promise with the given payload. Returns true if the promise was completed, false + /// if the promise was already completed. The payload is passed to the worker that is awaiting the promise. + golem-complete-promise: func(promise-id: promise-id, data: list) -> bool; - get-self-uri: func(function-name: string) -> uri; + /// Deletes the given promise + golem-delete-promise: func(promise-id: promise-id) -> (); + + /// Returns a Golem worker URI that can be used to invoke a given function on the current worker + get-self-uri: func(function-name: string) -> uri; + + /// Returns the current position in the persistent op log + get-oplog-index: func() -> oplog-index; + + /// Makes the current worker travel back in time and continue execution from the given position in the persistent + /// op log. + set-oplog-index: func(oplog-idx: oplog-index) -> (); } world golem-host { - import host; + import host; } \ No newline at end of file diff --git a/test-templates/promise/wit/deps/wasm-rpc/wasm-rpc.wit b/test-templates/promise/wit/deps/wasm-rpc/wasm-rpc.wit new file mode 100644 index 0000000000..f7deff5bf3 --- /dev/null +++ b/test-templates/promise/wit/deps/wasm-rpc/wasm-rpc.wit @@ -0,0 +1,54 @@ +package golem:rpc@0.1.0; + +interface types { + type node-index = s32; + + record wit-value { + nodes: list, + } + + variant wit-node { + record-value(list), + variant-value(tuple>), + enum-value(u32), + flags-value(list), + tuple-value(list), + list-value(list), + option-value(option), + result-value(result, option>), + prim-u8(u8), + prim-u16(u16), + prim-u32(u32), + prim-u64(u64), + prim-s8(s8), + prim-s16(s16), + prim-s32(s32), + prim-s64(s64), + prim-float32(float32), + prim-float64(float64), + prim-char(char), + prim-bool(bool), + prim-string(string), + } + + record uri { + value: string, + } + + variant rpc-error { + protocol-error(string), + denied(string), + not-found(string), + remote-internal-error(string) + } + + resource wasm-rpc { + constructor(location: uri); + + invoke-and-await: func(function-name: string, function-params: list) -> result; + } +} + +world wit-value { + import types; +} diff --git a/test-templates/promise/wit/promise.wit b/test-templates/promise/wit/promise.wit index 047e9a760f..5b4358fff8 100644 --- a/test-templates/promise/wit/promise.wit +++ b/test-templates/promise/wit/promise.wit @@ -1,6 +1,6 @@ package golem:it; world promise { - import golem:api/host; + import golem:api/host@0.2.0; export run: func() -> list; } diff --git a/test-templates/runtime-service.wasm b/test-templates/runtime-service.wasm index 2a033f6b889cd3aa484384c40a8cef598fde123e..593b27ea86aa5a493fe1e912f544d22831c4ed3a 100755 GIT binary patch literal 488642 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%0De99f8Tqz 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

Z4JruI6rTc`pOt=qCK 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 delta 4680 zcmbtYZH!b`89wK{cjoTwo!OoJ;A>gn%-t<4AG-@(I#8%|F9;MGT0c9DU?7*^L zQ)!KGM+*vq1*Gw4B(^3dG>C~wsZ9+r8_SOxF%m5X`@@)Mj3gvB#vepY@p;d=vkXf= zObh|eJ?Fgdc|V@#Id|?aZp=A5d}?EJQLgnADJeZcPmc|f5T}PaV^!ZGWy9{_eFH znZ@INXPcnx&K*w;J~=k9W8c2vog!U-ZlFnt;J7sXb7X6*`XkXTj#VZqA}8`+sZ=T= z5|LcxrUEUr)GDeg<*`x`7-madN)$+|E>&0XRKJ$%b3%*!Fw$yBzS#nnBJ$3(_2kmd)T}-zyBnToH;p(q|8d?Nq4N=MahJc!>XQ znw>w*dkdIzhik=ln)1i(yccLM_$bcdKUyM4TAx##?NJV)4Q^Eauyc`>Nv5zq;-&(v zazcneXH-zn2_CJOQih8057|1zBA2d9{pC4+q#W{H8?R9B@FRwm3cH>VE7afIjFzZk zG%^}pKY#6fYCJ@3tSPE3it3iz#KSjv7(|uIWjLxF#>1wZjF6|Birw7a=nt5OZNY;F zyRE3MBwmuovmB{w!%y5Wii_$(GORgZZ&6)kQ|i}V^d_&DFt}s~94JbM=Zp3^4pThg zMH6mc@^rOob=g_j=@cV?_g=5AUU935&&2jEx0>wLrO=BiYGaOz!0AWNR8wvojRe*X zPnbeLt$tD<^H4yuy8g)t6xGY@%c1Z)$xs!Q?U^QPdN825bfPk0z8}!)ZkJT(VbSFa zbcY0Nhdv^JqjYpgrw)u36`Q29w4PqT;IS+fdlTCf61-#Uv8}jcO9w{7w6lICOOG`= zqk_-ac?q8KInp+qz8tMyh8Y_^DuZJxBAWxHy3{EihxJT>dc;(}cXUsr%F(5-PM8;S zbcoPtqZ{ZjVWToskGCe&+hOOC^^ zJX%^*RR=5-prSe5Of3XrnRCswbk->rhfqZEhFn@_3TfvS6gTfQ)9R)>=W&)e%{bmI(5ZmVMDO0decOK&jnCxm z;RO^BBlGE2TDsBZqtjqakx#22O@I+cPw)fsLvOHTpU^w^hu58mK@dg6x&6A8dMz$) zx6-s2XtGkyCDFjH)dmL#Y_7m*t&YH(ZEaCiMFz0B&ijai`4BmI4>ef}tN&9@%(ZFs zh<<-b0A5i6^O5PGGlTiabP7K=WjiQXRS+bUD2P_2XeHnc;8X3z^ySZ}QSmP-{h$+pmO$VdK?Ig}+nB+a`l4V|d?2`Qbq zrD|f1u~|Hm9;b^K9GpqB^Uy4`>yXY=1?=US^m;F}0SeD5$2tXVN7NuY-!gob6`QK+ zv7nrqMK3LdPZ$-5F~qy9>o65bL`z>Rhu)|y0K^cXvsP|zqtW}_QH7MVv7W&mT;Js| z0|TAXNC&5)R2kUuX*8Su5l`s_FkJ1$q?%{&P7#TP>Me%a3M7!>CkxOOstztQ5UrwH z#?yP_xC&Kl?u5cw#3CY7Zl_0Dl9augl+AD2sm;pu&2}1Xx+guee-3UJPUGYpy3t~T zW`(s>w6rtF=Tdt^H5-78f%xiNTmn!YbA2w&v66jjE_GTz^XAbT)#BGi0vY1slPx|~ zi_hB2#c$R$YW;joQ-}3)LDTQ;%#i|xcIJG6Chob8o(+@h=xj*K8>-h4_`=}&V@Pw= zH!9}ckT$nF+!dh^C@RAIU;(w7zWZpQyMP=oWJ1zfS^?$gu%ngK03Oq7 zGRg|zPrN<3Y~9f2+{nzs+Fi`U2}wbCfkO!ZTzdpp=dbrszop*7`8Cv=e0SJ7pVp*o z(ahgFXuA3FeA@j1>8@Kq&om{pM_HMpe8`mr)K`UrssScnbAW@ea1ag-o)!rldb?<3 zc>>l+5ZMZcX;`Up$OzIXjbme4GmyCIzw4r(bzQK%h)bc2Vl8JU?~p-oqfQ3+1p(<0 zTJj5WVG*@j9IsqNAGg=siAA(cpWs_l80J(DDUVtG!4QwHOfiG{JEE6``S0Kl-AZ#1z5W0 z29oG*wdUw%wdOSx_#mnvi@T_T6YiyoJAzTXY#H_6Ef4rPnG^&~WoP#kT zj{VQIc>eyo>Eu9SX7o{CRp)E3HnXiS(fKd+(MVP2J=M>lF)#kz=XCzH_T?m{#k_ui z3JN4x_W)f*_-0y>w)I+&;7tH`Q814sQbhSj6S@FC_7|(nf0LmUctV)e3VLt`ZUTTI z=EW#qZVd7#d0o8ri3jNhnTPBBO%Gp`lOG#=={`2#JB3I-3ix>?mkLqWIXE;jJXRi; zqP~%T0i&^aF&9n33~lxM;&tBs9YX`6rTM^MxqIg@_U<3pUtTr7XK+X^kfL*N|E|HY zft}^lNlKs-u1LOu+?8^8b0qAHcOGl zs*tc#^OclSK7e3l%J-ILnO@}yB~^N8U}$*kS?o~uONY6(&tFs!M8cCo&BTtHDj+Ha zBhgIe^teC0F1=B);jA+!JK6{X{${c;OP)1OdE^b6W8?lB^R01zn)w(0@nvcr$7y~v h?zhd5K{JPHKLibyd+{wO1%ID3QN6#&e7Ec`{4e6`^Fjas diff --git a/test-templates/runtime-service/Cargo.lock b/test-templates/runtime-service/Cargo.lock index 42302c9794..385d96087f 100644 --- a/test-templates/runtime-service/Cargo.lock +++ b/test-templates/runtime-service/Cargo.lock @@ -2,18 +2,206 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "anyhow" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -25,24 +213,352 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "h2" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fa0ae458eb99874f54c09f4f9174f8b45fb87e854536a4e608696247f0c23" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "libc" version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.4.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" version = "0.8.5" @@ -74,12 +590,367 @@ dependencies = [ ] [[package]] -name = "runtime-service" -version = "0.0.1" +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "once_cell", - "rand", - "wit-bindgen", + "bitflags 1.3.2", +] + +[[package]] +name = "reqwest" +version = "0.11.18" +source = "git+https://github.com/zivergetech/reqwest?branch=update-feb-2024#77ca01d96ca6ec93d961f8a9f73b631d00267efc" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", + "wit-bindgen", +] + +[[package]] +name = "runtime-service" +version = "0.0.1" +dependencies = [ + "once_cell", + "rand", + "reqwest", + "wit-bindgen", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustix" +version = "0.38.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "spdx" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ef1a0fa1e39ac22972c8db23ff89aea700ab96aa87114e1fb55937a631a0c9" +dependencies = [ + "smallvec", +] + +[[package]] +name = "syn" +version = "2.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", ] [[package]] @@ -88,11 +959,340 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "wasm-encoder" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-metadata" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d835d67708f6374937c550ad8dd1d17c616ae009e3f00d7a0ac9f7825e78c36a" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.118.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c" +dependencies = [ + "indexmap", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wit-bindgen" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b76f1d099678b4f69402a421e888bbe71bf20320c2f3f3565d0e7484dbe5bc20" dependencies = [ - "bitflags", + "bitflags 2.4.0", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75d55e1a488af2981fb0edac80d8d20a51ac36897a1bdef4abde33c29c1b6d0d" +dependencies = [ + "anyhow", + "wit-component", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01ff9cae7bf5736750d94d91eb8a49f5e3a04aff1d1a3218287d9b2964510f8" +dependencies = [ + "anyhow", + "heck", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804a98e2538393d47aa7da65a7348116d6ff403b426665152b70a168c0146d49" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", + "wit-component", +] + +[[package]] +name = "wit-component" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a35a2a9992898c9d27f1664001860595a4bc99d32dd3599d547412e17d7e2" +dependencies = [ + "anyhow", + "bitflags 2.4.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "316b36a9f0005f5aa4b03c39bc3728d045df136f8c13a73b7db4510dec725e08" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", ] diff --git a/test-templates/runtime-service/cargo.toml b/test-templates/runtime-service/cargo.toml index ba3b6e1b51..2bb9b3d9cb 100644 --- a/test-templates/runtime-service/cargo.toml +++ b/test-templates/runtime-service/cargo.toml @@ -15,6 +15,7 @@ strip = true [dependencies] once_cell = "1.17.1" rand = "0.8.5" +reqwest = { git = "https://github.com/zivergetech/reqwest", branch = "update-feb-2024", features = ["json"] } wit-bindgen = { version = "0.16.0", default-features = false, features = ["realloc"] } [package.metadata.component.target] diff --git a/test-templates/runtime-service/src/lib.rs b/test-templates/runtime-service/src/lib.rs index 094376e690..6d7336a37b 100644 --- a/test-templates/runtime-service/src/lib.rs +++ b/test-templates/runtime-service/src/lib.rs @@ -1,5 +1,6 @@ mod bindings; +use reqwest::{Client, Response}; use crate::bindings::exports::golem::it::api::Guest; use crate::bindings::golem::api::host::*; @@ -9,4 +10,66 @@ impl Guest for Component { fn get_self_uri(function_name: String) -> String { get_self_uri(&function_name).value } + + fn jump() -> u64 { + let mut state = 0; + + println!("started: {state}"); // 'started 1' + state += 1; + + let state1 = get_oplog_index(); + + state += 1; + println!("second: {state}"); // 'second 2' + + if remote_call(state) { + set_oplog_index(state1); // we resume from state 1, so we emit 'second 2' again but not 'started 1' + } + + state += 1; + println!("third: {state}"); // 'third 3' + + let state2 = get_oplog_index(); + + state += 1; + println!("fourth: {state}"); // 'fourth 4' + + if remote_call(state) { + set_oplog_index(state2); // we resume from state 2, so emit 'fourth 4' again but not the rest + } + + state += 1; + println!("fifth: {state}"); // 'fifth 5' + + // Expected final output: + // started 1 + // second 2 + // second 2 + // third 3 + // fourth 4 + // fourth 4 + // fifth 5 + + state // final value is 5 + } } + +fn remote_call(param: u64) -> bool { + let port = std::env::var("PORT").unwrap_or("9999".to_string()); + + let client = Client::builder().build().unwrap(); + + let url = format!("http://localhost:{port}/step/{param}"); + + println!("Sending GET {url}"); + + let response: Response = client.get(&url) + .send() + .expect("Request failed"); + + let status = response.status(); + let body = response.json::().expect("Invalid response"); + + println!("Received {status} {body}"); + body +} \ No newline at end of file diff --git a/test-templates/runtime-service/wit/deps/golem/golem-host.wit b/test-templates/runtime-service/wit/deps/golem/golem-host.wit index bf70bcebcc..b5c3d4668b 100644 --- a/test-templates/runtime-service/wit/deps/golem/golem-host.wit +++ b/test-templates/runtime-service/wit/deps/golem/golem-host.wit @@ -1,43 +1,63 @@ -package golem:api; +package golem:api@0.2.0; +/// The Golem host API provides low level access to Golem specific features such as promises and control over +/// the durability and transactional guarantees the executor provides. interface host { - use golem:rpc/types@0.1.0.{uri}; + use golem:rpc/types@0.1.0.{uri}; - record promise-id { - worker-id: worker-id, - oplog-idx: s32, - } + /// An index into the persistent log storing all performed operations of a worker + type oplog-index = u64; - record worker-id { - template-id: template-id, - worker-name: string - } + /// A promise ID is a value that can be passed to an external Golem API to complete that promise + /// from an arbitrary external source, while Golem workers can await for this completion. + record promise-id { + worker-id: worker-id, + oplog-idx: oplog-index, + } - - record template-id { - uuid: uuid, - } + /// Represents a Golem worker + record worker-id { + template-id: template-id, + worker-name: string + } - record uuid { - high-bits: u64, - low-bits: u64 - } - - record account-id { - account-name: string - } - golem-create-promise: func() -> promise-id; + /// Represents a Golem template + record template-id { + uuid: uuid, + } - golem-await-promise: func(promise-id: promise-id) -> list; + /// UUID + record uuid { + high-bits: u64, + low-bits: u64 + } - golem-complete-promise: func(promise-id: promise-id, data: list) -> bool; + /// Create a new promise + golem-create-promise: func() -> promise-id; - golem-delete-promise: func(promise-id: promise-id) -> (); + /// Suspends execution until the given promise gets completed, and returns the payload passed to + /// the promise completion. + golem-await-promise: func(promise-id: promise-id) -> list; - get-self-uri: func(function-name: string) -> uri; + /// Completes the given promise with the given payload. Returns true if the promise was completed, false + /// if the promise was already completed. The payload is passed to the worker that is awaiting the promise. + golem-complete-promise: func(promise-id: promise-id, data: list) -> bool; + + /// Deletes the given promise + golem-delete-promise: func(promise-id: promise-id) -> (); + + /// Returns a Golem worker URI that can be used to invoke a given function on the current worker + get-self-uri: func(function-name: string) -> uri; + + /// Returns the current position in the persistent op log + get-oplog-index: func() -> oplog-index; + + /// Makes the current worker travel back in time and continue execution from the given position in the persistent + /// op log. + set-oplog-index: func(oplog-idx: oplog-index) -> (); } world golem-host { - import host; + import host; } \ No newline at end of file diff --git a/test-templates/runtime-service/wit/runtime.wit b/test-templates/runtime-service/wit/runtime.wit index 7ab5078b55..ba5af09e8a 100644 --- a/test-templates/runtime-service/wit/runtime.wit +++ b/test-templates/runtime-service/wit/runtime.wit @@ -2,9 +2,10 @@ package golem:it; interface api { get-self-uri: func(function-name: string) -> string; + jump: func() -> u64; } world runtime-service { - import golem:api/host; + import golem:api/host@0.2.0; export api; } \ No newline at end of file