From 376c1c7c80f6b8533d9bcb9d2d1844c3bf1576b5 Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Mon, 13 Jan 2025 11:56:19 +0100 Subject: [PATCH] Defined the DurabilityHost interface and migrated Durability to it (#1236) * Defined the DurabilityHost interface and migrated Durability to it * Updated OpenAPI spec --- golem-common/src/model/oplog.rs | 14 +- golem-common/src/model/public_oplog.rs | 78 ++-- .../src/durable_host/blobstore/container.rs | 49 ++- .../src/durable_host/blobstore/mod.rs | 26 +- .../src/durable_host/blobstore/types.rs | 17 +- .../src/durable_host/cli/environment.rs | 14 +- .../src/durable_host/cli/exit.rs | 7 +- .../src/durable_host/cli/stderr.rs | 5 +- .../src/durable_host/cli/stdin.rs | 5 +- .../src/durable_host/cli/stdout.rs | 5 +- .../src/durable_host/cli/terminal_input.rs | 5 +- .../src/durable_host/cli/terminal_output.rs | 5 +- .../src/durable_host/cli/terminal_stderr.rs | 5 +- .../src/durable_host/cli/terminal_stdin.rs | 5 +- .../src/durable_host/cli/terminal_stdout.rs | 5 +- .../durable_host/clocks/monotonic_clock.rs | 19 +- .../src/durable_host/clocks/wall_clock.rs | 10 +- .../src/durable_host/durability.rs | 390 +++++++++++++----- .../src/durable_host/filesystem/preopens.rs | 6 +- .../src/durable_host/filesystem/types.rs | 69 ++-- .../src/durable_host/golem/mod.rs | 61 ++- .../src/durable_host/golem/v11.rs | 15 +- .../src/durable_host/http/mod.rs | 12 +- .../src/durable_host/http/outgoing_http.rs | 22 +- .../src/durable_host/http/types.rs | 140 +++---- .../src/durable_host/io/error.rs | 7 +- .../src/durable_host/io/poll.rs | 15 +- .../src/durable_host/io/streams.rs | 53 ++- .../src/durable_host/keyvalue/atomic.rs | 7 +- .../src/durable_host/keyvalue/caching.rs | 41 +- .../src/durable_host/keyvalue/error.rs | 7 +- .../src/durable_host/keyvalue/eventual.rs | 18 +- .../durable_host/keyvalue/eventual_batch.rs | 18 +- .../src/durable_host/keyvalue/types.rs | 23 +- .../src/durable_host/logging/logging.rs | 5 +- .../src/durable_host/mod.rs | 32 +- .../src/durable_host/random/insecure.rs | 10 +- .../src/durable_host/random/insecure_seed.rs | 6 +- .../src/durable_host/random/random.rs | 10 +- .../durable_host/sockets/instance_network.rs | 5 +- .../durable_host/sockets/ip_name_lookup.rs | 15 +- .../src/durable_host/sockets/network.rs | 9 +- .../src/durable_host/sockets/tcp.rs | 61 ++- .../durable_host/sockets/tcp_create_socket.rs | 5 +- .../src/durable_host/sockets/udp.rs | 45 +- .../durable_host/sockets/udp_create_socket.rs | 5 +- .../src/durable_host/wasm_rpc/mod.rs | 47 ++- golem-worker-executor-base/src/model/mod.rs | 2 +- .../src/model/public_oplog/wit.rs | 16 +- .../src/services/oplog/mod.rs | 26 +- .../src/services/oplog/tests.rs | 6 +- .../tests/compatibility/v1.rs | 19 +- .../tests/compatibility/v1_1.rs | 4 +- openapi/golem-service.yaml | 82 ++-- 54 files changed, 877 insertions(+), 711 deletions(-) diff --git a/golem-common/src/model/oplog.rs b/golem-common/src/model/oplog.rs index f563afec10..e95d446f55 100644 --- a/golem-common/src/model/oplog.rs +++ b/golem-common/src/model/oplog.rs @@ -316,7 +316,7 @@ pub enum OplogEntry { timestamp: Timestamp, function_name: String, response: OplogPayload, - wrapped_function_type: WrappedFunctionType, + wrapped_function_type: DurableFunctionType, // TODO: rename in Golem 2.0 }, /// The worker has been invoked ExportedFunctionInvoked { @@ -433,7 +433,7 @@ pub enum OplogEntry { function_name: String, request: OplogPayload, response: OplogPayload, - wrapped_function_type: WrappedFunctionType, + wrapped_function_type: DurableFunctionType, // TODO: rename in Golem 2.0 }, /// The current version of the Create entry (previous is CreateV1) Create { @@ -676,14 +676,14 @@ impl OplogEntry { wrapped_function_type, .. } => match wrapped_function_type { - WrappedFunctionType::WriteRemoteBatched(Some(begin_index)) + DurableFunctionType::WriteRemoteBatched(Some(begin_index)) if *begin_index == idx => { true } - WrappedFunctionType::ReadLocal => true, - WrappedFunctionType::WriteLocal => true, - WrappedFunctionType::ReadRemote => true, + DurableFunctionType::ReadLocal => true, + DurableFunctionType::WriteLocal => true, + DurableFunctionType::ReadRemote => true, _ => false, }, OplogEntry::ExportedFunctionCompleted { .. } => false, @@ -857,7 +857,7 @@ pub enum OplogPayload { } #[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)] -pub enum WrappedFunctionType { +pub enum DurableFunctionType { /// The side-effect reads from the worker's local state (for example local file system, /// random generator, etc.) ReadLocal, diff --git a/golem-common/src/model/public_oplog.rs b/golem-common/src/model/public_oplog.rs index fc9d718698..77ca4deb21 100644 --- a/golem-common/src/model/public_oplog.rs +++ b/golem-common/src/model/public_oplog.rs @@ -13,7 +13,7 @@ // limitations under the License. use crate::model::lucene::{LeafQuery, Query}; -use crate::model::oplog::{LogLevel, OplogIndex, WorkerResourceId, WrappedFunctionType}; +use crate::model::oplog::{DurableFunctionType, LogLevel, OplogIndex, WorkerResourceId}; use crate::model::plugin::PluginInstallation; use crate::model::regions::OplogRegion; use crate::model::RetryConfig; @@ -78,7 +78,7 @@ pub struct WriteRemoteBatchedParameters { #[cfg_attr(feature = "poem", derive(poem_openapi::Union))] #[cfg_attr(feature = "poem", oai(discriminator_name = "type", one_of = true))] #[serde(tag = "type")] -pub enum PublicWrappedFunctionType { +pub enum PublicDurableFunctionType { /// The side-effect reads from the worker's local state (for example local file system, /// random generator, etc.) ReadLocal(Empty), @@ -98,15 +98,15 @@ pub enum PublicWrappedFunctionType { WriteRemoteBatched(WriteRemoteBatchedParameters), } -impl From for PublicWrappedFunctionType { - fn from(wrapped_function_type: WrappedFunctionType) -> Self { - match wrapped_function_type { - WrappedFunctionType::ReadLocal => PublicWrappedFunctionType::ReadLocal(Empty {}), - WrappedFunctionType::WriteLocal => PublicWrappedFunctionType::WriteLocal(Empty {}), - WrappedFunctionType::ReadRemote => PublicWrappedFunctionType::ReadRemote(Empty {}), - WrappedFunctionType::WriteRemote => PublicWrappedFunctionType::WriteRemote(Empty {}), - WrappedFunctionType::WriteRemoteBatched(index) => { - PublicWrappedFunctionType::WriteRemoteBatched(WriteRemoteBatchedParameters { +impl From for PublicDurableFunctionType { + fn from(function_type: DurableFunctionType) -> Self { + match function_type { + DurableFunctionType::ReadLocal => PublicDurableFunctionType::ReadLocal(Empty {}), + DurableFunctionType::WriteLocal => PublicDurableFunctionType::WriteLocal(Empty {}), + DurableFunctionType::ReadRemote => PublicDurableFunctionType::ReadRemote(Empty {}), + DurableFunctionType::WriteRemote => PublicDurableFunctionType::WriteRemote(Empty {}), + DurableFunctionType::WriteRemoteBatched(index) => { + PublicDurableFunctionType::WriteRemoteBatched(WriteRemoteBatchedParameters { index, }) } @@ -114,26 +114,26 @@ impl From for PublicWrappedFunctionType { } } -impl IntoValue for PublicWrappedFunctionType { +impl IntoValue for PublicDurableFunctionType { fn into_value(self) -> Value { match self { - PublicWrappedFunctionType::ReadLocal(_) => Value::Variant { + PublicDurableFunctionType::ReadLocal(_) => Value::Variant { case_idx: 0, case_value: None, }, - PublicWrappedFunctionType::WriteLocal(_) => Value::Variant { + PublicDurableFunctionType::WriteLocal(_) => Value::Variant { case_idx: 1, case_value: None, }, - PublicWrappedFunctionType::ReadRemote(_) => Value::Variant { + PublicDurableFunctionType::ReadRemote(_) => Value::Variant { case_idx: 2, case_value: None, }, - PublicWrappedFunctionType::WriteRemote(_) => Value::Variant { + PublicDurableFunctionType::WriteRemote(_) => Value::Variant { case_idx: 3, case_value: None, }, - PublicWrappedFunctionType::WriteRemoteBatched(params) => Value::Variant { + PublicDurableFunctionType::WriteRemoteBatched(params) => Value::Variant { case_idx: 4, case_value: Some(Box::new(params.index.into_value())), }, @@ -381,7 +381,7 @@ pub struct ImportedFunctionInvokedParameters { pub function_name: String, pub request: ValueAndType, pub response: ValueAndType, - pub wrapped_function_type: PublicWrappedFunctionType, + pub wrapped_function_type: PublicDurableFunctionType, // TODO: rename in Golem 2.0 } impl IntoValue for ImportedFunctionInvokedParameters { @@ -405,7 +405,7 @@ impl IntoValue for ImportedFunctionInvokedParameters { field("response", WitValue::get_type()), field( "wrapped_function_type", - PublicWrappedFunctionType::get_type(), + PublicDurableFunctionType::get_type(), ), ]) } @@ -1504,10 +1504,10 @@ mod protobuf { ExportedFunctionParameters, FailedUpdateParameters, GrowMemoryParameters, ImportedFunctionInvokedParameters, JumpParameters, LogParameters, ManualUpdateParameters, OplogCursor, PendingUpdateParameters, PendingWorkerInvocationParameters, - PluginInstallationDescription, PublicOplogEntry, PublicRetryConfig, - PublicUpdateDescription, PublicWorkerInvocation, PublicWrappedFunctionType, - ResourceParameters, SnapshotBasedUpdateParameters, SuccessfulUpdateParameters, - TimestampParameter, WriteRemoteBatchedParameters, + PluginInstallationDescription, PublicDurableFunctionType, PublicOplogEntry, + PublicRetryConfig, PublicUpdateDescription, PublicWorkerInvocation, ResourceParameters, + SnapshotBasedUpdateParameters, SuccessfulUpdateParameters, TimestampParameter, + WriteRemoteBatchedParameters, }; use crate::model::regions::OplogRegion; use crate::model::Empty; @@ -2186,7 +2186,7 @@ mod protobuf { } impl TryFrom - for PublicWrappedFunctionType + for PublicDurableFunctionType { type Error = String; @@ -2195,19 +2195,19 @@ mod protobuf { ) -> Result { match value.r#type() { wrapped_function_type::Type::ReadLocal => { - Ok(PublicWrappedFunctionType::ReadLocal(Empty {})) + Ok(PublicDurableFunctionType::ReadLocal(Empty {})) } wrapped_function_type::Type::WriteLocal => { - Ok(PublicWrappedFunctionType::WriteLocal(Empty {})) + Ok(PublicDurableFunctionType::WriteLocal(Empty {})) } wrapped_function_type::Type::ReadRemote => { - Ok(PublicWrappedFunctionType::ReadRemote(Empty {})) + Ok(PublicDurableFunctionType::ReadRemote(Empty {})) } wrapped_function_type::Type::WriteRemote => { - Ok(PublicWrappedFunctionType::WriteRemote(Empty {})) + Ok(PublicDurableFunctionType::WriteRemote(Empty {})) } wrapped_function_type::Type::WriteRemoteBatched => Ok( - PublicWrappedFunctionType::WriteRemoteBatched(WriteRemoteBatchedParameters { + PublicDurableFunctionType::WriteRemoteBatched(WriteRemoteBatchedParameters { index: value.oplog_index.map(OplogIndex::from_u64), }), ), @@ -2215,34 +2215,34 @@ mod protobuf { } } - impl From for golem_api_grpc::proto::golem::worker::WrappedFunctionType { - fn from(value: PublicWrappedFunctionType) -> Self { + impl From for golem_api_grpc::proto::golem::worker::WrappedFunctionType { + fn from(value: PublicDurableFunctionType) -> Self { match value { - PublicWrappedFunctionType::ReadLocal(_) => { + PublicDurableFunctionType::ReadLocal(_) => { golem_api_grpc::proto::golem::worker::WrappedFunctionType { r#type: wrapped_function_type::Type::ReadLocal as i32, oplog_index: None, } } - PublicWrappedFunctionType::WriteLocal(_) => { + PublicDurableFunctionType::WriteLocal(_) => { golem_api_grpc::proto::golem::worker::WrappedFunctionType { r#type: wrapped_function_type::Type::WriteLocal as i32, oplog_index: None, } } - PublicWrappedFunctionType::ReadRemote(_) => { + PublicDurableFunctionType::ReadRemote(_) => { golem_api_grpc::proto::golem::worker::WrappedFunctionType { r#type: wrapped_function_type::Type::ReadRemote as i32, oplog_index: None, } } - PublicWrappedFunctionType::WriteRemote(_) => { + PublicDurableFunctionType::WriteRemote(_) => { golem_api_grpc::proto::golem::worker::WrappedFunctionType { r#type: wrapped_function_type::Type::WriteRemote as i32, oplog_index: None, } } - PublicWrappedFunctionType::WriteRemoteBatched(parameters) => { + PublicDurableFunctionType::WriteRemoteBatched(parameters) => { golem_api_grpc::proto::golem::worker::WrappedFunctionType { r#type: wrapped_function_type::Type::WriteRemoteBatched as i32, oplog_index: parameters.index.map(|index| index.into()), @@ -2449,8 +2449,8 @@ mod tests { ExportedFunctionInvokedParameters, ExportedFunctionParameters, FailedUpdateParameters, GrowMemoryParameters, ImportedFunctionInvokedParameters, JumpParameters, LogParameters, PendingUpdateParameters, PendingWorkerInvocationParameters, PluginInstallationDescription, - PublicOplogEntry, PublicRetryConfig, PublicUpdateDescription, PublicWorkerInvocation, - PublicWrappedFunctionType, ResourceParameters, SnapshotBasedUpdateParameters, + PublicDurableFunctionType, PublicOplogEntry, PublicRetryConfig, PublicUpdateDescription, + PublicWorkerInvocation, ResourceParameters, SnapshotBasedUpdateParameters, SuccessfulUpdateParameters, TimestampParameter, }; use crate::model::{ @@ -2525,7 +2525,7 @@ mod tests { value: Value::List(vec![Value::U64(1)]), typ: list(u64()), }, - wrapped_function_type: PublicWrappedFunctionType::ReadRemote(Empty {}), + wrapped_function_type: PublicDurableFunctionType::ReadRemote(Empty {}), }); let serialized = entry.to_json_string(); let deserialized: PublicOplogEntry = serde_json::from_str(&serialized).unwrap(); 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 a88767d8fe..70c23aca30 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::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::WasiView; @@ -21,8 +21,7 @@ use crate::durable_host::blobstore::types::{ ContainerEntry, IncomingValueEntry, OutgoingValueEntry, StreamObjectNamesEntry, }; use crate::durable_host::serialized::SerializableError; -use crate::durable_host::{Durability, DurableWorkerCtx}; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx}; use crate::preview2::wasi::blobstore::container::{ Container, ContainerMetadata, Error, Host, HostContainer, HostStreamObjectNames, IncomingValue, ObjectMetadata, ObjectName, OutgoingValue, StreamObjectNames, @@ -35,7 +34,7 @@ impl HostContainer for DurableWorkerCtx { &mut self, container: Resource, ) -> anyhow::Result> { - record_host_function_call("blobstore::container::container", "name"); + self.observe_function_call("blobstore::container::container", "name"); let name = self .as_wasi_view() .table() @@ -48,7 +47,7 @@ impl HostContainer for DurableWorkerCtx { &mut self, container: Resource, ) -> anyhow::Result> { - record_host_function_call("blobstore::container::container", "info"); + self.observe_function_call("blobstore::container::container", "info"); let info = self .as_wasi_view() .table() @@ -67,11 +66,11 @@ impl HostContainer for DurableWorkerCtx { start: u64, end: u64, ) -> anyhow::Result, Error>> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem blobstore::container", "get_data", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; @@ -112,11 +111,11 @@ impl HostContainer for DurableWorkerCtx { name: ObjectName, data: Resource, ) -> anyhow::Result> { - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem blobstore::container", "write_data", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -156,11 +155,11 @@ impl HostContainer for DurableWorkerCtx { &mut self, container: Resource, ) -> anyhow::Result, Error>> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem blobstore::container", "list_object", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; @@ -199,11 +198,11 @@ impl HostContainer for DurableWorkerCtx { container: Resource, name: ObjectName, ) -> anyhow::Result> { - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem blobstore::container", "delete_object", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -238,11 +237,11 @@ impl HostContainer for DurableWorkerCtx { container: Resource, names: Vec, ) -> anyhow::Result> { - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem blobstore::container", "delete_objects", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -277,11 +276,11 @@ impl HostContainer for DurableWorkerCtx { container: Resource, name: ObjectName, ) -> anyhow::Result> { - let durability = Durability::::new( + let durability = Durability::::new( self, "golem blobstore::container", "has_object", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; @@ -317,11 +316,11 @@ impl HostContainer for DurableWorkerCtx { name: ObjectName, ) -> anyhow::Result> { let durability = - Durability::::new( + Durability::::new( self, "golem blobstore::container", "object_info", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; @@ -360,11 +359,11 @@ impl HostContainer for DurableWorkerCtx { } async fn clear(&mut self, container: Resource) -> anyhow::Result> { - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem blobstore::container", "clear", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -390,7 +389,7 @@ impl HostContainer for DurableWorkerCtx { } async fn drop(&mut self, container: Resource) -> anyhow::Result<()> { - record_host_function_call("blobstore::container::container", "drop"); + self.observe_function_call("blobstore::container::container", "drop"); self.as_wasi_view() .table() .delete::(container)?; @@ -405,7 +404,7 @@ impl HostStreamObjectNames for DurableWorkerCtx { self_: Resource, len: u64, ) -> anyhow::Result, bool), Error>> { - record_host_function_call( + self.observe_function_call( "blobstore::container::stream_object_names", "read_stream_object_names", ); @@ -431,7 +430,7 @@ impl HostStreamObjectNames for DurableWorkerCtx { self_: Resource, num: u64, ) -> anyhow::Result> { - record_host_function_call( + self.observe_function_call( "blobstore::container::stream_object_names", "skip_stream_object_names", ); @@ -453,7 +452,7 @@ impl HostStreamObjectNames for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("blobstore::container::stream_object_names", "drop"); + self.observe_function_call("blobstore::container::stream_object_names", "drop"); self.as_wasi_view().table().delete(rep)?; Ok(()) } 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 cea9ae06ed..fdef07c450 100644 --- a/golem-worker-executor-base/src/durable_host/blobstore/mod.rs +++ b/golem-worker-executor-base/src/durable_host/blobstore/mod.rs @@ -17,7 +17,7 @@ pub mod types; use async_trait::async_trait; use futures_util::TryFutureExt; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::WasiView; @@ -36,11 +36,11 @@ impl Host for DurableWorkerCtx { name: ContainerName, ) -> anyhow::Result, Error>> { let account_id = self.state.owned_worker_id.account_id(); - let durability = Durability::::new( + let durability = Durability::::new( self, "golem blobstore::blobstore", "create_container", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; let result = if durability.is_live() { @@ -72,11 +72,11 @@ impl Host for DurableWorkerCtx { name: ContainerName, ) -> anyhow::Result, Error>> { let account_id = self.state.owned_worker_id.account_id(); - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem blobstore::blobstore", "get_container", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; let result = if durability.is_live() { @@ -105,11 +105,11 @@ impl Host for DurableWorkerCtx { async fn delete_container(&mut self, name: ContainerName) -> anyhow::Result> { let account_id = self.state.owned_worker_id.account_id(); - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem blobstore::blobstore", "delete_container", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; let result = if durability.is_live() { @@ -134,11 +134,11 @@ impl Host for DurableWorkerCtx { name: ContainerName, ) -> anyhow::Result> { let account_id = self.state.owned_worker_id.account_id(); - let durability = Durability::::new( + let durability = Durability::::new( self, "golem blobstore::blobstore", "container_exists", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; let result = if durability.is_live() { @@ -164,11 +164,11 @@ impl Host for DurableWorkerCtx { dest: ObjectId, ) -> anyhow::Result> { let account_id = self.state.owned_worker_id.account_id(); - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem blobstore::blobstore", "copy_object", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; let result = if durability.is_live() { @@ -206,11 +206,11 @@ impl Host for DurableWorkerCtx { dest: ObjectId, ) -> anyhow::Result> { let account_id = self.state.owned_worker_id.account_id(); - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem blobstore::blobstore", "move_object", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; let result = if durability.is_live() { diff --git a/golem-worker-executor-base/src/durable_host/blobstore/types.rs b/golem-worker-executor-base/src/durable_host/blobstore/types.rs index 91142e8892..31b07175f0 100644 --- a/golem-worker-executor-base/src/durable_host/blobstore/types.rs +++ b/golem-worker-executor-base/src/durable_host/blobstore/types.rs @@ -22,8 +22,7 @@ use wasmtime_wasi::{ HostInputStream, HostOutputStream, InputStream, StreamResult, Subscribe, WasiView, }; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::preview2::wasi::blobstore::types::{ Error, Host, HostIncomingValue, HostOutgoingValue, IncomingValue, IncomingValueAsyncBody, @@ -34,7 +33,7 @@ use crate::workerctx::WorkerCtx; #[async_trait] impl HostOutgoingValue for DurableWorkerCtx { async fn new_outgoing_value(&mut self) -> anyhow::Result> { - record_host_function_call("blobstore::types::outgoing_value", "new_outgoing_value"); + self.observe_function_call("blobstore::types::outgoing_value", "new_outgoing_value"); let outgoing_value = self .as_wasi_view() .table() @@ -46,7 +45,7 @@ impl HostOutgoingValue for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, ()>> { - record_host_function_call( + self.observe_function_call( "blobstore::types::outgoing_value", "outgoing_value_write_body", ); @@ -62,7 +61,7 @@ impl HostOutgoingValue for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("blobstore::types::outgoing_value", "drop"); + self.observe_function_call("blobstore::types::outgoing_value", "drop"); self.as_wasi_view() .table() .delete::(rep)?; @@ -76,7 +75,7 @@ impl HostIncomingValue for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call( + self.observe_function_call( "blobstore::types::incoming_value", "incoming_value_consume_sync", ); @@ -94,7 +93,7 @@ impl HostIncomingValue for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, Error>> { - record_host_function_call( + self.observe_function_call( "blobstore::types::incoming_value", "incoming_value_consume_async", ); @@ -110,7 +109,7 @@ impl HostIncomingValue for DurableWorkerCtx { } async fn size(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("blobstore::types::incoming_value", "size"); + self.observe_function_call("blobstore::types::incoming_value", "size"); let body = self .as_wasi_view() .table() @@ -122,7 +121,7 @@ impl HostIncomingValue for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("blobstore::types::incoming_value", "drop"); + self.observe_function_call("blobstore::types::incoming_value", "drop"); self.as_wasi_view() .table() .delete::(rep)?; 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 a0bdbbcfa0..f3a720a4e2 100644 --- a/golem-worker-executor-base/src/durable_host/cli/environment.rs +++ b/golem-worker-executor-base/src/durable_host/cli/environment.rs @@ -17,17 +17,17 @@ use async_trait::async_trait; use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime_wasi::bindings::cli::environment::Host; #[async_trait] impl Host for DurableWorkerCtx { async fn get_environment(&mut self) -> anyhow::Result> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem_environment", "get_environment", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; @@ -40,11 +40,11 @@ impl Host for DurableWorkerCtx { } async fn get_arguments(&mut self) -> anyhow::Result> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem_environment", "get_arguments", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; @@ -57,11 +57,11 @@ impl Host for DurableWorkerCtx { } async fn initial_cwd(&mut self) -> anyhow::Result> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem_environment", "get_arguments", // TODO: fix in 2.0 - for backward compatibility with Golem 1.0 - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; diff --git a/golem-worker-executor-base/src/durable_host/cli/exit.rs b/golem-worker-executor-base/src/durable_host/cli/exit.rs index 5e31c453b7..5f955b903f 100644 --- a/golem-worker-executor-base/src/durable_host/cli/exit.rs +++ b/golem-worker-executor-base/src/durable_host/cli/exit.rs @@ -14,20 +14,19 @@ use async_trait::async_trait; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::exit::Host; #[async_trait] impl Host for DurableWorkerCtx { fn exit(&mut self, status: Result<(), ()>) -> anyhow::Result<()> { - record_host_function_call("cli::exit", "exit"); + self.observe_function_call("cli::exit", "exit"); Host::exit(&mut self.as_wasi_view(), status) } fn exit_with_code(&mut self, status_code: u8) -> anyhow::Result<()> { - record_host_function_call("cli::exit", "exit_with_code"); + self.observe_function_call("cli::exit", "exit_with_code"); Host::exit_with_code(&mut self.as_wasi_view(), status_code) } } diff --git a/golem-worker-executor-base/src/durable_host/cli/stderr.rs b/golem-worker-executor-base/src/durable_host/cli/stderr.rs index a2e3f22026..787bd7cde1 100644 --- a/golem-worker-executor-base/src/durable_host/cli/stderr.rs +++ b/golem-worker-executor-base/src/durable_host/cli/stderr.rs @@ -14,14 +14,13 @@ use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::stderr::{Host, OutputStream}; impl Host for DurableWorkerCtx { fn get_stderr(&mut self) -> anyhow::Result> { - record_host_function_call("cli::stderr", "get_stderr"); + self.observe_function_call("cli::stderr", "get_stderr"); self.as_wasi_view().get_stderr() } } diff --git a/golem-worker-executor-base/src/durable_host/cli/stdin.rs b/golem-worker-executor-base/src/durable_host/cli/stdin.rs index d11192509d..a4c6cd0041 100644 --- a/golem-worker-executor-base/src/durable_host/cli/stdin.rs +++ b/golem-worker-executor-base/src/durable_host/cli/stdin.rs @@ -14,14 +14,13 @@ use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::stdin::{Host, InputStream}; impl Host for DurableWorkerCtx { fn get_stdin(&mut self) -> anyhow::Result> { - record_host_function_call("cli::stdin", "get_stdin"); + self.observe_function_call("cli::stdin", "get_stdin"); self.as_wasi_view().get_stdin() } } diff --git a/golem-worker-executor-base/src/durable_host/cli/stdout.rs b/golem-worker-executor-base/src/durable_host/cli/stdout.rs index 666cb7272c..4bd7b38f72 100644 --- a/golem-worker-executor-base/src/durable_host/cli/stdout.rs +++ b/golem-worker-executor-base/src/durable_host/cli/stdout.rs @@ -14,14 +14,13 @@ use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::stdout::{Host, OutputStream}; impl Host for DurableWorkerCtx { fn get_stdout(&mut self) -> anyhow::Result> { - record_host_function_call("cli::stdout", "get_stdout"); + self.observe_function_call("cli::stdout", "get_stdout"); self.as_wasi_view().get_stdout() } } diff --git a/golem-worker-executor-base/src/durable_host/cli/terminal_input.rs b/golem-worker-executor-base/src/durable_host/cli/terminal_input.rs index 2b823ddd55..d0ce424257 100644 --- a/golem-worker-executor-base/src/durable_host/cli/terminal_input.rs +++ b/golem-worker-executor-base/src/durable_host/cli/terminal_input.rs @@ -15,15 +15,14 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::terminal_input::{Host, HostTerminalInput, TerminalInput}; #[async_trait] impl HostTerminalInput for DurableWorkerCtx { fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("cli::terminal_input::terminal_input", "drop"); + self.observe_function_call("cli::terminal_input::terminal_input", "drop"); HostTerminalInput::drop(&mut self.as_wasi_view(), rep) } } diff --git a/golem-worker-executor-base/src/durable_host/cli/terminal_output.rs b/golem-worker-executor-base/src/durable_host/cli/terminal_output.rs index 10fa916073..ba1e8f3b43 100644 --- a/golem-worker-executor-base/src/durable_host/cli/terminal_output.rs +++ b/golem-worker-executor-base/src/durable_host/cli/terminal_output.rs @@ -15,15 +15,14 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::terminal_output::{Host, HostTerminalOutput, TerminalOutput}; #[async_trait] impl HostTerminalOutput for DurableWorkerCtx { fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("cli::terminal_output::terminal_output", "drop"); + self.observe_function_call("cli::terminal_output::terminal_output", "drop"); HostTerminalOutput::drop(&mut self.as_wasi_view(), rep) } } diff --git a/golem-worker-executor-base/src/durable_host/cli/terminal_stderr.rs b/golem-worker-executor-base/src/durable_host/cli/terminal_stderr.rs index f46e4289ef..1dcabd4ed8 100644 --- a/golem-worker-executor-base/src/durable_host/cli/terminal_stderr.rs +++ b/golem-worker-executor-base/src/durable_host/cli/terminal_stderr.rs @@ -15,15 +15,14 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::terminal_stderr::{Host, TerminalOutput}; #[async_trait] impl Host for DurableWorkerCtx { fn get_terminal_stderr(&mut self) -> anyhow::Result>> { - record_host_function_call("cli::terminal_stderr", "get_terminal_stderr"); + self.observe_function_call("cli::terminal_stderr", "get_terminal_stderr"); self.as_wasi_view().get_terminal_stderr() } } diff --git a/golem-worker-executor-base/src/durable_host/cli/terminal_stdin.rs b/golem-worker-executor-base/src/durable_host/cli/terminal_stdin.rs index 1fe68b4a1e..10402eaa7d 100644 --- a/golem-worker-executor-base/src/durable_host/cli/terminal_stdin.rs +++ b/golem-worker-executor-base/src/durable_host/cli/terminal_stdin.rs @@ -15,15 +15,14 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::terminal_stdin::{Host, TerminalInput}; #[async_trait] impl Host for DurableWorkerCtx { fn get_terminal_stdin(&mut self) -> anyhow::Result>> { - record_host_function_call("cli::terminal_stdin", "get_terminal_stdin"); + self.observe_function_call("cli::terminal_stdin", "get_terminal_stdin"); self.as_wasi_view().get_terminal_stdin() } } diff --git a/golem-worker-executor-base/src/durable_host/cli/terminal_stdout.rs b/golem-worker-executor-base/src/durable_host/cli/terminal_stdout.rs index e5c82def97..451ab45c68 100644 --- a/golem-worker-executor-base/src/durable_host/cli/terminal_stdout.rs +++ b/golem-worker-executor-base/src/durable_host/cli/terminal_stdout.rs @@ -15,15 +15,14 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::cli::terminal_stdout::{Host, TerminalOutput}; #[async_trait] impl Host for DurableWorkerCtx { fn get_terminal_stdout(&mut self) -> anyhow::Result>> { - record_host_function_call("cli::terminal_stdout", "get_terminal_stdout"); + self.observe_function_call("cli::terminal_stdout", "get_terminal_stdout"); self.as_wasi_view().get_terminal_stdout() } } 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 d3ef9e267e..9531315722 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 @@ -16,21 +16,20 @@ use async_trait::async_trait; use wasmtime::component::Resource; use crate::durable_host::serialized::SerializableError; -use crate::durable_host::{Durability, DurableWorkerCtx}; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx}; use crate::services::oplog::CommitLevel; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime_wasi::bindings::clocks::monotonic_clock::{Duration, Host, Instant, Pollable}; #[async_trait] impl Host for DurableWorkerCtx { async fn now(&mut self) -> anyhow::Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "monotonic_clock", "now", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; @@ -43,11 +42,11 @@ impl Host for DurableWorkerCtx { } async fn resolution(&mut self) -> anyhow::Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "monotonic_clock", "resolution", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; @@ -60,16 +59,16 @@ impl Host for DurableWorkerCtx { } async fn subscribe_instant(&mut self, when: Instant) -> anyhow::Result> { - record_host_function_call("clocks::monotonic_clock", "subscribe_instant"); + self.observe_function_call("clocks::monotonic_clock", "subscribe_instant"); Host::subscribe_instant(&mut self.as_wasi_view(), when).await } async fn subscribe_duration(&mut self, when: Duration) -> anyhow::Result> { - let durability = Durability::::new( + let durability = Durability::::new( self, "monotonic_clock", "now", // TODO: fix in 2.0 - should be 'subscribe_duration' but have to keep for backward compatibility with Golem 1.0 - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; 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 78dfb268c5..40bdd72cd5 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 @@ -17,17 +17,17 @@ use async_trait::async_trait; use crate::durable_host::serialized::{SerializableDateTime, SerializableError}; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime_wasi::bindings::clocks::wall_clock::{Datetime, Host}; #[async_trait] impl Host for DurableWorkerCtx { async fn now(&mut self) -> anyhow::Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "wall_clock", "now", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; @@ -40,11 +40,11 @@ impl Host for DurableWorkerCtx { } async fn resolution(&mut self) -> anyhow::Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "wall_clock", "resolution", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; diff --git a/golem-worker-executor-base/src/durable_host/durability.rs b/golem-worker-executor-base/src/durable_host/durability.rs index 4f3e4bb72d..3c9bb0e314 100644 --- a/golem-worker-executor-base/src/durable_host/durability.rs +++ b/golem-worker-executor-base/src/durable_host/durability.rs @@ -18,62 +18,262 @@ use crate::metrics::wasm::record_host_function_call; use crate::model::PersistenceLevel; use crate::services::oplog::{CommitLevel, OplogOps}; use crate::workerctx::WorkerCtx; +use async_trait::async_trait; use bincode::{Decode, Encode}; use bytes::Bytes; -use golem_common::model::oplog::{OplogEntry, OplogIndex, WrappedFunctionType}; -use golem_common::serialization::try_deserialize; +use golem_common::model::oplog::{DurableFunctionType, OplogEntry, OplogIndex}; +use golem_common::model::Timestamp; +use golem_common::serialization::{serialize, try_deserialize}; +use golem_wasm_rpc::{IntoValue, IntoValueAndType, ValueAndType}; use std::fmt::Debug; use std::marker::PhantomData; use tracing::error; +#[derive(Debug)] +pub struct DurableExecutionState { + pub is_live: bool, + pub persistence_level: PersistenceLevel, +} + +#[derive(Debug)] +#[allow(dead_code)] +pub struct PersistedDurableFunctionInvocation { + timestamp: Timestamp, + function_name: String, + response: Vec, + function_type: DurableFunctionType, + oplog_entry_version: OplogEntryVersion, +} + +#[async_trait] +pub trait DurabilityHost { + /// Observes a function call (produces logs and metrics) + fn observe_function_call(&self, interface: &'static str, function: &'static str); + + /// Marks the beginning of a durable function. + /// + /// There must be a corresponding call to `end_durable_function` after the function has + /// performed its work (it can be ended in a different context, for example after an async + /// pollable operation has been completed) + async fn begin_durable_function( + &mut self, + function_type: &DurableFunctionType, + ) -> Result; + + /// Marks the end of a durable function + /// + /// This is a pair of `begin_durable_function` and should be called after the durable function + /// has performed and persisted or replayed its work. The `begin_index` should be the index + /// returned by `begin_durable_function`. + async fn end_durable_function( + &mut self, + function_type: &DurableFunctionType, + begin_index: OplogIndex, + ) -> Result<(), GolemError>; + + /// Gets the current durable execution state + fn durable_execution_state(&self) -> DurableExecutionState; + + /// Writes a record to the worker's oplog representing a durable function invocation + async fn persist_durable_function_invocation( + &self, + function_name: String, + request: &[u8], + response: &[u8], + function_type: DurableFunctionType, + ); + + /// Writes a record to the worker's oplog representing a durable function invocation + /// + /// The request and response are defined as pairs of value and type, which makes it + /// self-describing for observers of oplogs. This is the recommended way to persist + /// third-party function invocations. + async fn persist_typed_durable_function_invocation( + &self, + function_name: String, + request: ValueAndType, + response: ValueAndType, + function_type: DurableFunctionType, + ); + + /// Reads the next persisted durable function invocation from the oplog during replay + async fn read_persisted_durable_function_invocation( + &mut self, + ) -> Result; +} + +#[async_trait] +impl DurabilityHost for DurableWorkerCtx { + fn observe_function_call(&self, interface: &'static str, function: &'static str) { + record_host_function_call(interface, function); + } + + async fn begin_durable_function( + &mut self, + function_type: &DurableFunctionType, + ) -> Result { + self.state.begin_function(function_type).await + } + + async fn end_durable_function( + &mut self, + function_type: &DurableFunctionType, + begin_index: OplogIndex, + ) -> Result<(), GolemError> { + self.state.end_function(function_type, begin_index).await?; + if function_type == &DurableFunctionType::WriteRemote + || matches!(function_type, DurableFunctionType::WriteRemoteBatched(_)) + { + self.state.oplog.commit(CommitLevel::DurableOnly).await; + } + Ok(()) + } + + fn durable_execution_state(&self) -> DurableExecutionState { + DurableExecutionState { + is_live: self.state.is_live(), + persistence_level: self.state.persistence_level, + } + } + + async fn persist_durable_function_invocation( + &self, + function_name: String, + request: &[u8], + response: &[u8], + function_type: DurableFunctionType, + ) { + self.state + .oplog + .add_raw_imported_function_invoked(function_name, request, response, function_type) + .await + .unwrap_or_else(|err| { + panic!("failed to serialize and store durable function invocation: {err}") + }); + } + + async fn persist_typed_durable_function_invocation( + &self, + function_name: String, + request: ValueAndType, + response: ValueAndType, + function_type: DurableFunctionType, + ) { + let request = serialize(&request).unwrap_or_else(|err| { + panic!("failed to serialize request ({request:?}) for persisting durable function invocation: {err}") + }).to_vec(); + let response = serialize(&response).unwrap_or_else(|err| { + panic!("failed to serialize response ({response:?}) for persisting durable function invocation: {err}") + }).to_vec(); + + self.state + .oplog + .add_imported_function_invoked(function_name, &request, &response, function_type) + .await + .unwrap_or_else(|err| { + panic!("failed to serialize and store durable function invocation: {err}") + }); + } + + async fn read_persisted_durable_function_invocation( + &mut self, + ) -> Result { + let (_, oplog_entry) = crate::get_oplog_entry!( + self.state.replay_state, + OplogEntry::ImportedFunctionInvoked, + OplogEntry::ImportedFunctionInvokedV1 + )?; + + let bytes = self + .state + .oplog + .get_raw_payload_of_entry(&oplog_entry) + .await + .map_err(|err| { + GolemError::unexpected_oplog_entry("ImportedFunctionInvoked payload", err) + })? + .unwrap(); + + match oplog_entry { + OplogEntry::ImportedFunctionInvoked { + timestamp, + function_name, + wrapped_function_type, + .. + } => Ok(PersistedDurableFunctionInvocation { + timestamp, + function_name, + response: bytes.to_vec(), + function_type: wrapped_function_type, + oplog_entry_version: OplogEntryVersion::V2, + }), + OplogEntry::ImportedFunctionInvokedV1 { + timestamp, + function_name, + wrapped_function_type, + .. + } => Ok(PersistedDurableFunctionInvocation { + timestamp, + function_name, + response: bytes.to_vec(), + function_type: wrapped_function_type, + oplog_entry_version: OplogEntryVersion::V1, + }), + _ => Err(GolemError::unexpected_oplog_entry( + "ImportedFunctionInvoked", + format!("{:?}", oplog_entry), + )), + } + } +} + +#[derive(Debug)] pub enum OplogEntryVersion { V1, V2, } -pub struct Durability { - package: &'static str, +pub struct Durability { + interface: &'static str, function: &'static str, - function_type: WrappedFunctionType, + function_type: DurableFunctionType, begin_index: OplogIndex, - is_live: bool, - persistence_level: PersistenceLevel, - _ctx: PhantomData, + durable_execution_state: DurableExecutionState, _sok: PhantomData, _serr: PhantomData, } -impl Durability { +impl Durability { pub async fn new( - ctx: &mut DurableWorkerCtx, - package: &'static str, + ctx: &mut impl DurabilityHost, + interface: &'static str, function: &'static str, - function_type: WrappedFunctionType, + function_type: DurableFunctionType, ) -> Result { - record_host_function_call(package, function); + ctx.observe_function_call(interface, function); - let begin_index = ctx.state.begin_function(&function_type).await?; + let begin_index = ctx.begin_durable_function(&function_type).await?; + let durable_execution_state = ctx.durable_execution_state(); Ok(Self { - package, + interface, function, function_type, begin_index, - is_live: ctx.state.is_live(), - persistence_level: ctx.state.persistence_level.clone(), - _ctx: PhantomData, + durable_execution_state, _sok: PhantomData, _serr: PhantomData, }) } pub fn is_live(&self) -> bool { - self.is_live || self.persistence_level == PersistenceLevel::PersistNothing + self.durable_execution_state.is_live + || self.durable_execution_state.persistence_level == PersistenceLevel::PersistNothing } pub async fn persist( &self, - ctx: &mut DurableWorkerCtx, + ctx: &mut impl DurabilityHost, input: SIn, result: Result, ) -> Result @@ -101,9 +301,9 @@ impl Durability { pub async fn persist_serializable( &self, - ctx: &mut DurableWorkerCtx, + ctx: &mut impl DurabilityHost, input: SIn, - serializable_result: Result, + result: Result, ) -> Result<(), GolemError> where SIn: Debug + Encode + Send + Sync, @@ -111,77 +311,74 @@ impl Durability { SErr: Debug + Encode + Send + Sync, { let function_name = self.function_name(); - if ctx.state.persistence_level != PersistenceLevel::PersistNothing { - ctx.state - .oplog - .add_imported_function_invoked( - function_name.to_string(), - &input, - &serializable_result, - self.function_type.clone(), - ) - .await - .unwrap_or_else(|err| { - panic!( - "failed to serialize and store function request ({:?}) and response ({:?}): {err}", - input, - serializable_result - ) - }); - ctx.state - .end_function(&self.function_type, self.begin_index) + if self.durable_execution_state.persistence_level != PersistenceLevel::PersistNothing { + let serialized_input = serialize(&input).unwrap_or_else(|err| { + panic!("failed to serialize input ({input:?}) for persisting durable function invocation: {err}") + }).to_vec(); + let serialized_result = serialize(&result).unwrap_or_else(|err| { + panic!("failed to serialize result ({result:?}) for persisting durable function invocation: {err}") + }).to_vec(); + + ctx.persist_durable_function_invocation( + function_name.to_string(), + &serialized_input, + &serialized_result, + self.function_type.clone(), + ) + .await; + ctx.end_durable_function(&self.function_type, self.begin_index) + .await?; + } + Ok(()) + } + + pub async fn persist_typed_value( + &self, + ctx: &mut impl DurabilityHost, + input: SIn, + result: Result, + ) -> Result<(), GolemError> + where + SIn: Debug + IntoValue + Send + Sync, + SOk: Debug + IntoValue + Send + Sync, + SErr: Debug + IntoValue + Send + Sync, + { + let function_name = self.function_name(); + if self.durable_execution_state.persistence_level != PersistenceLevel::PersistNothing { + let input_value = input.into_value_and_type(); + let result_value = result.into_value_and_type(); + + ctx.persist_typed_durable_function_invocation( + function_name.to_string(), + input_value, + result_value, + self.function_type.clone(), + ) + .await; + ctx.end_durable_function(&self.function_type, self.begin_index) .await?; - if self.function_type == WrappedFunctionType::WriteRemote - || matches!( - self.function_type, - WrappedFunctionType::WriteRemoteBatched(_) - ) - { - ctx.state.oplog.commit(CommitLevel::DurableOnly).await; - } } Ok(()) } pub async fn replay_raw( &self, - ctx: &mut DurableWorkerCtx, + ctx: &mut impl DurabilityHost, ) -> Result<(Bytes, OplogEntryVersion), GolemError> { - let (_, oplog_entry) = crate::get_oplog_entry!( - ctx.state.replay_state, - OplogEntry::ImportedFunctionInvoked, - OplogEntry::ImportedFunctionInvokedV1 - )?; - - let version = if matches!(oplog_entry, OplogEntry::ImportedFunctionInvokedV1 { .. }) { - OplogEntryVersion::V1 - } else { - OplogEntryVersion::V2 - }; + let oplog_entry = ctx.read_persisted_durable_function_invocation().await?; let function_name = self.function_name(); Self::validate_oplog_entry(&oplog_entry, &function_name)?; - let bytes = ctx - .state - .oplog - .get_raw_payload_of_entry(&oplog_entry) - .await - .map_err(|err| { - GolemError::unexpected_oplog_entry("ImportedFunctionInvoked payload", err) - })? - .unwrap(); - - ctx.state - .end_function(&self.function_type, self.begin_index) + ctx.end_durable_function(&self.function_type, self.begin_index) .await?; - Ok((bytes, version)) + Ok((oplog_entry.response.into(), oplog_entry.oplog_entry_version)) } pub async fn replay_serializable( &self, - ctx: &mut DurableWorkerCtx, + ctx: &mut impl DurabilityHost, ) -> Result, GolemError> where SOk: Decode, @@ -196,7 +393,7 @@ impl Durability { Ok(result) } - pub async fn replay(&self, ctx: &mut DurableWorkerCtx) -> Result + pub async fn replay(&self, ctx: &mut impl DurabilityHost) -> Result where Ok: From, Err: From + From, @@ -210,44 +407,27 @@ impl Durability { } fn function_name(&self) -> String { - if self.package.is_empty() { + if self.interface.is_empty() { // For backward compatibility - some of the recorded function names were not following the pattern self.function.to_string() } else { - format!("{}::{}", self.package, self.function) + format!("{}::{}", self.interface, self.function) } } fn validate_oplog_entry( - oplog_entry: &OplogEntry, + oplog_entry: &PersistedDurableFunctionInvocation, expected_function_name: &str, ) -> Result<(), GolemError> { - if let OplogEntry::ImportedFunctionInvoked { function_name, .. } = oplog_entry { - if function_name != expected_function_name { - error!( - "Unexpected imported function call entry in oplog: expected {}, got {}", - expected_function_name, function_name - ); - Err(GolemError::unexpected_oplog_entry( - expected_function_name, - function_name, - )) - } else { - Ok(()) - } - } else if let OplogEntry::ImportedFunctionInvokedV1 { function_name, .. } = oplog_entry { - if function_name != expected_function_name { - error!( - "Unexpected imported function call entry in oplog: expected {}, got {}", - expected_function_name, function_name - ); - Err(GolemError::unexpected_oplog_entry( - expected_function_name, - function_name, - )) - } else { - Ok(()) - } + if oplog_entry.function_name != expected_function_name { + error!( + "Unexpected imported function call entry in oplog: expected {}, got {}", + expected_function_name, oplog_entry.function_name + ); + Err(GolemError::unexpected_oplog_entry( + expected_function_name, + oplog_entry.function_name.clone(), + )) } else { Ok(()) } 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 1667e9cf3a..d2f522d901 100644 --- a/golem-worker-executor-base/src/durable_host/filesystem/preopens.rs +++ b/golem-worker-executor-base/src/durable_host/filesystem/preopens.rs @@ -19,17 +19,17 @@ use wasmtime::component::Resource; use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime_wasi::bindings::filesystem::preopens::{Descriptor, Host}; #[async_trait] impl Host for DurableWorkerCtx { async fn get_directories(&mut self) -> anyhow::Result, String)>> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "cli::preopens", "get_directories", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; 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 aed6257eac..a352f212ed 100644 --- a/golem-worker-executor-base/src/durable_host/filesystem/types.rs +++ b/golem-worker-executor-base/src/durable_host/filesystem/types.rs @@ -30,13 +30,12 @@ use wasmtime_wasi::runtime::spawn_blocking; use wasmtime_wasi::FsError; use wasmtime_wasi::ReaddirIterator; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use crate::durable_host::serialized::{ SerializableDateTime, SerializableError, SerializableFileTimes, }; -use crate::durable_host::{Durability, DurableWorkerCtx}; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; #[async_trait] @@ -46,7 +45,7 @@ impl HostDescriptor for DurableWorkerCtx { self_: Resource, offset: Filesize, ) -> Result, FsError> { - record_host_function_call("filesystem::types::descriptor", "read_via_stream"); + self.observe_function_call("filesystem::types::descriptor", "read_via_stream"); HostDescriptor::read_via_stream(&mut self.as_wasi_view(), self_, offset) } @@ -56,7 +55,7 @@ impl HostDescriptor for DurableWorkerCtx { offset: Filesize, ) -> Result, FsError> { self.fail_if_read_only(&fd)?; - record_host_function_call("filesystem::types::descriptor", "write_via_stream"); + self.observe_function_call("filesystem::types::descriptor", "write_via_stream"); HostDescriptor::write_via_stream(&mut self.as_wasi_view(), fd, offset) } @@ -64,7 +63,7 @@ impl HostDescriptor for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result, FsError> { - record_host_function_call("filesystem::types::descriptor", "append_via_stream"); + self.observe_function_call("filesystem::types::descriptor", "append_via_stream"); HostDescriptor::append_via_stream(&mut self.as_wasi_view(), self_) } @@ -75,17 +74,17 @@ impl HostDescriptor for DurableWorkerCtx { length: Filesize, advice: Advice, ) -> Result<(), FsError> { - record_host_function_call("filesystem::types::descriptor", "advise"); + self.observe_function_call("filesystem::types::descriptor", "advise"); HostDescriptor::advise(&mut self.as_wasi_view(), self_, offset, length, advice).await } async fn sync_data(&mut self, self_: Resource) -> Result<(), FsError> { - record_host_function_call("filesystem::types::descriptor", "sync_data"); + self.observe_function_call("filesystem::types::descriptor", "sync_data"); HostDescriptor::sync_data(&mut self.as_wasi_view(), self_).await } async fn get_flags(&mut self, fd: Resource) -> Result { - record_host_function_call("filesystem::types::descriptor", "get_flags"); + self.observe_function_call("filesystem::types::descriptor", "get_flags"); let read_only = self.is_read_only(&fd)?; let wasi_view = &mut self.as_wasi_view(); @@ -99,14 +98,14 @@ impl HostDescriptor for DurableWorkerCtx { } async fn get_type(&mut self, self_: Resource) -> Result { - record_host_function_call("filesystem::types::descriptor", "get_type"); + self.observe_function_call("filesystem::types::descriptor", "get_type"); HostDescriptor::get_type(&mut self.as_wasi_view(), self_).await } async fn set_size(&mut self, fd: Resource, size: Filesize) -> Result<(), FsError> { self.fail_if_read_only(&fd)?; - record_host_function_call("filesystem::types::descriptor", "set_size"); + self.observe_function_call("filesystem::types::descriptor", "set_size"); HostDescriptor::set_size(&mut self.as_wasi_view(), fd, size).await } @@ -119,7 +118,7 @@ impl HostDescriptor for DurableWorkerCtx { ) -> Result<(), FsError> { self.fail_if_read_only(&fd)?; - record_host_function_call("filesystem::types::descriptor", "set_times"); + self.observe_function_call("filesystem::types::descriptor", "set_times"); HostDescriptor::set_times( &mut self.as_wasi_view(), @@ -136,7 +135,7 @@ impl HostDescriptor for DurableWorkerCtx { length: Filesize, offset: Filesize, ) -> Result<(Vec, bool), FsError> { - record_host_function_call("filesystem::types::descriptor", "read"); + self.observe_function_call("filesystem::types::descriptor", "read"); HostDescriptor::read(&mut self.as_wasi_view(), self_, length, offset).await } @@ -148,7 +147,7 @@ impl HostDescriptor for DurableWorkerCtx { ) -> Result { self.fail_if_read_only(&fd)?; - record_host_function_call("filesystem::types::descriptor", "write"); + self.observe_function_call("filesystem::types::descriptor", "write"); HostDescriptor::write(&mut self.as_wasi_view(), fd, buffer, offset).await } @@ -156,7 +155,7 @@ impl HostDescriptor for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result, FsError> { - record_host_function_call("filesystem::types::descriptor", "read_directory"); + self.observe_function_call("filesystem::types::descriptor", "read_directory"); let stream = HostDescriptor::read_directory(&mut self.as_wasi_view(), self_).await?; // Iterating through the whole stream to make sure we have a stable order let mut entries = Vec::new(); @@ -172,7 +171,7 @@ impl HostDescriptor for DurableWorkerCtx { } async fn sync(&mut self, self_: Resource) -> Result<(), FsError> { - record_host_function_call("filesystem::types::descriptor", "sync"); + self.observe_function_call("filesystem::types::descriptor", "sync"); HostDescriptor::sync(&mut self.as_wasi_view(), self_).await } @@ -181,16 +180,16 @@ impl HostDescriptor for DurableWorkerCtx { self_: Resource, path: String, ) -> Result<(), FsError> { - record_host_function_call("filesystem::types::descriptor", "create_directory_at"); + self.observe_function_call("filesystem::types::descriptor", "create_directory_at"); HostDescriptor::create_directory_at(&mut self.as_wasi_view(), self_, path).await } async fn stat(&mut self, self_: Resource) -> Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "filesystem::types::descriptor", "stat", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await .map_err(FsError::trap)?; @@ -241,11 +240,11 @@ impl HostDescriptor for DurableWorkerCtx { path_flags: PathFlags, path: String, ) -> Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "filesystem::types::descriptor", "stat_at", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await .map_err(FsError::trap)?; @@ -301,7 +300,7 @@ impl HostDescriptor for DurableWorkerCtx { ) -> Result<(), FsError> { self.fail_if_read_only(&fd)?; - record_host_function_call("filesystem::types::descriptor", "set_times_at"); + self.observe_function_call("filesystem::types::descriptor", "set_times_at"); HostDescriptor::set_times_at( &mut self.as_wasi_view(), fd, @@ -321,7 +320,7 @@ impl HostDescriptor for DurableWorkerCtx { new_descriptor: Resource, new_path: String, ) -> Result<(), FsError> { - record_host_function_call("filesystem::types::descriptor", "link_at"); + self.observe_function_call("filesystem::types::descriptor", "link_at"); HostDescriptor::link_at( &mut self.as_wasi_view(), self_, @@ -341,7 +340,7 @@ impl HostDescriptor for DurableWorkerCtx { open_flags: OpenFlags, flags: DescriptorFlags, ) -> Result, FsError> { - record_host_function_call("filesystem::types::descriptor", "open_at"); + self.observe_function_call("filesystem::types::descriptor", "open_at"); HostDescriptor::open_at( &mut self.as_wasi_view(), self_, @@ -358,7 +357,7 @@ impl HostDescriptor for DurableWorkerCtx { self_: Resource, path: String, ) -> Result { - record_host_function_call("filesystem::types::descriptor", "readlink_at"); + self.observe_function_call("filesystem::types::descriptor", "readlink_at"); HostDescriptor::readlink_at(&mut self.as_wasi_view(), self_, path).await } @@ -367,7 +366,7 @@ impl HostDescriptor for DurableWorkerCtx { self_: Resource, path: String, ) -> Result<(), FsError> { - record_host_function_call("filesystem::types::descriptor", "remove_directory_at"); + self.observe_function_call("filesystem::types::descriptor", "remove_directory_at"); HostDescriptor::remove_directory_at(&mut self.as_wasi_view(), self_, path.clone()).await } @@ -381,7 +380,7 @@ impl HostDescriptor for DurableWorkerCtx { self.fail_if_read_only(&old_fd)?; self.fail_if_read_only(&new_fd)?; - record_host_function_call("filesystem::types::descriptor", "rename_at"); + self.observe_function_call("filesystem::types::descriptor", "rename_at"); HostDescriptor::rename_at( &mut self.as_wasi_view(), old_fd, @@ -400,7 +399,7 @@ impl HostDescriptor for DurableWorkerCtx { ) -> Result<(), FsError> { self.fail_if_read_only(&fd)?; - record_host_function_call("filesystem::types::descriptor", "symlink_at"); + self.observe_function_call("filesystem::types::descriptor", "symlink_at"); HostDescriptor::symlink_at(&mut self.as_wasi_view(), fd, old_path, new_path.clone()).await } @@ -411,7 +410,7 @@ impl HostDescriptor for DurableWorkerCtx { ) -> Result<(), FsError> { self.fail_if_read_only(&fd)?; - record_host_function_call("filesystem::types::descriptor", "unlink_file_at"); + self.observe_function_call("filesystem::types::descriptor", "unlink_file_at"); HostDescriptor::unlink_file_at(&mut self.as_wasi_view(), fd, path.clone()).await } @@ -420,7 +419,7 @@ impl HostDescriptor for DurableWorkerCtx { self_: Resource, other: Resource, ) -> anyhow::Result { - record_host_function_call("filesystem::types::descriptor", "is_same_object"); + self.observe_function_call("filesystem::types::descriptor", "is_same_object"); HostDescriptor::is_same_object(&mut self.as_wasi_view(), self_, other).await } @@ -428,7 +427,7 @@ impl HostDescriptor for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result { - record_host_function_call("filesystem::types::descriptor", "metadata_hash"); + self.observe_function_call("filesystem::types::descriptor", "metadata_hash"); // Using the WASI stat function as it guarantees the file times are preserved let metadata = self.stat(self_).await?; @@ -442,7 +441,7 @@ impl HostDescriptor for DurableWorkerCtx { path_flags: PathFlags, path: String, ) -> Result { - record_host_function_call("filesystem::types::descriptor", "metadata_hash_at"); + self.observe_function_call("filesystem::types::descriptor", "metadata_hash_at"); // Using the WASI stat_at function as it guarantees the file times are preserved let metadata = self.stat_at(self_, path_flags, path).await?; @@ -450,7 +449,7 @@ impl HostDescriptor for DurableWorkerCtx { } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("filesystem::types::descriptor", "drop"); + self.observe_function_call("filesystem::types::descriptor", "drop"); HostDescriptor::drop(&mut self.as_wasi_view(), rep) } } @@ -461,7 +460,7 @@ impl HostDirectoryEntryStream for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result, FsError> { - record_host_function_call( + self.observe_function_call( "filesystem::types::directory_entry_stream", "read_directory_entry", ); @@ -469,7 +468,7 @@ impl HostDirectoryEntryStream for DurableWorkerCtx { } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("filesystem::types::directory_entry_stream", "drop"); + self.observe_function_call("filesystem::types::directory_entry_stream", "drop"); HostDirectoryEntryStream::drop(&mut self.as_wasi_view(), rep) } } 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 35288a5b4a..45f9a890d3 100644 --- a/golem-worker-executor-base/src/durable_host/golem/mod.rs +++ b/golem-worker-executor-base/src/durable_host/golem/mod.rs @@ -25,9 +25,8 @@ use wasmtime_wasi::WasiView; use crate::durable_host::serialized::SerializableError; use crate::durable_host::wasm_rpc::UrnExtensions; -use crate::durable_host::{Durability, DurableWorkerCtx}; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx}; use crate::get_oplog_entry; -use crate::metrics::wasm::record_host_function_call; use crate::model::InterruptKind; use crate::preview2::golem; use crate::preview2::golem::api0_2_0::host::{ @@ -36,7 +35,7 @@ use crate::preview2::golem::api0_2_0::host::{ use crate::services::oplog::CommitLevel; use crate::services::HasWorker; use crate::workerctx::{InvocationManagement, StatusManagement, WorkerCtx}; -use golem_common::model::oplog::{OplogEntry, OplogIndex, WrappedFunctionType}; +use golem_common::model::oplog::{DurableFunctionType, OplogEntry, OplogIndex}; use golem_common::model::regions::OplogRegion; use golem_common::model::{ ComponentId, IdempotencyKey, OwnedWorkerId, PromiseId, ScanCursor, WorkerId, @@ -50,7 +49,7 @@ impl HostGetWorkers for DurableWorkerCtx { filter: Option, precise: bool, ) -> anyhow::Result> { - record_host_function_call("golem::api::get-workers", "new"); + self.observe_function_call("golem::api::get-workers", "new"); let entry = GetWorkersEntry::new(component_id.into(), filter.map(|f| f.into()), precise); let resource = self.as_wasi_view().table().push(entry)?; Ok(resource) @@ -60,7 +59,7 @@ impl HostGetWorkers for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result>> { - record_host_function_call("golem::api::get-workers", "get-next"); + self.observe_function_call("golem::api::get-workers", "get-next"); let (component_id, filter, count, precise, cursor) = self .as_wasi_view() .table() @@ -94,7 +93,7 @@ impl HostGetWorkers for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("golem::api::get-workers", "drop"); + self.observe_function_call("golem::api::get-workers", "drop"); self.as_wasi_view().table().delete::(rep)?; Ok(()) } @@ -131,7 +130,7 @@ impl GetWorkersEntry { #[async_trait] impl golem::api0_2_0::host::Host for DurableWorkerCtx { async fn create_promise(&mut self) -> Result { - record_host_function_call("golem::api", "create_promise"); + self.observe_function_call("golem::api", "create_promise"); let oplog_idx = self.get_oplog_index().await?; Ok(self @@ -149,7 +148,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { &mut self, promise_id: golem::api0_2_0::host::PromiseId, ) -> Result, anyhow::Error> { - record_host_function_call("golem::api", "await_promise"); + self.observe_function_call("golem::api", "await_promise"); let promise_id: PromiseId = promise_id.into(); match self .public_state @@ -170,11 +169,11 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { promise_id: golem::api0_2_0::host::PromiseId, data: Vec, ) -> Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "", // TODO: fix in 2.0 "golem_complete_promise", - WrappedFunctionType::WriteLocal, + DurableFunctionType::WriteLocal, ) .await?; @@ -197,11 +196,11 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { &mut self, promise_id: golem::api0_2_0::host::PromiseId, ) -> Result<(), anyhow::Error> { - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "", // TODO: fix in 2.0 "golem_delete_promise", - WrappedFunctionType::WriteLocal, + DurableFunctionType::WriteLocal, ) .await?; @@ -224,7 +223,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { &mut self, function_name: String, ) -> Result { - record_host_function_call("golem::api", "get_self_uri"); + self.observe_function_call("golem::api", "get_self_uri"); let uri = golem_wasm_rpc::golem::rpc::types::Uri::golem_urn( &self.owned_worker_id.worker_id, Some(&function_name), @@ -233,7 +232,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { } async fn get_oplog_index(&mut self) -> anyhow::Result { - record_host_function_call("golem::api", "get_oplog_index"); + self.observe_function_call("golem::api", "get_oplog_index"); if self.state.is_live() { self.state.oplog.add(OplogEntry::nop()).await; Ok(self.state.current_oplog_index().await.into()) @@ -247,7 +246,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { &mut self, oplog_idx: golem::api0_2_0::host::OplogIndex, ) -> anyhow::Result<()> { - record_host_function_call("golem::api", "set_oplog_index"); + self.observe_function_call("golem::api", "set_oplog_index"); let jump_source = self.state.current_oplog_index().await.next(); // index of the Jump instruction that we will add let jump_target = OplogIndex::from_u64(oplog_idx).next(); // we want to jump _after_ reaching the target index if jump_target > jump_source { @@ -289,7 +288,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { } async fn oplog_commit(&mut self, replicas: u8) -> anyhow::Result<()> { - record_host_function_call("golem::api", "oplog_commit"); + self.observe_function_call("golem::api", "oplog_commit"); if self.state.is_live() { let timeout = Duration::from_secs(1); debug!("Worker committing oplog to {replicas} replicas"); @@ -312,7 +311,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { } async fn mark_begin_operation(&mut self) -> anyhow::Result { - record_host_function_call("golem::api", "mark_begin_operation"); + self.observe_function_call("golem::api", "mark_begin_operation"); if self.state.is_live() { self.state @@ -369,7 +368,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { &mut self, begin: golem::api0_2_0::host::OplogIndex, ) -> anyhow::Result<()> { - record_host_function_call("golem::api", "mark_end_operation"); + self.observe_function_call("golem::api", "mark_end_operation"); if self.state.is_live() { self.state .oplog @@ -383,7 +382,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { } async fn get_retry_policy(&mut self) -> anyhow::Result { - record_host_function_call("golem::api", "get_retry_policy"); + self.observe_function_call("golem::api", "get_retry_policy"); match &self.state.overridden_retry_policy { Some(policy) => Ok(policy.into()), None => Ok((&self.state.config.retry).into()), @@ -391,7 +390,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { } async fn set_retry_policy(&mut self, new_retry_policy: RetryPolicy) -> anyhow::Result<()> { - record_host_function_call("golem::api", "set_retry_policy"); + self.observe_function_call("golem::api", "set_retry_policy"); let new_retry_policy: RetryConfig = new_retry_policy.into(); self.state.overridden_retry_policy = Some(new_retry_policy.clone()); @@ -407,15 +406,15 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { } async fn get_oplog_persistence_level(&mut self) -> anyhow::Result { - record_host_function_call("golem::api", "get_oplog_persistence_level"); - Ok(self.state.persistence_level.clone().into()) + self.observe_function_call("golem::api", "get_oplog_persistence_level"); + Ok(self.state.persistence_level.into()) } async fn set_oplog_persistence_level( &mut self, new_persistence_level: PersistenceLevel, ) -> anyhow::Result<()> { - record_host_function_call("golem::api", "set_oplog_persistence_level"); + self.observe_function_call("golem::api", "set_oplog_persistence_level"); // commit all pending entries and change persistence level if self.state.is_live() { self.state.oplog.commit(CommitLevel::DurableOnly).await; @@ -429,22 +428,22 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { } async fn get_idempotence_mode(&mut self) -> anyhow::Result { - record_host_function_call("golem::api", "get_idempotence_mode"); + self.observe_function_call("golem::api", "get_idempotence_mode"); Ok(self.state.assume_idempotence) } async fn set_idempotence_mode(&mut self, idempotent: bool) -> anyhow::Result<()> { - record_host_function_call("golem::api", "set_idempotence_mode"); + self.observe_function_call("golem::api", "set_idempotence_mode"); self.state.assume_idempotence = idempotent; Ok(()) } async fn generate_idempotency_key(&mut self) -> anyhow::Result { - let durability = Durability::::new( + let durability = Durability::<(u64, u64), SerializableError>::new( self, "golem api", "generate_idempotency_key", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -473,11 +472,11 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { target_version: ComponentVersion, mode: UpdateMode, ) -> anyhow::Result<()> { - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem::api", "update-worker", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -506,7 +505,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { } async fn get_self_metadata(&mut self) -> anyhow::Result { - record_host_function_call("golem::api", "get_self_metadata"); + self.observe_function_call("golem::api", "get_self_metadata"); let metadata = self.public_state.worker().get_metadata().await?; Ok(metadata.into()) } @@ -515,7 +514,7 @@ impl golem::api0_2_0::host::Host for DurableWorkerCtx { &mut self, worker_id: golem::api0_2_0::host::WorkerId, ) -> anyhow::Result> { - record_host_function_call("golem::api", "get_worker_metadata"); + self.observe_function_call("golem::api", "get_worker_metadata"); let worker_id: WorkerId = worker_id.into(); let owned_worker_id = OwnedWorkerId::new(&self.owned_worker_id.account_id, &worker_id); let metadata = self.state.worker_service.get(&owned_worker_id).await; diff --git a/golem-worker-executor-base/src/durable_host/golem/v11.rs b/golem-worker-executor-base/src/durable_host/golem/v11.rs index 116430c374..f7971cf027 100644 --- a/golem-worker-executor-base/src/durable_host/golem/v11.rs +++ b/golem-worker-executor-base/src/durable_host/golem/v11.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::model::public_oplog::{ find_component_version_at, get_public_oplog_chunk, search_public_oplog, }; @@ -190,7 +189,7 @@ impl HostGetOplog for DurableWorkerCtx { worker_id: crate::preview2::golem::api1_1_0::oplog::WorkerId, start: crate::preview2::golem::api1_1_0::oplog::OplogIndex, ) -> anyhow::Result> { - record_host_function_call("golem::api::get-oplog", "new"); + self.observe_function_call("golem::api::get-oplog", "new"); let account_id = self.owned_worker_id.account_id(); let worker_id: golem_common::model::WorkerId = worker_id.into(); @@ -209,7 +208,7 @@ impl HostGetOplog for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result>> { - record_host_function_call("golem::api::get-oplog", "get-next"); + self.observe_function_call("golem::api::get-oplog", "get-next"); let component_service = self.state.component_service.clone(); let oplog_service = self.state.oplog_service(); @@ -247,7 +246,7 @@ impl HostGetOplog for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("golem::api::get-oplog", "drop"); + self.observe_function_call("golem::api::get-oplog", "drop"); self.as_wasi_view().table().delete(rep)?; Ok(()) } @@ -293,7 +292,7 @@ impl HostSearchOplog for DurableWorkerCtx { worker_id: golem::api1_1_0::oplog::WorkerId, text: String, ) -> anyhow::Result> { - record_host_function_call("golem::api::search-oplog", "new"); + self.observe_function_call("golem::api::search-oplog", "new"); let account_id = self.owned_worker_id.account_id(); let worker_id: golem_common::model::WorkerId = worker_id.into(); @@ -313,7 +312,7 @@ impl HostSearchOplog for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result>> { - record_host_function_call("golem::api::search-oplog", "get-next"); + self.observe_function_call("golem::api::search-oplog", "get-next"); let component_service = self.state.component_service.clone(); let oplog_service = self.state.oplog_service(); @@ -356,7 +355,7 @@ impl HostSearchOplog for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("golem::api::search-oplog", "drop"); + self.observe_function_call("golem::api::search-oplog", "drop"); self.as_wasi_view().table().delete(rep)?; Ok(()) } diff --git a/golem-worker-executor-base/src/durable_host/http/mod.rs b/golem-worker-executor-base/src/durable_host/http/mod.rs index b417460c81..6cc0a7e4c0 100644 --- a/golem-worker-executor-base/src/durable_host/http/mod.rs +++ b/golem-worker-executor-base/src/durable_host/http/mod.rs @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::durable_host::{DurableWorkerCtx, HttpRequestCloseOwner}; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx, HttpRequestCloseOwner}; use crate::error::GolemError; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use tracing::warn; pub mod outgoing_http; @@ -32,9 +32,11 @@ pub(crate) async fn end_http_request( if let Some(state) = ctx.state.open_http_requests.remove(¤t_handle) { match ctx.state.open_function_table.get(&state.root_handle) { Some(begin_index) => { - ctx.state - .end_function(&WrappedFunctionType::WriteRemoteBatched(None), *begin_index) - .await?; + ctx.end_durable_function( + &DurableFunctionType::WriteRemoteBatched(None), + *begin_index, + ) + .await?; ctx.state.open_function_table.remove(&state.root_handle); } None => { diff --git a/golem-worker-executor-base/src/durable_host/http/outgoing_http.rs b/golem-worker-executor-base/src/durable_host/http/outgoing_http.rs index 42d6e6a6a9..175d1d0471 100644 --- a/golem-worker-executor-base/src/durable_host/http/outgoing_http.rs +++ b/golem-worker-executor-base/src/durable_host/http/outgoing_http.rs @@ -21,11 +21,12 @@ use wasmtime_wasi_http::bindings::wasi::http::outgoing_handler::Host; use wasmtime_wasi_http::types::{HostFutureIncomingResponse, HostOutgoingRequest}; use wasmtime_wasi_http::{HttpError, HttpResult}; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use crate::durable_host::http::serialized::SerializableHttpRequest; -use crate::durable_host::{DurableWorkerCtx, HttpRequestCloseOwner, HttpRequestState}; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{ + DurabilityHost, DurableWorkerCtx, HttpRequestCloseOwner, HttpRequestState, +}; use crate::workerctx::WorkerCtx; #[async_trait] @@ -35,12 +36,11 @@ impl Host for DurableWorkerCtx { request: Resource, options: Option>, ) -> HttpResult> { - record_host_function_call("http::outgoing_handler", "handle"); + self.observe_function_call("http::outgoing_handler", "handle"); // Durability is handled by the WasiHttpView send_request method and the follow-up calls to await/poll the response future let begin_index = self - .state - .begin_function(&WrappedFunctionType::WriteRemoteBatched(None)) + .begin_durable_function(&DurableFunctionType::WriteRemoteBatched(None)) .await .map_err(|err| HttpError::trap(anyhow!(err)))?; @@ -89,10 +89,12 @@ impl Host for DurableWorkerCtx { ); } Err(_) => { - self.state - .end_function(&WrappedFunctionType::WriteRemoteBatched(None), begin_index) - .await - .map_err(|err| HttpError::trap(anyhow!(err)))?; + self.end_durable_function( + &DurableFunctionType::WriteRemoteBatched(None), + begin_index, + ) + .await + .map_err(|err| HttpError::trap(anyhow!(err)))?; } } 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 45f0865392..1ca6d2e0ef 100644 --- a/golem-worker-executor-base/src/durable_host/http/types.rs +++ b/golem-worker-executor-base/src/durable_host/http/types.rs @@ -32,23 +32,22 @@ use wasmtime_wasi_http::get_fields; use wasmtime_wasi_http::types::FieldMap; use wasmtime_wasi_http::{HttpError, HttpResult}; -use golem_common::model::oplog::{OplogEntry, WrappedFunctionType}; +use golem_common::model::oplog::{DurableFunctionType, OplogEntry}; use crate::durable_host::http::serialized::{ SerializableErrorCode, SerializableResponse, SerializableResponseHeaders, }; use crate::durable_host::http::{continue_http_request, end_http_request}; use crate::durable_host::serialized::SerializableError; -use crate::durable_host::{Durability, DurableWorkerCtx, HttpRequestCloseOwner}; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx, HttpRequestCloseOwner}; use crate::get_oplog_entry; -use crate::metrics::wasm::record_host_function_call; use crate::model::PersistenceLevel; use crate::services::oplog::{CommitLevel, OplogOps}; use crate::workerctx::WorkerCtx; impl HostFields for DurableWorkerCtx { fn new(&mut self) -> anyhow::Result> { - record_host_function_call("http::types::fields", "new"); + self.observe_function_call("http::types::fields", "new"); HostFields::new(&mut self.as_wasi_http_view()) } @@ -56,17 +55,17 @@ impl HostFields for DurableWorkerCtx { &mut self, entries: Vec<(FieldKey, FieldValue)>, ) -> anyhow::Result, HeaderError>> { - record_host_function_call("http::types::fields", "from_list"); + self.observe_function_call("http::types::fields", "from_list"); HostFields::from_list(&mut self.as_wasi_http_view(), entries) } fn get(&mut self, self_: Resource, name: FieldKey) -> anyhow::Result> { - record_host_function_call("http::types::fields", "get"); + self.observe_function_call("http::types::fields", "get"); HostFields::get(&mut self.as_wasi_http_view(), self_, name) } fn has(&mut self, self_: Resource, name: FieldKey) -> anyhow::Result { - record_host_function_call("http::types::fields", "has"); + self.observe_function_call("http::types::fields", "has"); HostFields::has(&mut self.as_wasi_http_view(), self_, name) } @@ -76,7 +75,7 @@ impl HostFields for DurableWorkerCtx { name: FieldKey, value: Vec, ) -> anyhow::Result> { - record_host_function_call("http::types::fields", "set"); + self.observe_function_call("http::types::fields", "set"); HostFields::set(&mut self.as_wasi_http_view(), self_, name, value) } @@ -85,7 +84,7 @@ impl HostFields for DurableWorkerCtx { self_: Resource, name: FieldKey, ) -> anyhow::Result> { - record_host_function_call("http::types::fields", "delete"); + self.observe_function_call("http::types::fields", "delete"); HostFields::delete(&mut self.as_wasi_http_view(), self_, name) } @@ -95,29 +94,29 @@ impl HostFields for DurableWorkerCtx { name: FieldKey, value: FieldValue, ) -> anyhow::Result> { - record_host_function_call("http::types::fields", "append"); + self.observe_function_call("http::types::fields", "append"); HostFields::append(&mut self.as_wasi_http_view(), self_, name, value) } fn entries(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::fields", "entries"); + self.observe_function_call("http::types::fields", "entries"); HostFields::entries(&mut self.as_wasi_http_view(), self_) } fn clone(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::fields", "clone"); + self.observe_function_call("http::types::fields", "clone"); HostFields::clone(&mut self.as_wasi_http_view(), self_) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::fields", "drop"); + self.observe_function_call("http::types::fields", "drop"); HostFields::drop(&mut self.as_wasi_http_view(), rep) } } impl HostIncomingRequest for DurableWorkerCtx { fn method(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("http::types::incoming_request", "method"); + self.observe_function_call("http::types::incoming_request", "method"); HostIncomingRequest::method(&mut self.as_wasi_http_view(), self_) } @@ -125,22 +124,22 @@ impl HostIncomingRequest for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call("http::types::incoming_request", "path_with_query"); + self.observe_function_call("http::types::incoming_request", "path_with_query"); HostIncomingRequest::path_with_query(&mut self.as_wasi_http_view(), self_) } fn scheme(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::incoming_request", "scheme"); + self.observe_function_call("http::types::incoming_request", "scheme"); HostIncomingRequest::scheme(&mut self.as_wasi_http_view(), self_) } fn authority(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::incoming_request", "authority"); + self.observe_function_call("http::types::incoming_request", "authority"); HostIncomingRequest::authority(&mut self.as_wasi_http_view(), self_) } fn headers(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::incoming_request", "headers"); + self.observe_function_call("http::types::incoming_request", "headers"); HostIncomingRequest::headers(&mut self.as_wasi_http_view(), self_) } @@ -148,19 +147,19 @@ impl HostIncomingRequest for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, ()>> { - record_host_function_call("http::types::incoming_request", "consume"); + self.observe_function_call("http::types::incoming_request", "consume"); HostIncomingRequest::consume(&mut self.as_wasi_http_view(), self_) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::incoming_request", "drop"); + self.observe_function_call("http::types::incoming_request", "drop"); HostIncomingRequest::drop(&mut self.as_wasi_http_view(), rep) } } impl HostOutgoingRequest for DurableWorkerCtx { fn new(&mut self, headers: Resource) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "new"); + self.observe_function_call("http::types::outgoing_request", "new"); HostOutgoingRequest::new(&mut self.as_wasi_http_view(), headers) } @@ -168,12 +167,12 @@ impl HostOutgoingRequest for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, ()>> { - record_host_function_call("http::types::outgoing_request", "body"); + self.observe_function_call("http::types::outgoing_request", "body"); HostOutgoingRequest::body(&mut self.as_wasi_http_view(), self_) } fn method(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("http::types::outgoing_request", "method"); + self.observe_function_call("http::types::outgoing_request", "method"); HostOutgoingRequest::method(&mut self.as_wasi_http_view(), self_) } @@ -182,7 +181,7 @@ impl HostOutgoingRequest for DurableWorkerCtx { self_: Resource, method: Method, ) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "set_method"); + self.observe_function_call("http::types::outgoing_request", "set_method"); HostOutgoingRequest::set_method(&mut self.as_wasi_http_view(), self_, method) } @@ -190,7 +189,7 @@ impl HostOutgoingRequest for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "path_with_query"); + self.observe_function_call("http::types::outgoing_request", "path_with_query"); HostOutgoingRequest::path_with_query(&mut self.as_wasi_http_view(), self_) } @@ -199,7 +198,7 @@ impl HostOutgoingRequest for DurableWorkerCtx { self_: Resource, path_with_query: Option, ) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "set_path_with_query"); + self.observe_function_call("http::types::outgoing_request", "set_path_with_query"); HostOutgoingRequest::set_path_with_query( &mut self.as_wasi_http_view(), self_, @@ -208,7 +207,7 @@ impl HostOutgoingRequest for DurableWorkerCtx { } fn scheme(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "scheme"); + self.observe_function_call("http::types::outgoing_request", "scheme"); HostOutgoingRequest::scheme(&mut self.as_wasi_http_view(), self_) } @@ -217,12 +216,12 @@ impl HostOutgoingRequest for DurableWorkerCtx { self_: Resource, scheme: Option, ) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "set_scheme"); + self.observe_function_call("http::types::outgoing_request", "set_scheme"); HostOutgoingRequest::set_scheme(&mut self.as_wasi_http_view(), self_, scheme) } fn authority(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "authority"); + self.observe_function_call("http::types::outgoing_request", "authority"); HostOutgoingRequest::authority(&mut self.as_wasi_http_view(), self_) } @@ -231,17 +230,17 @@ impl HostOutgoingRequest for DurableWorkerCtx { self_: Resource, authority: Option, ) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "set_authority"); + self.observe_function_call("http::types::outgoing_request", "set_authority"); HostOutgoingRequest::set_authority(&mut self.as_wasi_http_view(), self_, authority) } fn headers(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_request", "headers"); + self.observe_function_call("http::types::outgoing_request", "headers"); HostOutgoingRequest::headers(&mut self.as_wasi_http_view(), self_) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::outgoing_request", "drop"); + self.observe_function_call("http::types::outgoing_request", "drop"); HostOutgoingRequest::drop(&mut self.as_wasi_http_view(), rep) } } @@ -249,7 +248,7 @@ impl HostOutgoingRequest for DurableWorkerCtx { #[async_trait] impl HostRequestOptions for DurableWorkerCtx { fn new(&mut self) -> anyhow::Result> { - record_host_function_call("http::types::request_options", "new"); + self.observe_function_call("http::types::request_options", "new"); HostRequestOptions::new(&mut self.as_wasi_http_view()) } @@ -257,7 +256,7 @@ impl HostRequestOptions for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call("http::types::request_options", "connect_timeout_ms"); + self.observe_function_call("http::types::request_options", "connect_timeout_ms"); HostRequestOptions::connect_timeout(&mut self.as_wasi_http_view(), self_) } @@ -266,7 +265,7 @@ impl HostRequestOptions for DurableWorkerCtx { self_: Resource, ms: Option, ) -> anyhow::Result> { - record_host_function_call("http::types::request_options", "set_connect_timeout_ms"); + self.observe_function_call("http::types::request_options", "set_connect_timeout_ms"); HostRequestOptions::set_connect_timeout(&mut self.as_wasi_http_view(), self_, ms) } @@ -274,7 +273,7 @@ impl HostRequestOptions for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call("http::types::request_options", "first_byte_timeout_ms"); + self.observe_function_call("http::types::request_options", "first_byte_timeout_ms"); HostRequestOptions::first_byte_timeout(&mut self.as_wasi_http_view(), self_) } @@ -283,7 +282,7 @@ impl HostRequestOptions for DurableWorkerCtx { self_: Resource, ms: Option, ) -> anyhow::Result> { - record_host_function_call("http::types::request_options", "set_first_byte_timeout_ms"); + self.observe_function_call("http::types::request_options", "set_first_byte_timeout_ms"); HostRequestOptions::set_first_byte_timeout(&mut self.as_wasi_http_view(), self_, ms) } @@ -291,7 +290,7 @@ impl HostRequestOptions for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call("http::types::request_options", "between_bytes_timeout_ms"); + self.observe_function_call("http::types::request_options", "between_bytes_timeout_ms"); HostRequestOptions::between_bytes_timeout(&mut self.as_wasi_http_view(), self_) } @@ -300,7 +299,7 @@ impl HostRequestOptions for DurableWorkerCtx { self_: Resource, ms: Option, ) -> anyhow::Result> { - record_host_function_call( + self.observe_function_call( "http::types::request_options", "set_between_bytes_timeout_ms", ); @@ -308,7 +307,7 @@ impl HostRequestOptions for DurableWorkerCtx { } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::request_options", "drop"); + self.observe_function_call("http::types::request_options", "drop"); HostRequestOptions::drop(&mut self.as_wasi_http_view(), rep) } } @@ -320,12 +319,12 @@ impl HostResponseOutparam for DurableWorkerCtx { param: Resource, response: Result, ErrorCode>, ) -> anyhow::Result<()> { - record_host_function_call("http::types::response_outparam", "set"); + self.observe_function_call("http::types::response_outparam", "set"); HostResponseOutparam::set(&mut self.as_wasi_http_view(), param, response) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::response_outparam", "drop"); + self.observe_function_call("http::types::response_outparam", "drop"); HostResponseOutparam::drop(&mut self.as_wasi_http_view(), rep) } } @@ -333,12 +332,12 @@ impl HostResponseOutparam for DurableWorkerCtx { #[async_trait] impl HostIncomingResponse for DurableWorkerCtx { fn status(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("http::types::incoming_response", "status"); + self.observe_function_call("http::types::incoming_response", "status"); HostIncomingResponse::status(&mut self.as_wasi_http_view(), self_) } fn headers(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::incoming_response", "headers"); + self.observe_function_call("http::types::incoming_response", "headers"); HostIncomingResponse::headers(&mut self.as_wasi_http_view(), self_) } @@ -346,7 +345,7 @@ impl HostIncomingResponse for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, ()>> { - record_host_function_call("http::types::incoming_response", "consume"); + self.observe_function_call("http::types::incoming_response", "consume"); let handle = self_.rep(); let result = HostIncomingResponse::consume(&mut self.as_wasi_http_view(), self_); @@ -364,7 +363,7 @@ impl HostIncomingResponse for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::incoming_response", "drop"); + self.observe_function_call("http::types::incoming_response", "drop"); let handle = rep.rep(); if let Some(state) = self.state.open_http_requests.get(&handle) { @@ -383,7 +382,7 @@ impl HostIncomingBody for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, ()>> { - record_host_function_call("http::types::incoming_body", "stream"); + self.observe_function_call("http::types::incoming_body", "stream"); let handle = self_.rep(); let result = HostIncomingBody::stream(&mut self.as_wasi_http_view(), self_); @@ -405,7 +404,7 @@ impl HostIncomingBody for DurableWorkerCtx { &mut self, this: Resource, ) -> anyhow::Result> { - record_host_function_call("http::types::incoming_body", "finish"); + self.observe_function_call("http::types::incoming_body", "finish"); let handle = this.rep(); if let Some(state) = self.state.open_http_requests.get(&handle) { @@ -418,7 +417,7 @@ impl HostIncomingBody for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::incoming_body", "drop"); + self.observe_function_call("http::types::incoming_body", "drop"); let handle = rep.rep(); if let Some(state) = self.state.open_http_requests.get(&handle) { @@ -434,7 +433,7 @@ impl HostIncomingBody for DurableWorkerCtx { #[async_trait] impl HostFutureTrailers for DurableWorkerCtx { fn subscribe(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::future_trailers", "subscribe"); + self.observe_function_call("http::types::future_trailers", "subscribe"); HostFutureTrailers::subscribe(&mut self.as_wasi_http_view(), self_) } @@ -442,7 +441,7 @@ impl HostFutureTrailers for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result>, ErrorCode>, ()>>> { - record_host_function_call("http::types::future_trailers", "get"); + self.observe_function_call("http::types::future_trailers", "get"); let request_state = self .state @@ -461,14 +460,13 @@ impl HostFutureTrailers for DurableWorkerCtx { let request = request_state.request.clone(); let durability = Durability::< - Ctx, Option>>, SerializableErrorCode>, ()>>, SerializableError, >::new( self, "golem http::types::future_trailers", "get", - WrappedFunctionType::WriteRemoteBatched(Some(*begin_idx)), + DurableFunctionType::WriteRemoteBatched(Some(*begin_idx)), ) .await?; @@ -519,7 +517,7 @@ impl HostFutureTrailers for DurableWorkerCtx { } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::future_trailers", "drop"); + self.observe_function_call("http::types::future_trailers", "drop"); HostFutureTrailers::drop(&mut self.as_wasi_http_view(), rep) } } @@ -527,12 +525,12 @@ impl HostFutureTrailers for DurableWorkerCtx { #[async_trait] impl HostOutgoingResponse for DurableWorkerCtx { fn new(&mut self, headers: Resource) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_response", "new"); + self.observe_function_call("http::types::outgoing_response", "new"); HostOutgoingResponse::new(&mut self.as_wasi_http_view(), headers) } fn status_code(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("http::types::outgoing_response", "status_code"); + self.observe_function_call("http::types::outgoing_response", "status_code"); HostOutgoingResponse::status_code(&mut self.as_wasi_http_view(), self_) } @@ -541,12 +539,12 @@ impl HostOutgoingResponse for DurableWorkerCtx { self_: Resource, status_code: StatusCode, ) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_response", "set_status_code"); + self.observe_function_call("http::types::outgoing_response", "set_status_code"); HostOutgoingResponse::set_status_code(&mut self.as_wasi_http_view(), self_, status_code) } fn headers(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("http::types::outgoing_response", "headers"); + self.observe_function_call("http::types::outgoing_response", "headers"); HostOutgoingResponse::headers(&mut self.as_wasi_http_view(), self_) } @@ -554,12 +552,12 @@ impl HostOutgoingResponse for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, ()>> { - record_host_function_call("http::types::outgoing_response", "body"); + self.observe_function_call("http::types::outgoing_response", "body"); HostOutgoingResponse::body(&mut self.as_wasi_http_view(), self_) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::outgoing_response", "drop"); + self.observe_function_call("http::types::outgoing_response", "drop"); HostOutgoingResponse::drop(&mut self.as_wasi_http_view(), rep) } } @@ -570,7 +568,7 @@ impl HostOutgoingBody for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, ()>> { - record_host_function_call("http::types::outgoing_body", "write"); + self.observe_function_call("http::types::outgoing_body", "write"); HostOutgoingBody::write(&mut self.as_wasi_http_view(), self_) } @@ -579,12 +577,12 @@ impl HostOutgoingBody for DurableWorkerCtx { this: Resource, trailers: Option>, ) -> HttpResult<()> { - record_host_function_call("http::types::outgoing_body", "finish"); + self.observe_function_call("http::types::outgoing_body", "finish"); HostOutgoingBody::finish(&mut self.as_wasi_http_view(), this, trailers) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::outgoing_body", "drop"); + self.observe_function_call("http::types::outgoing_body", "drop"); HostOutgoingBody::drop(&mut self.as_wasi_http_view(), rep) } } @@ -595,7 +593,7 @@ impl HostFutureIncomingResponse for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call("http::types::future_incoming_response", "subscribe"); + self.observe_function_call("http::types::future_incoming_response", "subscribe"); // In replay mode the future is in Deferred state for which the built-in Subscribe implementation immediately returns. // This is exactly what we want for replay mode. In live mode the future is in Pending state until the response is // available, and the returned Pollable will wait for the request task to finish. @@ -606,7 +604,7 @@ impl HostFutureIncomingResponse for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, ErrorCode>, ()>>> { - record_host_function_call("http::types::future_incoming_response", "get"); + self.observe_function_call("http::types::future_incoming_response", "get"); // Each get call is stored in the oplog. If the result was Error or None (future is pending), we just // continue the replay. If the result was Ok, we return register the stored response to the table as a new // HostIncomingResponse and return its reference. @@ -617,7 +615,9 @@ impl HostFutureIncomingResponse for DurableWorkerCtx { // the body is stored in the oplog, so we can replay it later. In replay mode we initialize the body with a // fake stream which can only be read in the oplog, and fails if we try to read it in live mode. let handle = self_.rep(); - if self.state.is_live() || self.state.persistence_level == PersistenceLevel::PersistNothing + let durable_execution_state = self.durable_execution_state(); + if durable_execution_state.is_live + || durable_execution_state.persistence_level == PersistenceLevel::PersistNothing { let request_state = self.state.open_http_requests.get(&handle).ok_or_else(|| { anyhow!("No matching HTTP request is associated with resource handle") @@ -658,7 +658,7 @@ impl HostFutureIncomingResponse for DurableWorkerCtx { "http::types::future_incoming_response::get".to_string(), &request, &serializable_response, - WrappedFunctionType::WriteRemoteBatched(Some(begin_idx)), + DurableFunctionType::WriteRemoteBatched(Some(begin_idx)), ) .await .unwrap_or_else(|err| panic!("failed to serialize http response: {err}")); @@ -722,7 +722,7 @@ impl HostFutureIncomingResponse for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("http::types::future_incoming_response", "drop"); + self.observe_function_call("http::types::future_incoming_response", "drop"); let handle = rep.rep(); if let Some(state) = self.state.open_http_requests.get(&handle) { @@ -737,12 +737,12 @@ impl HostFutureIncomingResponse for DurableWorkerCtx { impl Host for DurableWorkerCtx { fn http_error_code(&mut self, err: Resource) -> anyhow::Result> { - record_host_function_call("http::types", "http_error_code"); + self.observe_function_call("http::types", "http_error_code"); Host::http_error_code(&mut self.as_wasi_http_view(), err) } fn convert_error_code(&mut self, err: HttpError) -> wasmtime::Result { - record_host_function_call("http::types", "convert_error_code"); + self.observe_function_call("http::types", "convert_error_code"); Host::convert_error_code(&mut self.as_wasi_http_view(), err) } } diff --git a/golem-worker-executor-base/src/durable_host/io/error.rs b/golem-worker-executor-base/src/durable_host/io/error.rs index b56d0b8415..cd55d2e17c 100644 --- a/golem-worker-executor-base/src/durable_host/io/error.rs +++ b/golem-worker-executor-base/src/durable_host/io/error.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use async_trait::async_trait; use wasmtime::component::Resource; @@ -22,12 +21,12 @@ use wasmtime_wasi::bindings::io::error::{Error, Host, HostError}; #[async_trait] impl HostError for DurableWorkerCtx { fn to_debug_string(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("io::error", "to_debug_string"); + self.observe_function_call("io::error", "to_debug_string"); HostError::to_debug_string(&mut self.as_wasi_view(), self_) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("io::error", "drop"); + self.observe_function_call("io::error", "drop"); HostError::drop(&mut self.as_wasi_view(), rep) } } diff --git a/golem-worker-executor-base/src/durable_host/io/poll.rs b/golem-worker-executor-base/src/durable_host/io/poll.rs index f12a1cb030..cf14dfbf17 100644 --- a/golem-worker-executor-base/src/durable_host/io/poll.rs +++ b/golem-worker-executor-base/src/durable_host/io/poll.rs @@ -15,24 +15,23 @@ use crate::model::InterruptKind; use async_trait::async_trait; use chrono::{Duration, Utc}; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::bindings::io::poll::{Host, HostPollable, Pollable}; use crate::durable_host::serialized::SerializableError; -use crate::durable_host::{Durability, DurableWorkerCtx, SuspendForSleep}; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx, SuspendForSleep}; use crate::workerctx::WorkerCtx; #[async_trait] impl HostPollable for DurableWorkerCtx { async fn ready(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("io::poll:pollable", "ready"); + self.observe_function_call("io::poll:pollable", "ready"); HostPollable::ready(&mut self.as_wasi_view(), self_).await } async fn block(&mut self, self_: Resource) -> anyhow::Result<()> { - record_host_function_call("io::poll:pollable", "block"); + self.observe_function_call("io::poll:pollable", "block"); let in_ = vec![self_]; let _ = self.poll(in_).await?; @@ -40,7 +39,7 @@ impl HostPollable for DurableWorkerCtx { } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("io::poll:pollable", "drop"); + self.observe_function_call("io::poll:pollable", "drop"); HostPollable::drop(&mut self.as_wasi_view(), rep) } } @@ -48,11 +47,11 @@ impl HostPollable for DurableWorkerCtx { #[async_trait] impl Host for DurableWorkerCtx { async fn poll(&mut self, in_: Vec>) -> anyhow::Result> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem io::poll", "poll", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; 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 fd13adc659..fe3b45de57 100644 --- a/golem-worker-executor-base/src/durable_host/io/streams.rs +++ b/golem-worker-executor-base/src/durable_host/io/streams.rs @@ -21,11 +21,10 @@ use crate::durable_host::http::end_http_request; use crate::durable_host::http::serialized::SerializableHttpRequest; use crate::durable_host::io::{ManagedStdErr, ManagedStdOut}; use crate::durable_host::serialized::SerializableStreamError; -use crate::durable_host::{Durability, DurableWorkerCtx, HttpRequestCloseOwner}; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx, HttpRequestCloseOwner}; use crate::error::GolemError; -use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::{OplogIndex, WrappedFunctionType}; +use golem_common::model::oplog::{DurableFunctionType, OplogIndex}; use golem_common::model::WorkerEvent; use wasmtime_wasi::bindings::io::streams::{ Host, HostInputStream, HostOutputStream, InputStream, OutputStream, Pollable, @@ -43,11 +42,11 @@ impl HostInputStream for DurableWorkerCtx { let handle = self_.rep(); let begin_idx = get_http_request_begin_idx(self, handle)?; - let durability = Durability::, SerializableStreamError>::new( + let durability = Durability::, SerializableStreamError>::new( self, "http::types::incoming_body_stream", "read", - WrappedFunctionType::WriteRemoteBatched(Some(begin_idx)), + DurableFunctionType::WriteRemoteBatched(Some(begin_idx)), ) .await?; @@ -62,7 +61,7 @@ impl HostInputStream for DurableWorkerCtx { end_http_request_if_closed(self, handle, &result).await?; result } else { - record_host_function_call("io::streams::input_stream", "read"); + self.observe_function_call("io::streams::input_stream", "read"); HostInputStream::read(&mut self.as_wasi_view(), self_, len).await } } @@ -76,11 +75,11 @@ impl HostInputStream for DurableWorkerCtx { let handle = self_.rep(); let begin_idx = get_http_request_begin_idx(self, handle)?; - let durability = Durability::, SerializableStreamError>::new( + let durability = Durability::, SerializableStreamError>::new( self, "http::types::incoming_body_stream", "blocking_read", - WrappedFunctionType::WriteRemoteBatched(Some(begin_idx)), + DurableFunctionType::WriteRemoteBatched(Some(begin_idx)), ) .await?; let result = if durability.is_live() { @@ -95,7 +94,7 @@ impl HostInputStream for DurableWorkerCtx { end_http_request_if_closed(self, handle, &result).await?; result } else { - record_host_function_call("io::streams::input_stream", "blocking_read"); + self.observe_function_call("io::streams::input_stream", "blocking_read"); HostInputStream::blocking_read(&mut self.as_wasi_view(), self_, len).await } } @@ -105,11 +104,11 @@ impl HostInputStream for DurableWorkerCtx { let handle = self_.rep(); let begin_idx = get_http_request_begin_idx(self, handle)?; - let durability = Durability::::new( + let durability = Durability::::new( self, "http::types::incoming_body_stream", "skip", - WrappedFunctionType::WriteRemoteBatched(Some(begin_idx)), + DurableFunctionType::WriteRemoteBatched(Some(begin_idx)), ) .await?; let result = if durability.is_live() { @@ -123,7 +122,7 @@ impl HostInputStream for DurableWorkerCtx { end_http_request_if_closed(self, handle, &result).await?; result } else { - record_host_function_call("io::streams::input_stream", "skip"); + self.observe_function_call("io::streams::input_stream", "skip"); HostInputStream::skip(&mut self.as_wasi_view(), self_, len).await } } @@ -137,11 +136,11 @@ impl HostInputStream for DurableWorkerCtx { let handle = self_.rep(); let begin_idx = get_http_request_begin_idx(self, handle)?; - let durability = Durability::::new( + let durability = Durability::::new( self, "http::types::incoming_body_stream", "blocking_skip", - WrappedFunctionType::WriteRemoteBatched(Some(begin_idx)), + DurableFunctionType::WriteRemoteBatched(Some(begin_idx)), ) .await?; @@ -156,18 +155,18 @@ impl HostInputStream for DurableWorkerCtx { end_http_request_if_closed(self, handle, &result).await?; result } else { - record_host_function_call("io::streams::input_stream", "blocking_skip"); + self.observe_function_call("io::streams::input_stream", "blocking_skip"); HostInputStream::blocking_skip(&mut self.as_wasi_view(), self_, len).await } } fn subscribe(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("io::streams::input_stream", "subscribe"); + self.observe_function_call("io::streams::input_stream", "subscribe"); HostInputStream::subscribe(&mut self.as_wasi_view(), self_) } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("io::streams::input_stream", "drop"); + self.observe_function_call("io::streams::input_stream", "drop"); if is_incoming_http_body_stream(self.table(), &rep) { let handle = rep.rep(); @@ -185,7 +184,7 @@ impl HostInputStream for DurableWorkerCtx { #[async_trait] impl HostOutputStream for DurableWorkerCtx { fn check_write(&mut self, self_: Resource) -> Result { - record_host_function_call("io::streams::output_stream", "check_write"); + self.observe_function_call("io::streams::output_stream", "check_write"); HostOutputStream::check_write(&mut self.as_wasi_view(), self_) } @@ -194,7 +193,7 @@ impl HostOutputStream for DurableWorkerCtx { self_: Resource, contents: Vec, ) -> Result<(), StreamError> { - record_host_function_call("io::streams::output_stream", "write"); + self.observe_function_call("io::streams::output_stream", "write"); let output = self.table().get(&self_)?; let event = if output.as_any().downcast_ref::().is_some() { @@ -226,17 +225,17 @@ impl HostOutputStream for DurableWorkerCtx { } async fn flush(&mut self, self_: Resource) -> Result<(), StreamError> { - record_host_function_call("io::streams::output_stream", "flush"); + self.observe_function_call("io::streams::output_stream", "flush"); HostOutputStream::flush(&mut self.as_wasi_view(), self_).await } async fn blocking_flush(&mut self, self_: Resource) -> Result<(), StreamError> { - record_host_function_call("io::streams::output_stream", "blocking_flush"); + self.observe_function_call("io::streams::output_stream", "blocking_flush"); HostOutputStream::blocking_flush(&mut self.as_wasi_view(), self_).await } fn subscribe(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("io::streams::output_stream", "subscribe"); + self.observe_function_call("io::streams::output_stream", "subscribe"); HostOutputStream::subscribe(&mut self.as_wasi_view(), self_) } @@ -245,7 +244,7 @@ impl HostOutputStream for DurableWorkerCtx { self_: Resource, len: u64, ) -> Result<(), StreamError> { - record_host_function_call("io::streams::output_stream", "write_zeroeas"); + self.observe_function_call("io::streams::output_stream", "write_zeroeas"); HostOutputStream::write_zeroes(&mut self.as_wasi_view(), self_, len).await } @@ -254,7 +253,7 @@ impl HostOutputStream for DurableWorkerCtx { self_: Resource, len: u64, ) -> Result<(), StreamError> { - record_host_function_call( + self.observe_function_call( "io::streams::output_stream", "blocking_write_zeroes_and_flush", ); @@ -268,7 +267,7 @@ impl HostOutputStream for DurableWorkerCtx { src: Resource, len: u64, ) -> Result { - record_host_function_call("io::streams::output_stream", "splice"); + self.observe_function_call("io::streams::output_stream", "splice"); HostOutputStream::splice(&mut self.as_wasi_view(), self_, src, len).await } @@ -278,12 +277,12 @@ impl HostOutputStream for DurableWorkerCtx { src: Resource, len: u64, ) -> Result { - record_host_function_call("io::streams::output_stream", "blocking_splice"); + self.observe_function_call("io::streams::output_stream", "blocking_splice"); HostOutputStream::blocking_splice(&mut self.as_wasi_view(), self_, src, len).await } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("io::streams::output_stream", "drop"); + self.observe_function_call("io::streams::output_stream", "drop"); HostOutputStream::drop(&mut self.as_wasi_view(), rep).await } } diff --git a/golem-worker-executor-base/src/durable_host/keyvalue/atomic.rs b/golem-worker-executor-base/src/durable_host/keyvalue/atomic.rs index 2e4b7c56f6..6bb82ec4d6 100644 --- a/golem-worker-executor-base/src/durable_host/keyvalue/atomic.rs +++ b/golem-worker-executor-base/src/durable_host/keyvalue/atomic.rs @@ -15,8 +15,7 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::preview2::wasi::keyvalue::atomic::{Bucket, Error, Host, Key}; use crate::workerctx::WorkerCtx; @@ -28,7 +27,7 @@ impl Host for DurableWorkerCtx { _key: Key, _delta: u64, ) -> anyhow::Result>> { - record_host_function_call("keyvalue::atomic", "increment"); + self.observe_function_call("keyvalue::atomic", "increment"); unimplemented!("increment") } @@ -39,7 +38,7 @@ impl Host for DurableWorkerCtx { _old: u64, _new: u64, ) -> anyhow::Result>> { - record_host_function_call("keyvalue::atomic", "compare_and_swap"); + self.observe_function_call("keyvalue::atomic", "compare_and_swap"); unimplemented!("compare_and_swap") } } diff --git a/golem-worker-executor-base/src/durable_host/keyvalue/caching.rs b/golem-worker-executor-base/src/durable_host/keyvalue/caching.rs index 5abbc7fcc8..b14378ece7 100644 --- a/golem-worker-executor-base/src/durable_host/keyvalue/caching.rs +++ b/golem-worker-executor-base/src/durable_host/keyvalue/caching.rs @@ -15,8 +15,7 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::preview2::wasi::keyvalue::cache::{ Error, FutureExistsResult, FutureGetOrSetResult, FutureGetResult, FutureResult, GetOrSetEntry, Host, HostFutureExistsResult, HostFutureGetOrSetResult, HostFutureGetResult, HostFutureResult, @@ -30,7 +29,7 @@ impl HostFutureGetResult for DurableWorkerCtx { &mut self, _self_: Resource, ) -> anyhow::Result>, Resource>>> { - record_host_function_call("keyvalue::cache::future_get", "future_get_result_get"); + self.observe_function_call("keyvalue::cache::future_get", "future_get_result_get"); unimplemented!("future_get_result_get") } @@ -38,12 +37,12 @@ impl HostFutureGetResult for DurableWorkerCtx { &mut self, _self_: Resource, ) -> anyhow::Result> { - record_host_function_call("keyvalue::cache::future_get", "listen_to_future_get_result"); + self.observe_function_call("keyvalue::cache::future_get", "listen_to_future_get_result"); unimplemented!("listen_to_future_get_result") } async fn drop(&mut self, _rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::cache::future_get", "drop"); + self.observe_function_call("keyvalue::cache::future_get", "drop"); unimplemented!("drop") } } @@ -54,7 +53,7 @@ impl HostFutureExistsResult for DurableWorkerCtx { &mut self, _self_: Resource, ) -> anyhow::Result>>> { - record_host_function_call("keyvalue::cache::future_exists", "future_exists_result_get"); + self.observe_function_call("keyvalue::cache::future_exists", "future_exists_result_get"); unimplemented!("future_exists_result_get") } @@ -62,7 +61,7 @@ impl HostFutureExistsResult for DurableWorkerCtx { &mut self, _self_: Resource, ) -> anyhow::Result> { - record_host_function_call( + self.observe_function_call( "keyvalue::cache::future_exists", "listen_to_future_exists_result", ); @@ -70,7 +69,7 @@ impl HostFutureExistsResult for DurableWorkerCtx { } async fn drop(&mut self, _rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::cache::future_exists", "drop"); + self.observe_function_call("keyvalue::cache::future_exists", "drop"); unimplemented!("drop") } } @@ -81,7 +80,7 @@ impl HostFutureResult for DurableWorkerCtx { &mut self, _self_: Resource, ) -> anyhow::Result>>> { - record_host_function_call("keyvalue::cache::future_result", "future_result_get"); + self.observe_function_call("keyvalue::cache::future_result", "future_result_get"); unimplemented!("future_result_get") } @@ -89,12 +88,12 @@ impl HostFutureResult for DurableWorkerCtx { &mut self, _self_: Resource, ) -> anyhow::Result> { - record_host_function_call("keyvalue::cache::future_result", "listen_to_future_result"); + self.observe_function_call("keyvalue::cache::future_result", "listen_to_future_result"); unimplemented!("listen_to_future_result") } async fn drop(&mut self, _rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::cache::future_result", "drop"); + self.observe_function_call("keyvalue::cache::future_result", "drop"); unimplemented!("drop") } } @@ -105,7 +104,7 @@ impl HostFutureGetOrSetResult for DurableWorkerCtx { &mut self, _self_: Resource, ) -> anyhow::Result>>> { - record_host_function_call( + self.observe_function_call( "keyvalue::cache::future_get_or_set", "future_get_or_set_result_get", ); @@ -116,7 +115,7 @@ impl HostFutureGetOrSetResult for DurableWorkerCtx { &mut self, _self_: Resource, ) -> anyhow::Result> { - record_host_function_call( + self.observe_function_call( "keyvalue::cache::future_get_or_set", "listen_to_future_get_or_set_result", ); @@ -124,7 +123,7 @@ impl HostFutureGetOrSetResult for DurableWorkerCtx { } async fn drop(&mut self, _rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::cache::future_get_or_set", "drop"); + self.observe_function_call("keyvalue::cache::future_get_or_set", "drop"); unimplemented!("drop") } } @@ -136,12 +135,12 @@ impl HostVacancy for DurableWorkerCtx { _self_: Resource, _ttl_ms: Option, ) -> anyhow::Result> { - record_host_function_call("keyvalue::cache::vacancy", "vacancy_fill"); + self.observe_function_call("keyvalue::cache::vacancy", "vacancy_fill"); unimplemented!("vacancy_fill") } async fn drop(&mut self, _rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::cache::vacancy", "drop"); + self.observe_function_call("keyvalue::cache::vacancy", "drop"); unimplemented!("drop") } } @@ -149,12 +148,12 @@ impl HostVacancy for DurableWorkerCtx { #[async_trait] impl Host for DurableWorkerCtx { async fn get(&mut self, _k: Key) -> anyhow::Result> { - record_host_function_call("keyvalue::cache", "get"); + self.observe_function_call("keyvalue::cache", "get"); unimplemented!("get") } async fn exists(&mut self, _k: Key) -> anyhow::Result> { - record_host_function_call("keyvalue::cache", "exists"); + self.observe_function_call("keyvalue::cache", "exists"); unimplemented!("exists") } @@ -164,17 +163,17 @@ impl Host for DurableWorkerCtx { _v: Resource, _ttl_ms: Option, ) -> anyhow::Result> { - record_host_function_call("keyvalue::cache", "set"); + self.observe_function_call("keyvalue::cache", "set"); unimplemented!("set") } async fn get_or_set(&mut self, _k: Key) -> anyhow::Result> { - record_host_function_call("keyvalue::cache", "get_or_set"); + self.observe_function_call("keyvalue::cache", "get_or_set"); unimplemented!("get_or_set") } async fn delete(&mut self, _k: Key) -> anyhow::Result> { - record_host_function_call("keyvalue::cache", "delete"); + self.observe_function_call("keyvalue::cache", "delete"); unimplemented!("delete") } } diff --git a/golem-worker-executor-base/src/durable_host/keyvalue/error.rs b/golem-worker-executor-base/src/durable_host/keyvalue/error.rs index 205387d04a..61f702c5f3 100644 --- a/golem-worker-executor-base/src/durable_host/keyvalue/error.rs +++ b/golem-worker-executor-base/src/durable_host/keyvalue/error.rs @@ -16,15 +16,14 @@ use async_trait::async_trait; use wasmtime::component::Resource; use wasmtime_wasi::WasiView; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::preview2::wasi::keyvalue::wasi_keyvalue_error::{Error, Host, HostError}; use crate::workerctx::WorkerCtx; #[async_trait] impl HostError for DurableWorkerCtx { async fn trace(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("keyvalue::wasi_cloud_error", "trace"); + self.observe_function_call("keyvalue::wasi_cloud_error", "trace"); let trace = self .as_wasi_view() .table() @@ -35,7 +34,7 @@ impl HostError for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::wasi_cloud_error", "drop_error"); + self.observe_function_call("keyvalue::wasi_cloud_error", "drop_error"); self.as_wasi_view().table().delete::(rep)?; Ok(()) } 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 945e6ef10a..642ab049e8 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::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::WasiView; @@ -41,11 +41,11 @@ impl Host for DurableWorkerCtx { .name .clone(); - let durability = Durability::>, SerializableError>::new( + let durability = Durability::>, SerializableError>::new( self, "golem keyvalue::eventual", "get", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; @@ -101,11 +101,11 @@ impl Host for DurableWorkerCtx { .unwrap() .clone(); - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem keyvalue::eventual", "set", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -146,11 +146,11 @@ impl Host for DurableWorkerCtx { .name .clone(); - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem keyvalue::eventual", "delete", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -191,11 +191,11 @@ impl Host for DurableWorkerCtx { .name .clone(); - let durability = Durability::::new( + let durability = Durability::::new( self, "golem keyvalue::eventual", "exists", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; 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 001b6f84a3..69559fc889 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::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime::component::Resource; use wasmtime_wasi::{ResourceTableError, WasiView}; @@ -41,11 +41,11 @@ impl Host for DurableWorkerCtx { .name .clone(); - let durability = Durability::>>, SerializableError>::new( + let durability = Durability::>>, SerializableError>::new( self, "golem keyvalue::eventual_batch", "get_many", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; let result = if durability.is_live() { @@ -101,11 +101,11 @@ impl Host for DurableWorkerCtx { .name .clone(); - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem keyvalue::eventual_batch", "get_keys", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; let keys = if durability.is_live() { @@ -149,11 +149,11 @@ impl Host for DurableWorkerCtx { }) .collect::)>, ResourceTableError>>()?; - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem keyvalue::eventual_batch", "set_many", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; @@ -200,11 +200,11 @@ impl Host for DurableWorkerCtx { .name .clone(); - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem keyvalue::eventual_batch", "delete_many", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; diff --git a/golem-worker-executor-base/src/durable_host/keyvalue/types.rs b/golem-worker-executor-base/src/durable_host/keyvalue/types.rs index 88d2508503..b65a0ca4a9 100644 --- a/golem-worker-executor-base/src/durable_host/keyvalue/types.rs +++ b/golem-worker-executor-base/src/durable_host/keyvalue/types.rs @@ -15,8 +15,7 @@ use std::any::Any; use std::sync::{Arc, RwLock}; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::preview2::wasi::keyvalue::types::{ Error, Host, HostBucket, HostIncomingValue, HostOutgoingValue, IncomingValue, IncomingValueAsyncBody, IncomingValueSyncBody, OutgoingValueBodyAsync, OutgoingValueBodySync, @@ -35,13 +34,13 @@ impl HostBucket for DurableWorkerCtx { &mut self, name: String, ) -> anyhow::Result, Resource>> { - record_host_function_call("keyvalue::types::bucket", "open"); + self.observe_function_call("keyvalue::types::bucket", "open"); let bucket = self.as_wasi_view().table().push(BucketEntry::new(name))?; Ok(Ok(bucket)) } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::types::bucket", "drop"); + self.observe_function_call("keyvalue::types::bucket", "drop"); self.as_wasi_view().table().delete::(rep)?; Ok(()) } @@ -50,7 +49,7 @@ impl HostBucket for DurableWorkerCtx { #[async_trait] impl HostOutgoingValue for DurableWorkerCtx { async fn new_outgoing_value(&mut self) -> anyhow::Result> { - record_host_function_call("keyvalue::types::outgoing_value", "new_outgoing_value"); + self.observe_function_call("keyvalue::types::outgoing_value", "new_outgoing_value"); let outgoing_value = self .as_wasi_view() .table() @@ -62,7 +61,7 @@ impl HostOutgoingValue for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, Resource>> { - record_host_function_call( + self.observe_function_call( "keyvalue::types::outgoing_value", "outgoing_value_write_body_async", ); @@ -82,7 +81,7 @@ impl HostOutgoingValue for DurableWorkerCtx { self_: Resource, value: OutgoingValueBodySync, ) -> anyhow::Result>> { - record_host_function_call( + self.observe_function_call( "keyvalue::types::outgoing_value", "outgoing_value_write_body_sync", ); @@ -97,7 +96,7 @@ impl HostOutgoingValue for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::types::outgoing_value", "drop"); + self.observe_function_call("keyvalue::types::outgoing_value", "drop"); self.as_wasi_view() .table() .delete::(rep)?; @@ -111,7 +110,7 @@ impl HostIncomingValue for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result>> { - record_host_function_call( + self.observe_function_call( "keyvalue::types::incoming_value", "incoming_value_consume_sync", ); @@ -129,7 +128,7 @@ impl HostIncomingValue for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result, Resource>> { - record_host_function_call( + self.observe_function_call( "keyvalue::types::incoming_value", "incoming_value_consume_async", ); @@ -148,7 +147,7 @@ impl HostIncomingValue for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result>> { - record_host_function_call("keyvalue::types::incoming_value", "size"); + self.observe_function_call("keyvalue::types::incoming_value", "size"); let body = self .as_wasi_view() .table() @@ -160,7 +159,7 @@ impl HostIncomingValue for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("keyvalue::types::incoming_value", "drop"); + self.observe_function_call("keyvalue::types::incoming_value", "drop"); self.as_wasi_view() .table() .delete::(rep)?; diff --git a/golem-worker-executor-base/src/durable_host/logging/logging.rs b/golem-worker-executor-base/src/durable_host/logging/logging.rs index bcec436ce6..acc1726a8a 100644 --- a/golem-worker-executor-base/src/durable_host/logging/logging.rs +++ b/golem-worker-executor-base/src/durable_host/logging/logging.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::preview2::wasi::logging::logging::{Host, Level}; use crate::workerctx::WorkerCtx; use async_trait::async_trait; @@ -22,7 +21,7 @@ use golem_common::model::{LogLevel, WorkerEvent}; #[async_trait] impl Host for DurableWorkerCtx { async fn log(&mut self, level: Level, context: String, message: String) -> anyhow::Result<()> { - record_host_function_call("logging::handler", "log"); + self.observe_function_call("logging::handler", "log"); let log_level = match level { Level::Critical => LogLevel::Critical, diff --git a/golem-worker-executor-base/src/durable_host/mod.rs b/golem-worker-executor-base/src/durable_host/mod.rs index 64f9047ee0..14589458d8 100644 --- a/golem-worker-executor-base/src/durable_host/mod.rs +++ b/golem-worker-executor-base/src/durable_host/mod.rs @@ -60,8 +60,8 @@ use futures_util::TryFutureExt; use futures_util::TryStreamExt; use golem_common::model::component::ComponentOwner; use golem_common::model::oplog::{ - IndexedResourceKey, LogLevel, OplogEntry, OplogIndex, UpdateDescription, WorkerError, - WorkerResourceId, WrappedFunctionType, + DurableFunctionType, IndexedResourceKey, LogLevel, OplogEntry, OplogIndex, UpdateDescription, + WorkerError, WorkerResourceId, }; use golem_common::model::plugin::{PluginOwner, PluginScope}; use golem_common::model::regions::{DeletedRegions, OplogRegion}; @@ -480,11 +480,11 @@ impl DurableWorkerCtx { match remote_worker_id.clone().try_into_worker_id() { Some(worker_id) => Ok(worker_id), None => { - let durability = Durability::::new( + let durability = Durability::::new( self, "golem::rpc::wasm-rpc", "generate_unique_local_worker_id", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; let worker_id = if durability.is_live() { @@ -1069,7 +1069,7 @@ impl UpdateManagement for DurableWorkerCtx { // While calling a snapshotting function (load/save), we completely turn off persistence // In addition to the user-controllable persistence level we also skip writing the // oplog entries marking the exported function call. - let previous_level = self.state.persistence_level.clone(); + let previous_level = self.state.persistence_level; self.state.snapshotting_mode = Some(previous_level); self.state.persistence_level = PersistenceLevel::PersistNothing; } @@ -1884,14 +1884,13 @@ impl PrivateDurableWorkerState Result { if self.persistence_level != PersistenceLevel::PersistNothing - && ((*wrapped_function_type == WrappedFunctionType::WriteRemote - && !self.assume_idempotence) + && ((*function_type == DurableFunctionType::WriteRemote && !self.assume_idempotence) || matches!( - *wrapped_function_type, - WrappedFunctionType::WriteRemoteBatched(None) + *function_type, + DurableFunctionType::WriteRemoteBatched(None) )) { if self.is_live() { @@ -1918,8 +1917,8 @@ impl PrivateDurableWorkerState PrivateDurableWorkerState Result<(), GolemError> { if self.persistence_level != PersistenceLevel::PersistNothing - && ((*wrapped_function_type == WrappedFunctionType::WriteRemote - && !self.assume_idempotence) + && ((*function_type == DurableFunctionType::WriteRemote && !self.assume_idempotence) || matches!( - *wrapped_function_type, - WrappedFunctionType::WriteRemoteBatched(None) + *function_type, + DurableFunctionType::WriteRemoteBatched(None) )) { if self.is_live() { 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 80b031fa93..ffb0ed86be 100644 --- a/golem-worker-executor-base/src/durable_host/random/insecure.rs +++ b/golem-worker-executor-base/src/durable_host/random/insecure.rs @@ -17,17 +17,17 @@ use async_trait::async_trait; use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime_wasi::bindings::random::insecure::Host; #[async_trait] impl Host for DurableWorkerCtx { async fn get_insecure_random_bytes(&mut self, len: u64) -> anyhow::Result> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem random::insecure", "get_insecure_random_bytes", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; @@ -40,11 +40,11 @@ impl Host for DurableWorkerCtx { } async fn get_insecure_random_u64(&mut self) -> anyhow::Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "golem random::insecure", "get_insecure_random_u64", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; 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 2e6215ddc8..3757924ff0 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 @@ -17,17 +17,17 @@ use async_trait::async_trait; use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime_wasi::bindings::random::insecure_seed::Host; #[async_trait] impl Host for DurableWorkerCtx { async fn insecure_seed(&mut self) -> anyhow::Result<(u64, u64)> { - let durability = Durability::::new( + let durability = Durability::<(u64, u64), SerializableError>::new( self, "golem random::insecure_seed", "insecure_seed", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; if durability.is_live() { 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 6497c9a583..44781d6d67 100644 --- a/golem-worker-executor-base/src/durable_host/random/random.rs +++ b/golem-worker-executor-base/src/durable_host/random/random.rs @@ -17,17 +17,17 @@ use async_trait::async_trait; use crate::durable_host::serialized::SerializableError; use crate::durable_host::{Durability, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime_wasi::bindings::random::random::Host; #[async_trait] impl Host for DurableWorkerCtx { async fn get_random_bytes(&mut self, len: u64) -> anyhow::Result> { - let durability = Durability::, SerializableError>::new( + let durability = Durability::, SerializableError>::new( self, "golem random", "get_random_bytes", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; if durability.is_live() { @@ -39,11 +39,11 @@ impl Host for DurableWorkerCtx { } async fn get_random_u64(&mut self) -> anyhow::Result { - let durability = Durability::::new( + let durability = Durability::::new( self, "golem random", "get_random_u64", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; if durability.is_live() { diff --git a/golem-worker-executor-base/src/durable_host/sockets/instance_network.rs b/golem-worker-executor-base/src/durable_host/sockets/instance_network.rs index 139f56cc44..f37a7aa739 100644 --- a/golem-worker-executor-base/src/durable_host/sockets/instance_network.rs +++ b/golem-worker-executor-base/src/durable_host/sockets/instance_network.rs @@ -15,15 +15,14 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::sockets::instance_network::{Host, Network}; #[async_trait] impl Host for DurableWorkerCtx { fn instance_network(&mut self) -> anyhow::Result> { - record_host_function_call("sockets::instance_network", "instance_network"); + self.observe_function_call("sockets::instance_network", "instance_network"); Host::instance_network(&mut self.as_wasi_view()) } } 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 37e134dbd1..a1ebdcb939 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 @@ -16,11 +16,10 @@ use async_trait::async_trait; use wasmtime::component::Resource; use crate::durable_host::serialized::{SerializableError, SerializableIpAddresses}; -use crate::durable_host::{Durability, DurableWorkerCtx}; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx}; use crate::error::GolemError; -use crate::metrics::wasm::record_host_function_call; use crate::workerctx::WorkerCtx; -use golem_common::model::oplog::WrappedFunctionType; +use golem_common::model::oplog::DurableFunctionType; use wasmtime_wasi::bindings::sockets::ip_name_lookup::{ Host, HostResolveAddressStream, IpAddress, Network, Pollable, ResolveAddressStream, }; @@ -33,7 +32,7 @@ impl HostResolveAddressStream for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result, SocketError> { - record_host_function_call( + self.observe_function_call( "sockets::ip_name_lookup::resolve_address_stream", "resolve_next_address", ); @@ -44,7 +43,7 @@ impl HostResolveAddressStream for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call( + self.observe_function_call( "sockets::ip_name_lookup::resolve_address_stream", "subscribe", ); @@ -52,7 +51,7 @@ impl HostResolveAddressStream for DurableWorkerCtx { } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("sockets::ip_name_lookup::resolve_address_stream", "drop"); + self.observe_function_call("sockets::ip_name_lookup::resolve_address_stream", "drop"); HostResolveAddressStream::drop(&mut self.as_wasi_view(), rep) } } @@ -64,11 +63,11 @@ impl Host for DurableWorkerCtx { network: Resource, name: String, ) -> Result, SocketError> { - let durability = Durability::::new( + let durability = Durability::::new( self, "sockets::ip_name_lookup", "resolve_addresses", - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await?; diff --git a/golem-worker-executor-base/src/durable_host/sockets/network.rs b/golem-worker-executor-base/src/durable_host/sockets/network.rs index 50ccc28d65..9cbd9ace45 100644 --- a/golem-worker-executor-base/src/durable_host/sockets/network.rs +++ b/golem-worker-executor-base/src/durable_host/sockets/network.rs @@ -15,15 +15,14 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::sockets::network::{Error, ErrorCode, Host, HostNetwork, Network}; use wasmtime_wasi::SocketError; impl HostNetwork for DurableWorkerCtx { fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("sockets::network", "drop_network"); + self.observe_function_call("sockets::network", "drop_network"); HostNetwork::drop(&mut self.as_wasi_view(), rep) } } @@ -31,12 +30,12 @@ impl HostNetwork for DurableWorkerCtx { #[async_trait] impl Host for DurableWorkerCtx { fn network_error_code(&mut self, err: Resource) -> anyhow::Result> { - record_host_function_call("sockets::network", "network_error_code"); + self.observe_function_call("sockets::network", "network_error_code"); Host::network_error_code(&mut self.as_wasi_view(), err) } fn convert_error_code(&mut self, err: SocketError) -> anyhow::Result { - record_host_function_call("sockets::network", "convert_error_code"); + self.observe_function_call("sockets::network", "convert_error_code"); Host::convert_error_code(&mut self.as_wasi_view(), err) } } diff --git a/golem-worker-executor-base/src/durable_host/sockets/tcp.rs b/golem-worker-executor-base/src/durable_host/sockets/tcp.rs index 7e856530d8..fb81d0a487 100644 --- a/golem-worker-executor-base/src/durable_host/sockets/tcp.rs +++ b/golem-worker-executor-base/src/durable_host/sockets/tcp.rs @@ -15,8 +15,7 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::sockets::tcp::{ Duration, Host, HostTcpSocket, InputStream, IpAddressFamily, IpSocketAddress, Network, @@ -32,12 +31,12 @@ impl HostTcpSocket for DurableWorkerCtx { network: Resource, local_address: IpSocketAddress, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "start_bind"); + self.observe_function_call("sockets::tcp", "start_bind"); HostTcpSocket::start_bind(&mut self.as_wasi_view(), self_, network, local_address).await } fn finish_bind(&mut self, self_: Resource) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "finish_bind"); + self.observe_function_call("sockets::tcp", "finish_bind"); HostTcpSocket::finish_bind(&mut self.as_wasi_view(), self_) } @@ -47,7 +46,7 @@ impl HostTcpSocket for DurableWorkerCtx { network: Resource, remote_address: IpSocketAddress, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "start_connect"); + self.observe_function_call("sockets::tcp", "start_connect"); HostTcpSocket::start_connect(&mut self.as_wasi_view(), self_, network, remote_address).await } @@ -55,17 +54,17 @@ impl HostTcpSocket for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result<(Resource, Resource), SocketError> { - record_host_function_call("sockets::tcp", "finish_connect"); + self.observe_function_call("sockets::tcp", "finish_connect"); HostTcpSocket::finish_connect(&mut self.as_wasi_view(), self_) } fn start_listen(&mut self, self_: Resource) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "start_listen"); + self.observe_function_call("sockets::tcp", "start_listen"); HostTcpSocket::start_listen(&mut self.as_wasi_view(), self_) } fn finish_listen(&mut self, self_: Resource) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "finish_listen"); + self.observe_function_call("sockets::tcp", "finish_listen"); HostTcpSocket::finish_listen(&mut self.as_wasi_view(), self_) } @@ -80,7 +79,7 @@ impl HostTcpSocket for DurableWorkerCtx { ), SocketError, > { - record_host_function_call("sockets::tcp", "accept"); + self.observe_function_call("sockets::tcp", "accept"); HostTcpSocket::accept(&mut self.as_wasi_view(), self_) } @@ -88,7 +87,7 @@ impl HostTcpSocket for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result { - record_host_function_call("sockets::tcp", "local_address"); + self.observe_function_call("sockets::tcp", "local_address"); HostTcpSocket::local_address(&mut self.as_wasi_view(), self_) } @@ -96,17 +95,17 @@ impl HostTcpSocket for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result { - record_host_function_call("sockets::tcp", "remote_address"); + self.observe_function_call("sockets::tcp", "remote_address"); HostTcpSocket::remote_address(&mut self.as_wasi_view(), self_) } fn is_listening(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("sockets::tcp", "is_listening"); + self.observe_function_call("sockets::tcp", "is_listening"); HostTcpSocket::is_listening(&mut self.as_wasi_view(), self_) } fn address_family(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("sockets::tcp", "address_family"); + self.observe_function_call("sockets::tcp", "address_family"); HostTcpSocket::address_family(&mut self.as_wasi_view(), self_) } @@ -115,12 +114,12 @@ impl HostTcpSocket for DurableWorkerCtx { self_: Resource, value: u64, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "set_listen_backlog_size"); + self.observe_function_call("sockets::tcp", "set_listen_backlog_size"); HostTcpSocket::set_listen_backlog_size(&mut self.as_wasi_view(), self_, value) } fn keep_alive_enabled(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::tcp", "keep_alive_enabled"); + self.observe_function_call("sockets::tcp", "keep_alive_enabled"); HostTcpSocket::keep_alive_enabled(&mut self.as_wasi_view(), self_) } @@ -129,7 +128,7 @@ impl HostTcpSocket for DurableWorkerCtx { self_: Resource, value: bool, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "set_keep_alive_enabled"); + self.observe_function_call("sockets::tcp", "set_keep_alive_enabled"); HostTcpSocket::set_keep_alive_enabled(&mut self.as_wasi_view(), self_, value) } @@ -137,7 +136,7 @@ impl HostTcpSocket for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result { - record_host_function_call("sockets::tcp", "keep_alive_idle_time"); + self.observe_function_call("sockets::tcp", "keep_alive_idle_time"); HostTcpSocket::keep_alive_idle_time(&mut self.as_wasi_view(), self_) } @@ -146,12 +145,12 @@ impl HostTcpSocket for DurableWorkerCtx { self_: Resource, value: Duration, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "set_keep_alive_idle_time"); + self.observe_function_call("sockets::tcp", "set_keep_alive_idle_time"); HostTcpSocket::set_keep_alive_idle_time(&mut self.as_wasi_view(), self_, value) } fn keep_alive_interval(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::tcp", "keep_alive_interval"); + self.observe_function_call("sockets::tcp", "keep_alive_interval"); HostTcpSocket::keep_alive_interval(&mut self.as_wasi_view(), self_) } @@ -160,12 +159,12 @@ impl HostTcpSocket for DurableWorkerCtx { self_: Resource, value: Duration, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "set_keep_alive_interval"); + self.observe_function_call("sockets::tcp", "set_keep_alive_interval"); HostTcpSocket::set_keep_alive_interval(&mut self.as_wasi_view(), self_, value) } fn keep_alive_count(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::tcp", "keep_alive_count"); + self.observe_function_call("sockets::tcp", "keep_alive_count"); HostTcpSocket::keep_alive_count(&mut self.as_wasi_view(), self_) } @@ -174,22 +173,22 @@ impl HostTcpSocket for DurableWorkerCtx { self_: Resource, value: u32, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "set_keep_alive_count"); + self.observe_function_call("sockets::tcp", "set_keep_alive_count"); HostTcpSocket::set_keep_alive_count(&mut self.as_wasi_view(), self_, value) } fn hop_limit(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::tcp", "hop_limit"); + self.observe_function_call("sockets::tcp", "hop_limit"); HostTcpSocket::hop_limit(&mut self.as_wasi_view(), self_) } fn set_hop_limit(&mut self, self_: Resource, value: u8) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "set_hop_limit"); + self.observe_function_call("sockets::tcp", "set_hop_limit"); HostTcpSocket::set_hop_limit(&mut self.as_wasi_view(), self_, value) } fn receive_buffer_size(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::tcp", "receive_buffer_size"); + self.observe_function_call("sockets::tcp", "receive_buffer_size"); HostTcpSocket::receive_buffer_size(&mut self.as_wasi_view(), self_) } @@ -198,12 +197,12 @@ impl HostTcpSocket for DurableWorkerCtx { self_: Resource, value: u64, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "set_receive_buffer_size"); + self.observe_function_call("sockets::tcp", "set_receive_buffer_size"); HostTcpSocket::set_receive_buffer_size(&mut self.as_wasi_view(), self_, value) } fn send_buffer_size(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::tcp", "send_buffer_size"); + self.observe_function_call("sockets::tcp", "send_buffer_size"); HostTcpSocket::send_buffer_size(&mut self.as_wasi_view(), self_) } @@ -212,12 +211,12 @@ impl HostTcpSocket for DurableWorkerCtx { self_: Resource, value: u64, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "set_send_buffer_size"); + self.observe_function_call("sockets::tcp", "set_send_buffer_size"); HostTcpSocket::set_send_buffer_size(&mut self.as_wasi_view(), self_, value) } fn subscribe(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("sockets::tcp", "subscribe"); + self.observe_function_call("sockets::tcp", "subscribe"); HostTcpSocket::subscribe(&mut self.as_wasi_view(), self_) } @@ -226,12 +225,12 @@ impl HostTcpSocket for DurableWorkerCtx { self_: Resource, shutdown_type: ShutdownType, ) -> Result<(), SocketError> { - record_host_function_call("sockets::tcp", "shutdown"); + self.observe_function_call("sockets::tcp", "shutdown"); HostTcpSocket::shutdown(&mut self.as_wasi_view(), self_, shutdown_type) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("sockets::tcp", "drop"); + self.observe_function_call("sockets::tcp", "drop"); HostTcpSocket::drop(&mut self.as_wasi_view(), rep) } } diff --git a/golem-worker-executor-base/src/durable_host/sockets/tcp_create_socket.rs b/golem-worker-executor-base/src/durable_host/sockets/tcp_create_socket.rs index cbf844f05b..e402a1970a 100644 --- a/golem-worker-executor-base/src/durable_host/sockets/tcp_create_socket.rs +++ b/golem-worker-executor-base/src/durable_host/sockets/tcp_create_socket.rs @@ -15,8 +15,7 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::sockets::tcp_create_socket::{Host, IpAddressFamily, TcpSocket}; use wasmtime_wasi::SocketError; @@ -27,7 +26,7 @@ impl Host for DurableWorkerCtx { &mut self, address_family: IpAddressFamily, ) -> Result, SocketError> { - record_host_function_call("sockets::tcp_create_socket", "create_tcp_socket"); + self.observe_function_call("sockets::tcp_create_socket", "create_tcp_socket"); Host::create_tcp_socket(&mut self.as_wasi_view(), address_family) } } diff --git a/golem-worker-executor-base/src/durable_host/sockets/udp.rs b/golem-worker-executor-base/src/durable_host/sockets/udp.rs index 89ca53679b..a4ca486cd1 100644 --- a/golem-worker-executor-base/src/durable_host/sockets/udp.rs +++ b/golem-worker-executor-base/src/durable_host/sockets/udp.rs @@ -15,8 +15,7 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::sockets::udp::{ Host, HostIncomingDatagramStream, HostOutgoingDatagramStream, HostUdpSocket, IncomingDatagram, @@ -33,12 +32,12 @@ impl HostUdpSocket for DurableWorkerCtx { network: Resource, local_address: IpSocketAddress, ) -> Result<(), SocketError> { - record_host_function_call("sockets::udp", "start_bind"); + self.observe_function_call("sockets::udp", "start_bind"); HostUdpSocket::start_bind(&mut self.as_wasi_view(), self_, network, local_address).await } fn finish_bind(&mut self, self_: Resource) -> Result<(), SocketError> { - record_host_function_call("sockets::udp", "finish_bind"); + self.observe_function_call("sockets::udp", "finish_bind"); HostUdpSocket::finish_bind(&mut self.as_wasi_view(), self_) } @@ -53,7 +52,7 @@ impl HostUdpSocket for DurableWorkerCtx { ), SocketError, > { - record_host_function_call("sockets::udp", "stream"); + self.observe_function_call("sockets::udp", "stream"); HostUdpSocket::stream(&mut self.as_wasi_view(), self_, remote_address).await } @@ -61,7 +60,7 @@ impl HostUdpSocket for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result { - record_host_function_call("sockets::udp", "local_address"); + self.observe_function_call("sockets::udp", "local_address"); HostUdpSocket::local_address(&mut self.as_wasi_view(), self_) } @@ -69,17 +68,17 @@ impl HostUdpSocket for DurableWorkerCtx { &mut self, self_: Resource, ) -> Result { - record_host_function_call("sockets::udp", "remote_address"); + self.observe_function_call("sockets::udp", "remote_address"); HostUdpSocket::remote_address(&mut self.as_wasi_view(), self_) } fn address_family(&mut self, self_: Resource) -> anyhow::Result { - record_host_function_call("sockets::udp", "address_family"); + self.observe_function_call("sockets::udp", "address_family"); HostUdpSocket::address_family(&mut self.as_wasi_view(), self_) } fn unicast_hop_limit(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::udp", "unicast_hop_limit"); + self.observe_function_call("sockets::udp", "unicast_hop_limit"); HostUdpSocket::unicast_hop_limit(&mut self.as_wasi_view(), self_) } @@ -88,12 +87,12 @@ impl HostUdpSocket for DurableWorkerCtx { self_: Resource, value: u8, ) -> Result<(), SocketError> { - record_host_function_call("sockets::udp", "set_unicast_hop_limit"); + self.observe_function_call("sockets::udp", "set_unicast_hop_limit"); HostUdpSocket::set_unicast_hop_limit(&mut self.as_wasi_view(), self_, value) } fn receive_buffer_size(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::udp", "receive_buffer_size"); + self.observe_function_call("sockets::udp", "receive_buffer_size"); HostUdpSocket::receive_buffer_size(&mut self.as_wasi_view(), self_) } @@ -102,12 +101,12 @@ impl HostUdpSocket for DurableWorkerCtx { self_: Resource, value: u64, ) -> Result<(), SocketError> { - record_host_function_call("sockets::udp", "set_receive_buffer_size"); + self.observe_function_call("sockets::udp", "set_receive_buffer_size"); HostUdpSocket::set_receive_buffer_size(&mut self.as_wasi_view(), self_, value) } fn send_buffer_size(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::udp", "send_buffer_size"); + self.observe_function_call("sockets::udp", "send_buffer_size"); HostUdpSocket::send_buffer_size(&mut self.as_wasi_view(), self_) } @@ -116,17 +115,17 @@ impl HostUdpSocket for DurableWorkerCtx { self_: Resource, value: u64, ) -> Result<(), SocketError> { - record_host_function_call("sockets::udp", "set_send_buffer_size"); + self.observe_function_call("sockets::udp", "set_send_buffer_size"); HostUdpSocket::set_send_buffer_size(&mut self.as_wasi_view(), self_, value) } fn subscribe(&mut self, self_: Resource) -> anyhow::Result> { - record_host_function_call("sockets::udp", "subscribe"); + self.observe_function_call("sockets::udp", "subscribe"); HostUdpSocket::subscribe(&mut self.as_wasi_view(), self_) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("sockets::udp", "drop"); + self.observe_function_call("sockets::udp", "drop"); HostUdpSocket::drop(&mut self.as_wasi_view(), rep) } } @@ -137,7 +136,7 @@ impl HostIncomingDatagramStream for DurableWorkerCtx { self_: Resource, max_results: u64, ) -> Result, SocketError> { - record_host_function_call("sockets::udp", "receive"); + self.observe_function_call("sockets::udp", "receive"); HostIncomingDatagramStream::receive(&mut self.as_wasi_view(), self_, max_results) } @@ -145,12 +144,12 @@ impl HostIncomingDatagramStream for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call("sockets::udp", "subscribe"); + self.observe_function_call("sockets::udp", "subscribe"); HostIncomingDatagramStream::subscribe(&mut self.as_wasi_view(), self_) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("sockets::udp", "drop"); + self.observe_function_call("sockets::udp", "drop"); HostIncomingDatagramStream::drop(&mut self.as_wasi_view(), rep) } } @@ -158,7 +157,7 @@ impl HostIncomingDatagramStream for DurableWorkerCtx { #[async_trait] impl HostOutgoingDatagramStream for DurableWorkerCtx { fn check_send(&mut self, self_: Resource) -> Result { - record_host_function_call("sockets::udp", "check_send"); + self.observe_function_call("sockets::udp", "check_send"); HostOutgoingDatagramStream::check_send(&mut self.as_wasi_view(), self_) } @@ -167,7 +166,7 @@ impl HostOutgoingDatagramStream for DurableWorkerCtx { self_: Resource, datagrams: Vec, ) -> Result { - record_host_function_call("sockets::udp", "send"); + self.observe_function_call("sockets::udp", "send"); HostOutgoingDatagramStream::send(&mut self.as_wasi_view(), self_, datagrams).await } @@ -175,12 +174,12 @@ impl HostOutgoingDatagramStream for DurableWorkerCtx { &mut self, self_: Resource, ) -> anyhow::Result> { - record_host_function_call("sockets::udp", "subscribe"); + self.observe_function_call("sockets::udp", "subscribe"); HostOutgoingDatagramStream::subscribe(&mut self.as_wasi_view(), self_) } fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("sockets::udp", "drop"); + self.observe_function_call("sockets::udp", "drop"); HostOutgoingDatagramStream::drop(&mut self.as_wasi_view(), rep) } } diff --git a/golem-worker-executor-base/src/durable_host/sockets/udp_create_socket.rs b/golem-worker-executor-base/src/durable_host/sockets/udp_create_socket.rs index da3992f484..820a2996dc 100644 --- a/golem-worker-executor-base/src/durable_host/sockets/udp_create_socket.rs +++ b/golem-worker-executor-base/src/durable_host/sockets/udp_create_socket.rs @@ -15,8 +15,7 @@ use async_trait::async_trait; use wasmtime::component::Resource; -use crate::durable_host::DurableWorkerCtx; -use crate::metrics::wasm::record_host_function_call; +use crate::durable_host::{DurabilityHost, DurableWorkerCtx}; use crate::workerctx::WorkerCtx; use wasmtime_wasi::bindings::sockets::udp_create_socket::{Host, IpAddressFamily, UdpSocket}; use wasmtime_wasi::SocketError; @@ -27,7 +26,7 @@ impl Host for DurableWorkerCtx { &mut self, address_family: IpAddressFamily, ) -> Result, SocketError> { - record_host_function_call("sockets::udp_create_socket", "create_udp_socket"); + self.observe_function_call("sockets::udp_create_socket", "create_udp_socket"); Host::create_udp_socket(&mut self.as_wasi_view(), address_family) } } 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 c5560a4284..7f1e29c611 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 @@ -18,10 +18,9 @@ use crate::durable_host::serialized::SerializableError; use crate::durable_host::wasm_rpc::serialized::{ SerializableInvokeRequest, SerializableInvokeResult, SerializableInvokeResultV1, }; -use crate::durable_host::{Durability, DurableWorkerCtx, OplogEntryVersion}; +use crate::durable_host::{Durability, DurabilityHost, DurableWorkerCtx, OplogEntryVersion}; use crate::error::GolemError; use crate::get_oplog_entry; -use crate::metrics::wasm::record_host_function_call; use crate::model::PersistenceLevel; use crate::services::component::ComponentService; use crate::services::oplog::{CommitLevel, OplogOps}; @@ -30,7 +29,7 @@ use crate::workerctx::{InvocationManagement, WorkerCtx}; use anyhow::anyhow; use async_trait::async_trait; use golem_common::model::exports::function_by_name; -use golem_common::model::oplog::{OplogEntry, WrappedFunctionType}; +use golem_common::model::oplog::{DurableFunctionType, OplogEntry}; use golem_common::model::{ AccountId, ComponentId, IdempotencyKey, OwnedWorkerId, TargetWorkerId, WorkerId, }; @@ -57,7 +56,7 @@ use wasmtime_wasi::subscribe; #[async_trait] impl HostWasmRpc for DurableWorkerCtx { async fn new(&mut self, location: Uri) -> anyhow::Result> { - record_host_function_call("golem::rpc::wasm-rpc", "new"); + self.observe_function_call("golem::rpc::wasm-rpc", "new"); match location.parse_as_golem_urn() { Some((remote_worker_id, None)) => { @@ -105,11 +104,11 @@ impl HostWasmRpc for DurableWorkerCtx { let oplog_index = self.state.current_oplog_index().await; // NOTE: Now that IdempotencyKey::derived is used, we no longer need to persist this, but we do to avoid breaking existing oplogs - let durability = Durability::::new( + let durability = Durability::<(u64, u64), SerializableError>::new( self, "golem::rpc::wasm-rpc", "invoke-and-await idempotency key", - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; let uuid = if durability.is_live() { @@ -126,11 +125,11 @@ impl HostWasmRpc for DurableWorkerCtx { }; let idempotency_key = IdempotencyKey::from_uuid(uuid); - let durability = Durability::::new( + let durability = Durability::::new( self, "golem::rpc::wasm-rpc", "invoke-and-await result", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; let result: Result = if durability.is_live() { @@ -237,11 +236,11 @@ impl HostWasmRpc for DurableWorkerCtx { let oplog_index = self.state.current_oplog_index().await; // NOTE: Now that IdempotencyKey::derived is used, we no longer need to persist this, but we do to avoid breaking existing oplogs - let durability = Durability::::new( + let durability = Durability::<(u64, u64), SerializableError>::new( self, "golem::rpc::wasm-rpc", "invoke-and-await idempotency key", // NOTE: must keep invoke-and-await in the name for compatibility with Golem 1.0 - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; let uuid = if durability.is_live() { @@ -259,11 +258,11 @@ impl HostWasmRpc for DurableWorkerCtx { let idempotency_key = IdempotencyKey::from_uuid(uuid); - let durability = Durability::::new( + let durability = Durability::<(), SerializableError>::new( self, "golem::rpc::wasm-rpc", "invoke", - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await?; let result: Result<(), RpcError> = if durability.is_live() { @@ -317,7 +316,7 @@ impl HostWasmRpc for DurableWorkerCtx { let begin_index = self .state - .begin_function(&WrappedFunctionType::WriteRemote) + .begin_function(&DurableFunctionType::WriteRemote) .await?; let entry = self.table().get(&this)?; @@ -333,11 +332,11 @@ impl HostWasmRpc for DurableWorkerCtx { let oplog_index = self.state.current_oplog_index().await; // NOTE: Now that IdempotencyKey::derived is used, we no longer need to persist this, but we do to avoid breaking existing oplogs - let durability = Durability::::new( + let durability = Durability::<(u64, u64), SerializableError>::new( self, "golem::rpc::wasm-rpc", "invoke-and-await idempotency key", // NOTE: must keep invoke-and-await in the name for compatibility with Golem 1.0 - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await?; let uuid = if durability.is_live() { @@ -412,7 +411,7 @@ impl HostWasmRpc for DurableWorkerCtx { } Err(_) => { self.state - .end_function(&WrappedFunctionType::WriteRemote, begin_index) + .end_function(&DurableFunctionType::WriteRemote, begin_index) .await?; } } @@ -421,7 +420,7 @@ impl HostWasmRpc for DurableWorkerCtx { } async fn drop(&mut self, rep: Resource) -> anyhow::Result<()> { - record_host_function_call("golem::rpc::wasm-rpc", "drop"); + self.observe_function_call("golem::rpc::wasm-rpc", "drop"); let _ = self.table().delete(rep)?; Ok(()) @@ -514,7 +513,7 @@ impl HostFutureInvokeResult for DurableWorkerCtx { &mut self, this: Resource, ) -> anyhow::Result> { - record_host_function_call("golem::rpc::future-invoke-result", "subscribe"); + self.observe_function_call("golem::rpc::future-invoke-result", "subscribe"); subscribe(self.table(), this, None) } @@ -522,7 +521,7 @@ impl HostFutureInvokeResult for DurableWorkerCtx { &mut self, this: Resource, ) -> anyhow::Result>> { - record_host_function_call("golem::rpc::future-invoke-result", "get"); + self.observe_function_call("golem::rpc::future-invoke-result", "get"); let rpc = self.rpc(); let component_service = self.state.component_service.clone(); @@ -649,7 +648,7 @@ impl HostFutureInvokeResult for DurableWorkerCtx { "golem::rpc::future-invoke-result::get".to_string(), &serializable_invoke_request, &serializable_invoke_result, - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ) .await .unwrap_or_else(|err| panic!("failed to serialize RPC response: {err}")); @@ -661,7 +660,7 @@ impl HostFutureInvokeResult for DurableWorkerCtx { match self.state.open_function_table.get(&handle) { Some(begin_index) => { self.state - .end_function(&WrappedFunctionType::WriteRemote, *begin_index) + .end_function(&DurableFunctionType::WriteRemote, *begin_index) .await?; self.state.open_function_table.remove(&handle); } @@ -703,7 +702,7 @@ impl HostFutureInvokeResult for DurableWorkerCtx { match self.state.open_function_table.get(&handle) { Some(begin_index) => { self.state - .end_function(&WrappedFunctionType::WriteRemote, *begin_index) + .end_function(&DurableFunctionType::WriteRemote, *begin_index) .await?; self.state.open_function_table.remove(&handle); } @@ -745,7 +744,7 @@ impl HostFutureInvokeResult for DurableWorkerCtx { match self.state.open_function_table.get(&handle) { Some(begin_index) => { self.state - .end_function(&WrappedFunctionType::WriteRemote, *begin_index) + .end_function(&DurableFunctionType::WriteRemote, *begin_index) .await?; self.state.open_function_table.remove(&handle); } @@ -768,7 +767,7 @@ impl HostFutureInvokeResult for DurableWorkerCtx { } async fn drop(&mut self, this: Resource) -> anyhow::Result<()> { - record_host_function_call("golem::rpc::future-invoke-result", "drop"); + self.observe_function_call("golem::rpc::future-invoke-result", "drop"); let _ = self.table().delete(this)?; Ok(()) } diff --git a/golem-worker-executor-base/src/model/mod.rs b/golem-worker-executor-base/src/model/mod.rs index 4cbc450f9c..6682f0a274 100644 --- a/golem-worker-executor-base/src/model/mod.rs +++ b/golem-worker-executor-base/src/model/mod.rs @@ -296,7 +296,7 @@ impl Display for LastError { } } -#[derive(Clone, Debug, PartialOrd, PartialEq)] +#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)] pub enum PersistenceLevel { PersistNothing, PersistRemoteSideEffects, diff --git a/golem-worker-executor-base/src/model/public_oplog/wit.rs b/golem-worker-executor-base/src/model/public_oplog/wit.rs index 119afd6643..e64ace1606 100644 --- a/golem-worker-executor-base/src/model/public_oplog/wit.rs +++ b/golem-worker-executor-base/src/model/public_oplog/wit.rs @@ -22,7 +22,7 @@ use golem_common::model::public_oplog::{ ExportedFunctionParameters, FailedUpdateParameters, GrowMemoryParameters, ImportedFunctionInvokedParameters, JumpParameters, LogParameters, ManualUpdateParameters, PendingUpdateParameters, PendingWorkerInvocationParameters, PluginInstallationDescription, - PublicRetryConfig, PublicWorkerInvocation, PublicWrappedFunctionType, ResourceParameters, + PublicDurableFunctionType, PublicRetryConfig, PublicWorkerInvocation, ResourceParameters, SnapshotBasedUpdateParameters, SuccessfulUpdateParameters, TimestampParameter, WriteRemoteBatchedParameters, }; @@ -253,14 +253,14 @@ impl From for Datetime { } } -impl From for oplog::WrappedFunctionType { - fn from(value: PublicWrappedFunctionType) -> Self { +impl From for oplog::WrappedFunctionType { + fn from(value: PublicDurableFunctionType) -> Self { match value { - PublicWrappedFunctionType::WriteLocal(_) => Self::WriteLocal, - PublicWrappedFunctionType::ReadLocal(_) => Self::ReadLocal, - PublicWrappedFunctionType::WriteRemote(_) => Self::WriteRemote, - PublicWrappedFunctionType::ReadRemote(_) => Self::ReadRemote, - PublicWrappedFunctionType::WriteRemoteBatched(WriteRemoteBatchedParameters { + PublicDurableFunctionType::WriteLocal(_) => Self::WriteLocal, + PublicDurableFunctionType::ReadLocal(_) => Self::ReadLocal, + PublicDurableFunctionType::WriteRemote(_) => Self::WriteRemote, + PublicDurableFunctionType::ReadRemote(_) => Self::ReadRemote, + PublicDurableFunctionType::WriteRemoteBatched(WriteRemoteBatchedParameters { index: idx, }) => Self::WriteRemoteBatched(idx.map(|idx| idx.into())), } diff --git a/golem-worker-executor-base/src/services/oplog/mod.rs b/golem-worker-executor-base/src/services/oplog/mod.rs index 80f078bce1..d7d3dc0000 100644 --- a/golem-worker-executor-base/src/services/oplog/mod.rs +++ b/golem-worker-executor-base/src/services/oplog/mod.rs @@ -27,7 +27,7 @@ use bytes::Bytes; pub use compressed::{CompressedOplogArchive, CompressedOplogArchiveService, CompressedOplogChunk}; use golem_common::cache::{BackgroundEvictionMode, Cache, FullCacheEvictionMode}; use golem_common::model::oplog::{ - OplogEntry, OplogIndex, OplogPayload, UpdateDescription, WrappedFunctionType, + DurableFunctionType, OplogEntry, OplogIndex, OplogPayload, UpdateDescription, }; use golem_common::model::{ AccountId, ComponentId, ComponentVersion, IdempotencyKey, OwnedWorkerId, ScanCursor, Timestamp, @@ -224,19 +224,35 @@ pub trait OplogOps: Oplog { function_name: String, request: &I, response: &O, - wrapped_function_type: WrappedFunctionType, + function_type: DurableFunctionType, ) -> Result { let serialized_request = serialize(request)?.to_vec(); let serialized_response = serialize(response)?.to_vec(); - let request_payload: OplogPayload = self.upload_payload(&serialized_request).await?; - let response_payload = self.upload_payload(&serialized_response).await?; + self.add_raw_imported_function_invoked( + function_name, + &serialized_request, + &serialized_response, + function_type, + ) + .await + } + + async fn add_raw_imported_function_invoked( + &self, + function_name: String, + serialized_request: &[u8], + serialized_response: &[u8], + function_type: DurableFunctionType, + ) -> Result { + let request_payload: OplogPayload = self.upload_payload(serialized_request).await?; + let response_payload = self.upload_payload(serialized_response).await?; let entry = OplogEntry::ImportedFunctionInvoked { timestamp: Timestamp::now_utc(), function_name, request: request_payload, response: response_payload, - wrapped_function_type, + wrapped_function_type: function_type, }; self.add(entry.clone()).await; Ok(entry) diff --git a/golem-worker-executor-base/src/services/oplog/tests.rs b/golem-worker-executor-base/src/services/oplog/tests.rs index 48b4985ff1..73e57c407e 100644 --- a/golem-worker-executor-base/src/services/oplog/tests.rs +++ b/golem-worker-executor-base/src/services/oplog/tests.rs @@ -443,7 +443,7 @@ async fn entries_with_small_payload(_tracing: &Tracing) { "f1".to_string(), &"request".to_string(), &"response".to_string(), - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await .unwrap(), @@ -562,7 +562,7 @@ async fn entries_with_large_payload(_tracing: &Tracing) { "f1".to_string(), &"request".to_string(), &large_payload1, - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ) .await .unwrap(), @@ -753,7 +753,7 @@ async fn multilayer_transfers_entries_after_limit_reached( "test-function".to_string(), &"request".to_string(), &i, - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ) .await .unwrap(), diff --git a/golem-worker-executor-base/tests/compatibility/v1.rs b/golem-worker-executor-base/tests/compatibility/v1.rs index 3afce8e820..53f1967be7 100644 --- a/golem-worker-executor-base/tests/compatibility/v1.rs +++ b/golem-worker-executor-base/tests/compatibility/v1.rs @@ -24,9 +24,8 @@ use test_r::test; use bincode::{Decode, Encode}; use goldenfile::Mint; use golem_common::model::oplog::{ - IndexedResourceKey, LogLevel, OplogEntry, OplogIndex, OplogPayload, PayloadId, - TimestampedUpdateDescription, UpdateDescription, WorkerError, WorkerResourceId, - WrappedFunctionType, + DurableFunctionType, IndexedResourceKey, LogLevel, OplogEntry, OplogIndex, OplogPayload, + PayloadId, TimestampedUpdateDescription, UpdateDescription, WorkerError, WorkerResourceId, }; use golem_common::model::regions::{DeletedRegions, OplogRegion}; use golem_common::model::RetryConfig; @@ -603,32 +602,32 @@ pub fn wrapped_function_type() { backward_compatible( "wrapped_function_type_read_local", &mut mint, - WrappedFunctionType::ReadLocal, + DurableFunctionType::ReadLocal, ); backward_compatible( "wrapped_function_type_read_remote", &mut mint, - WrappedFunctionType::ReadRemote, + DurableFunctionType::ReadRemote, ); backward_compatible( "wrapped_function_type_write_local", &mut mint, - WrappedFunctionType::WriteLocal, + DurableFunctionType::WriteLocal, ); backward_compatible( "wrapped_function_type_write_remote", &mut mint, - WrappedFunctionType::WriteRemote, + DurableFunctionType::WriteRemote, ); backward_compatible( "wrapped_function_type_write_remote_batched_none", &mut mint, - WrappedFunctionType::WriteRemoteBatched(None), + DurableFunctionType::WriteRemoteBatched(None), ); backward_compatible( "wrapped_function_type_write_remote_batched_some", &mut mint, - WrappedFunctionType::WriteRemoteBatched(Some(OplogIndex::from_u64(100))), + DurableFunctionType::WriteRemoteBatched(Some(OplogIndex::from_u64(100))), ); } @@ -713,7 +712,7 @@ pub fn oplog_entry() { timestamp: Timestamp::from(1724701938466), function_name: "test:pkg/iface.{fn}".to_string(), response: OplogPayload::Inline(vec![0, 1, 2, 3, 4]), - wrapped_function_type: WrappedFunctionType::ReadLocal, + wrapped_function_type: DurableFunctionType::ReadLocal, }; let oe3 = OplogEntry::ExportedFunctionInvoked { diff --git a/golem-worker-executor-base/tests/compatibility/v1_1.rs b/golem-worker-executor-base/tests/compatibility/v1_1.rs index a0bebba96c..3cf2f376e1 100644 --- a/golem-worker-executor-base/tests/compatibility/v1_1.rs +++ b/golem-worker-executor-base/tests/compatibility/v1_1.rs @@ -18,7 +18,7 @@ use test_r::test; use crate::compatibility::v1::backward_compatible; use goldenfile::Mint; use golem_common::model::oplog::{ - IndexedResourceKey, OplogEntry, OplogIndex, OplogPayload, WorkerResourceId, WrappedFunctionType, + DurableFunctionType, IndexedResourceKey, OplogEntry, OplogIndex, OplogPayload, WorkerResourceId, }; use golem_common::model::RetryConfig; use golem_common::model::{ @@ -52,7 +52,7 @@ pub fn oplog_entry() { function_name: "test:pkg/iface.{fn}".to_string(), request: OplogPayload::Inline(vec![5, 6, 7, 8, 9]), response: OplogPayload::Inline(vec![0, 1, 2, 3, 4]), - wrapped_function_type: WrappedFunctionType::ReadLocal, + wrapped_function_type: DurableFunctionType::ReadLocal, }; let oe27a = OplogEntry::Create { timestamp: Timestamp::from(1724701938466), diff --git a/openapi/golem-service.yaml b/openapi/golem-service.yaml index 3ea0f5153e..dd0db86075 100644 --- a/openapi/golem-service.yaml +++ b/openapi/golem-service.yaml @@ -4729,7 +4729,7 @@ components: response: $ref: '#/components/schemas/ValueAndType' wrapped_function_type: - $ref: '#/components/schemas/PublicWrappedFunctionType' + $ref: '#/components/schemas/PublicDurableFunctionType' required: - timestamp - function_name @@ -4955,6 +4955,46 @@ components: - Facebook - Microsoft - Gitlab + PublicDurableFunctionType: + discriminator: + propertyName: type + mapping: + ReadLocal: '#/components/schemas/PublicDurableFunctionType_Empty' + WriteLocal: '#/components/schemas/PublicDurableFunctionType_Empty' + ReadRemote: '#/components/schemas/PublicDurableFunctionType_Empty' + WriteRemote: '#/components/schemas/PublicDurableFunctionType_Empty' + WriteRemoteBatched: '#/components/schemas/PublicDurableFunctionType_WriteRemoteBatchedParameters' + type: object + oneOf: + - $ref: '#/components/schemas/PublicDurableFunctionType_Empty' + - $ref: '#/components/schemas/PublicDurableFunctionType_Empty' + - $ref: '#/components/schemas/PublicDurableFunctionType_Empty' + - $ref: '#/components/schemas/PublicDurableFunctionType_Empty' + - $ref: '#/components/schemas/PublicDurableFunctionType_WriteRemoteBatchedParameters' + PublicDurableFunctionType_Empty: + allOf: + - type: object + properties: + type: + example: WriteRemote + type: string + enum: + - WriteRemote + required: + - type + - $ref: '#/components/schemas/Empty' + PublicDurableFunctionType_WriteRemoteBatchedParameters: + allOf: + - type: object + properties: + type: + example: WriteRemoteBatched + type: string + enum: + - WriteRemoteBatched + required: + - type + - $ref: '#/components/schemas/WriteRemoteBatchedParameters' PublicOplogEntry: description: |- A mirror of the core `OplogEntry` type, without the undefined arbitrary payloads. @@ -5354,46 +5394,6 @@ components: required: - type - $ref: '#/components/schemas/ManualUpdateParameters' - PublicWrappedFunctionType: - discriminator: - propertyName: type - mapping: - ReadLocal: '#/components/schemas/PublicWrappedFunctionType_Empty' - WriteLocal: '#/components/schemas/PublicWrappedFunctionType_Empty' - ReadRemote: '#/components/schemas/PublicWrappedFunctionType_Empty' - WriteRemote: '#/components/schemas/PublicWrappedFunctionType_Empty' - WriteRemoteBatched: '#/components/schemas/PublicWrappedFunctionType_WriteRemoteBatchedParameters' - type: object - oneOf: - - $ref: '#/components/schemas/PublicWrappedFunctionType_Empty' - - $ref: '#/components/schemas/PublicWrappedFunctionType_Empty' - - $ref: '#/components/schemas/PublicWrappedFunctionType_Empty' - - $ref: '#/components/schemas/PublicWrappedFunctionType_Empty' - - $ref: '#/components/schemas/PublicWrappedFunctionType_WriteRemoteBatchedParameters' - PublicWrappedFunctionType_Empty: - allOf: - - type: object - properties: - type: - example: WriteRemote - type: string - enum: - - WriteRemote - required: - - type - - $ref: '#/components/schemas/Empty' - PublicWrappedFunctionType_WriteRemoteBatchedParameters: - allOf: - - type: object - properties: - type: - example: WriteRemoteBatched - type: string - enum: - - WriteRemoteBatched - required: - - type - - $ref: '#/components/schemas/WriteRemoteBatchedParameters' ResourceMetadata: type: object properties: