From 5572000c44e85d53b3cfcd2c46a5b27f215521e8 Mon Sep 17 00:00:00 2001 From: Valery Antopol Date: Wed, 27 Mar 2024 23:44:08 +0400 Subject: [PATCH 01/33] use async marine --- Cargo.lock | 231 ++++++++++++++++++-------- Cargo.toml | 6 +- crates/spell-service-api/src/lib.rs | 3 +- particle-builtins/src/builtins.rs | 2 +- particle-services/src/app_services.rs | 42 +++-- 5 files changed, 198 insertions(+), 86 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd937c65ed..32d94d738b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -610,6 +610,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-recursion" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.46", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -2518,14 +2529,12 @@ dependencies = [ [[package]] name = "fluence-app-service" -version = "0.35.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527d278ac6fb1313a13b8c58149c3f977e79b93bf4280ce08e2cd4cac55cee27" +version = "0.35.2" dependencies = [ "log", "maplit", - "marine-min-it-version", - "marine-runtime 0.36.1", + "marine-min-it-version 0.3.2", + "marine-runtime 0.36.2", "marine-wasm-backend-traits 0.6.0", "marine-wasmtime-backend 0.6.0", "serde", @@ -3653,6 +3662,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "it-json-serde" +version = "0.5.1" +dependencies = [ + "serde", + "serde_derive", + "serde_json", + "thiserror", + "wasmer-interface-types-fl 0.28.0", +] + [[package]] name = "it-json-serde" version = "0.5.1" @@ -3663,7 +3683,7 @@ dependencies = [ "serde_derive", "serde_json", "thiserror", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", ] [[package]] @@ -3674,7 +3694,23 @@ checksum = "20108e77e11eeb1ef019f54c3868e0f2e9227295502f0702fa2e7e730ea748f8" dependencies = [ "anyhow", "fluence-it-types", - "it-memory-traits", + "it-memory-traits 0.4.0", + "log", + "paste", + "thiserror", +] + +[[package]] +name = "it-lilo" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa7310e6ce8b8b6f11c3d0b5dd5824675fab3cfd335f70bcf9a51198de39cfe" +dependencies = [ + "anyhow", + "async-recursion", + "fluence-it-types", + "futures", + "it-memory-traits 0.5.0", "log", "paste", "thiserror", @@ -3689,6 +3725,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "it-memory-traits" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83089981169d53e2b13df7c8d132b471bf2fc4c85afe427c4a74115695c4612" +dependencies = [ + "thiserror", +] + [[package]] name = "it-to-bytes" version = "0.1.0" @@ -4922,16 +4967,16 @@ checksum = "81f40fac4650a022a2ce8d7b6df5614062fc32cb25fb44e61027997e90a3aff6" dependencies = [ "anyhow", "bytesize", - "it-lilo", - "it-memory-traits", + "it-lilo 0.6.0", + "it-memory-traits 0.4.0", "log", "marine-it-generator 0.16.0", - "marine-it-interfaces", + "marine-it-interfaces 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "marine-it-parser 0.15.1", - "marine-min-it-version", + "marine-min-it-version 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "marine-module-info-parser 0.14.0", - "marine-module-interface", - "marine-utils", + "marine-module-interface 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "marine-utils 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "marine-wasm-backend-traits 0.5.1", "marine-wasmtime-backend 0.5.1", "multimap 0.8.3", @@ -4940,27 +4985,26 @@ dependencies = [ "semver 1.0.20", "serde", "thiserror", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", ] [[package]] name = "marine-core" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2989c1670a82d69724804c7af5d8e4c35231083338806c49485d983f27dd440f" dependencies = [ "anyhow", "bytesize", - "it-lilo", - "it-memory-traits", + "futures", + "it-lilo 0.7.0", + "it-memory-traits 0.5.0", "log", "marine-it-generator 0.17.0", - "marine-it-interfaces", + "marine-it-interfaces 0.9.1", "marine-it-parser 0.16.0", - "marine-min-it-version", + "marine-min-it-version 0.3.2", "marine-module-info-parser 0.15.0", - "marine-module-interface", - "marine-utils", + "marine-module-interface 0.8.1", + "marine-utils 0.5.1", "marine-wasm-backend-traits 0.6.0", "marine-wasmtime-backend 0.6.0", "multimap 0.8.3", @@ -4969,7 +5013,7 @@ dependencies = [ "semver 1.0.20", "serde", "thiserror", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.28.0", ] [[package]] @@ -4978,7 +5022,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23bdd0119dc71f98e2f0a4bef305e43b9a4d9b9adbead12bc05b0fac1d5a247c" dependencies = [ - "it-lilo", + "it-lilo 0.6.0", "marine-it-parser 0.15.1", "marine-macro-impl 0.14.0", "once_cell", @@ -4986,16 +5030,14 @@ dependencies = [ "serde_json", "thiserror", "walrus", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", ] [[package]] name = "marine-it-generator" version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993c33c6df3ae978022058dfd63a33b52de1307adec59e0c3f3367dd06bdf342" dependencies = [ - "it-lilo", + "it-lilo 0.7.0", "marine-it-parser 0.16.0", "marine-macro-impl 0.14.0", "once_cell", @@ -5003,7 +5045,15 @@ dependencies = [ "serde_json", "thiserror", "walrus", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.28.0", +] + +[[package]] +name = "marine-it-interfaces" +version = "0.9.1" +dependencies = [ + "multimap 0.8.3", + "wasmer-interface-types-fl 0.28.0", ] [[package]] @@ -5013,7 +5063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c610d90a031911c17b2babc32c9fad7261bae6ab0bf118051cd665b5d9bcfbe" dependencies = [ "multimap 0.8.3", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", ] [[package]] @@ -5024,34 +5074,32 @@ checksum = "921afa7f139791b24c4cb91c918d1ef7411ef40c3b801309ec43f6b2c89b107b" dependencies = [ "anyhow", "itertools 0.10.5", - "marine-it-interfaces", - "marine-module-interface", + "marine-it-interfaces 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "marine-module-interface 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "marine-wasm-backend-traits 0.5.1", "nom", "semver 1.0.20", "serde", "thiserror", "walrus", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", ] [[package]] name = "marine-it-parser" version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa9ba677486e1f1bf2bfd3e34b259255df277887fa90d5c22acb258bdedc34e" dependencies = [ "anyhow", "itertools 0.10.5", - "marine-it-interfaces", - "marine-module-interface", + "marine-it-interfaces 0.9.1", + "marine-module-interface 0.8.1", "marine-wasm-backend-traits 0.6.0", "nom", "semver 1.0.20", "serde", "thiserror", "walrus", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.28.0", ] [[package]] @@ -5146,6 +5194,14 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "marine-min-it-version" +version = "0.3.2" +dependencies = [ + "once_cell", + "semver 1.0.20", +] + [[package]] name = "marine-min-it-version" version = "0.3.2" @@ -5176,8 +5232,6 @@ dependencies = [ [[package]] name = "marine-module-info-parser" version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db5fe45b6f0f397ecce757c23a3d0c4a08c2e9ffa6e7f642cb89e1ec777b16d" dependencies = [ "anyhow", "chrono", @@ -5190,6 +5244,21 @@ dependencies = [ "walrus", ] +[[package]] +name = "marine-module-interface" +version = "0.8.1" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "marine-it-interfaces 0.9.1", + "nom", + "semver 1.0.20", + "serde", + "thiserror", + "walrus", + "wasmer-interface-types-fl 0.28.0", +] + [[package]] name = "marine-module-interface" version = "0.8.1" @@ -5198,13 +5267,13 @@ checksum = "d92d2243bf0d3aea6401d9e57a1ee17677b624337981322e0153cc2d54744080" dependencies = [ "anyhow", "itertools 0.10.5", - "marine-it-interfaces", + "marine-it-interfaces 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "nom", "semver 1.0.20", "serde", "thiserror", "walrus", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", ] [[package]] @@ -5280,18 +5349,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c599c7c13e976170a1211e31fe2fb4557e0479cbdba331b19a5a9e87f145f52" dependencies = [ "bytesize", - "it-json-serde", - "it-memory-traits", + "it-json-serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "it-memory-traits 0.4.0", "itertools 0.10.5", "log", "marine-call-parameters 0.10.3", "marine-call-parameters 0.12.0", "marine-call-parameters 0.13.0", "marine-core 0.29.0", - "marine-module-interface", + "marine-module-interface 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "marine-rs-sdk 0.14.0", "marine-rs-sdk-main 0.14.0", - "marine-utils", + "marine-utils 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "marine-wasm-backend-traits 0.5.1", "marine-wasmtime-backend 0.5.1", "parking_lot", @@ -5302,28 +5371,26 @@ dependencies = [ "serde_with 2.3.3", "thiserror", "toml 0.5.11", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", ] [[package]] name = "marine-runtime" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b524b572fa9c8c1b7a14c30d8e27a339404eeab70531bc9a9e739f1db4bc6af" +version = "0.36.2" dependencies = [ "bytesize", - "it-json-serde", - "it-memory-traits", + "it-json-serde 0.5.1", + "it-memory-traits 0.5.0", "itertools 0.10.5", "log", "marine-call-parameters 0.10.3", "marine-call-parameters 0.12.0", "marine-call-parameters 0.13.0", "marine-core 0.30.0", - "marine-module-interface", + "marine-module-interface 0.8.1", "marine-rs-sdk 0.14.0", "marine-rs-sdk-main 0.14.0", - "marine-utils", + "marine-utils 0.5.1", "marine-wasm-backend-traits 0.6.0", "marine-wasmtime-backend 0.6.0", "parking_lot", @@ -5334,7 +5401,7 @@ dependencies = [ "serde_with 2.3.3", "thiserror", "toml 0.5.11", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.28.0", ] [[package]] @@ -5367,6 +5434,10 @@ dependencies = [ "quote", ] +[[package]] +name = "marine-utils" +version = "0.5.1" + [[package]] name = "marine-utils" version = "0.5.1" @@ -5380,26 +5451,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "220bc47cfabb8b4ab97bf2bd7bbab9738857b69beeda0a1ac5776c600b64bb46" dependencies = [ "anyhow", - "it-memory-traits", + "it-memory-traits 0.4.0", "multimap 0.8.3", "paste", "thiserror", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", "wasmparser 0.101.1", ] [[package]] name = "marine-wasm-backend-traits" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50ba17135a13735abfc8fbbb221cd27fb8c607482ec72d7cd8f37315c9fdf6c5" dependencies = [ "anyhow", - "it-memory-traits", + "futures", + "it-memory-traits 0.5.0", "multimap 0.8.3", "paste", "thiserror", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.28.0", "wasmparser 0.101.1", ] @@ -5410,12 +5480,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaa0dc5a7da0e3334f3ce5b341ba4354341af9a1f9efae24884a1b931efdf23e" dependencies = [ "anyhow", - "it-memory-traits", + "it-memory-traits 0.4.0", "log", "marine-wasm-backend-traits 0.5.1", "multimap 0.8.3", "paste", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.27.0", "wasmtime", "wasmtime-wasi", ] @@ -5423,16 +5493,15 @@ dependencies = [ [[package]] name = "marine-wasmtime-backend" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7a74c532073142ced94fdeaf7a3e84f92ec5ebef5751fbd5516185ae3cf211" dependencies = [ "anyhow", - "it-memory-traits", + "futures", + "it-memory-traits 0.5.0", "log", "marine-wasm-backend-traits 0.6.0", "multimap 0.8.3", "paste", - "wasmer-interface-types-fl", + "wasmer-interface-types-fl 0.28.0", "wasmtime", "wasmtime-wasi", ] @@ -9313,12 +9382,36 @@ checksum = "62958478f282fbf2b05c12f9630972bd8194937de1ab22d6a59d43093be32886" dependencies = [ "anyhow", "fluence-it-types", - "it-lilo", - "it-memory-traits", + "it-lilo 0.6.0", + "it-memory-traits 0.4.0", + "it-to-bytes", + "itertools 0.10.5", + "log", + "nom", + "safe-transmute", + "semver 1.0.20", + "serde", + "serde_json", + "thiserror", + "wast 8.0.0", +] + +[[package]] +name = "wasmer-interface-types-fl" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a753426d5a76076aa16a435b5a5f316e3803461f551975d196928bc92e42916" +dependencies = [ + "anyhow", + "fluence-it-types", + "futures", + "it-lilo 0.7.0", + "it-memory-traits 0.5.0", "it-to-bytes", "itertools 0.10.5", "log", "nom", + "paste", "safe-transmute", "semver 1.0.20", "serde", diff --git a/Cargo.toml b/Cargo.toml index 1a82d9ac37..66a37c6123 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,10 +110,10 @@ fluence-spell-dtos = "=0.7.5" fluence-spell-distro = "=0.7.5" # marine -fluence-app-service = "0.35.1" +fluence-app-service = { version = "=0.35.2", path = "../marine/crates/fluence-app-service", features = ["wasmtime"] } marine-utils = "0.5.1" -marine-it-parser = "0.16.0" -marine-module-info-parser = "0.15.0" +marine-it-parser = { version = "0.16.0", path = "../marine/crates/it-parser" } +marine-module-info-parser = { version = "0.15.0", path = "../marine/crates/module-info-parser" } # avm avm-server = "=0.37.0" diff --git a/crates/spell-service-api/src/lib.rs b/crates/spell-service-api/src/lib.rs index 906ac1d25a..a40096c82f 100644 --- a/crates/spell-service-api/src/lib.rs +++ b/crates/spell-service-api/src/lib.rs @@ -362,7 +362,8 @@ mod tests { None, workers.clone(), scope.clone(), - ); + ).expect("Unable to create ParticleAppServices"); + (pas, repo, root_key_pair.get_peer_id()) } diff --git a/particle-builtins/src/builtins.rs b/particle-builtins/src/builtins.rs index 651dabaf8a..97435721aa 100644 --- a/particle-builtins/src/builtins.rs +++ b/particle-builtins/src/builtins.rs @@ -125,7 +125,7 @@ where health_registry, workers.clone(), scope.clone(), - ); + ).expect("TODO async-marine: handle error from ParticleAppServices"); Self { connectivity, diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index 0b100ecf13..6812fe270d 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -19,10 +19,7 @@ use std::time::{Duration, Instant}; use std::{collections::HashMap, sync::Arc}; use derivative::Derivative; -use fluence_app_service::{ - AppService, AppServiceConfig, AppServiceError, CallParameters, MarineConfig, MarineError, - MarineWASIConfig, ModuleDescriptor, SecurityTetraplet, ServiceInterface, -}; +use fluence_app_service::{AppService, AppServiceConfig, AppServiceError, AppServiceFactory, CallParameters, EpochTicker, MarineConfig, MarineError, MarineWASIConfig, ModuleDescriptor, SecurityTetraplet, ServiceInterface, WasmtimeConfig}; use humantime_serde::re::humantime::format_duration as pretty; use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; use serde::{Deserialize, Serialize}; @@ -184,6 +181,10 @@ pub struct ParticleAppServices { scopes: PeerScopes, pub metrics: Option, health: Option, + #[derivative(Debug = "ignore")] + app_service_factory: AppServiceFactory, + #[derivative(Debug = "ignore")] + app_service_epoch_ticker: EpochTicker, } fn resolve_alias(services: &Services, alias: &String, particle_id: &str) -> Option { @@ -216,7 +217,7 @@ impl ParticleAppServices { health_registry: Option<&mut HealthCheckRegistry>, workers: Arc, scope: PeerScopes, - ) -> Self { + ) -> Result { let vault = ParticleVault::new(config.particles_vault_dir.clone()); let root_runtime_handle = Handle::current(); @@ -225,7 +226,20 @@ impl ParticleAppServices { registry.register("persisted_services", persisted_services.clone()); persisted_services }); - Self { + + let mut wasmtime_config = WasmtimeConfig::default(); + // TODO async-marine: impl proper configuration + // TODO async-marine: move to the right place + wasmtime_config + .debug_info(true) + .wasm_backtrace(true) + .epoch_interruption(true) + .async_wasm_stack(2 * 1024 * 1024) + .max_wasm_stack(2 * 1024 * 1024); + + let (app_service_factory, epoch_ticker) = AppServiceFactory::new(wasmtime_config) + .map_err(ServiceError::Engine)?; + Ok(Self { config, vault, root_services: <_>::default(), @@ -236,7 +250,9 @@ impl ParticleAppServices { scopes: scope, metrics, health, - } + app_service_factory, + app_service_epoch_ticker: epoch_ticker + }) } pub async fn create_service( @@ -469,15 +485,15 @@ impl ParticleAppServices { let mut service = service.lock(); let old_memory = service.module_memory_stats(); let old_mem_usage = ServicesMetricsBuiltin::get_used_memory(&old_memory); - // TODO: set execution timeout https://github.com/fluencelabs/fluence/issues/1212 + // TODO async-marine: set execution timeout https://github.com/fluencelabs/fluence/issues/1212 let call_time_start = Instant::now(); - let result = service - .call( + let result = tokio::runtime::Handle::current().block_on(service + .call_async( function_name.clone(), JValue::Array(function_args.function_args), params, ) - .map_err(|e| { + ).map_err(|e| { if let Some(metrics) = self.metrics.as_ref() { let stats = ServiceCallStats::Fail { timestamp }; // If the called function is unknown we don't want to save info @@ -1117,7 +1133,8 @@ impl ParticleAppServices { self.config.envs ); - AppService::new(app_config, service_id, self.config.envs.clone()) + self.app_service_factory.new_app_service(app_config, service_id, self.config.envs.clone()) + .await .map_err(ServiceError::Engine) } @@ -1242,6 +1259,7 @@ mod tests { ); ParticleAppServices::new(config, repo, None, None, workers, scope) + .expect("Could not create ParticleAppServices") } async fn call_add_alias_raw( From 30007d7bb9625fb7404dfdc0b5e7ba33191c1a53 Mon Sep 17 00:00:00 2001 From: Valery Antopol Date: Wed, 27 Mar 2024 23:46:50 +0400 Subject: [PATCH 02/33] use marine from git --- Cargo.lock | 69 ++++++++++++++++++++++++++++++++---------------------- Cargo.toml | 6 ++--- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32d94d738b..8eef59de47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2530,10 +2530,11 @@ dependencies = [ [[package]] name = "fluence-app-service" version = "0.35.2" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "log", "maplit", - "marine-min-it-version 0.3.2", + "marine-min-it-version 0.3.2 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "marine-runtime 0.36.2", "marine-wasm-backend-traits 0.6.0", "marine-wasmtime-backend 0.6.0", @@ -3665,25 +3666,26 @@ dependencies = [ [[package]] name = "it-json-serde" version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a74b6ed688d9de56b4e4cb5aca2bd7a883909f1be8d8d6ba40e3a2d25b9feba5" dependencies = [ "serde", "serde_derive", "serde_json", "thiserror", - "wasmer-interface-types-fl 0.28.0", + "wasmer-interface-types-fl 0.27.0", ] [[package]] name = "it-json-serde" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74b6ed688d9de56b4e4cb5aca2bd7a883909f1be8d8d6ba40e3a2d25b9feba5" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "serde", "serde_derive", "serde_json", "thiserror", - "wasmer-interface-types-fl 0.27.0", + "wasmer-interface-types-fl 0.28.0", ] [[package]] @@ -4991,6 +4993,7 @@ dependencies = [ [[package]] name = "marine-core" version = "0.30.0" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "anyhow", "bytesize", @@ -4999,12 +5002,12 @@ dependencies = [ "it-memory-traits 0.5.0", "log", "marine-it-generator 0.17.0", - "marine-it-interfaces 0.9.1", + "marine-it-interfaces 0.9.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "marine-it-parser 0.16.0", - "marine-min-it-version 0.3.2", + "marine-min-it-version 0.3.2 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "marine-module-info-parser 0.15.0", - "marine-module-interface 0.8.1", - "marine-utils 0.5.1", + "marine-module-interface 0.8.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", + "marine-utils 0.5.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "marine-wasm-backend-traits 0.6.0", "marine-wasmtime-backend 0.6.0", "multimap 0.8.3", @@ -5036,6 +5039,7 @@ dependencies = [ [[package]] name = "marine-it-generator" version = "0.17.0" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "it-lilo 0.7.0", "marine-it-parser 0.16.0", @@ -5051,19 +5055,20 @@ dependencies = [ [[package]] name = "marine-it-interfaces" version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c610d90a031911c17b2babc32c9fad7261bae6ab0bf118051cd665b5d9bcfbe" dependencies = [ "multimap 0.8.3", - "wasmer-interface-types-fl 0.28.0", + "wasmer-interface-types-fl 0.27.0", ] [[package]] name = "marine-it-interfaces" version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c610d90a031911c17b2babc32c9fad7261bae6ab0bf118051cd665b5d9bcfbe" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "multimap 0.8.3", - "wasmer-interface-types-fl 0.27.0", + "wasmer-interface-types-fl 0.28.0", ] [[package]] @@ -5088,11 +5093,12 @@ dependencies = [ [[package]] name = "marine-it-parser" version = "0.16.0" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "anyhow", "itertools 0.10.5", - "marine-it-interfaces 0.9.1", - "marine-module-interface 0.8.1", + "marine-it-interfaces 0.9.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", + "marine-module-interface 0.8.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "marine-wasm-backend-traits 0.6.0", "nom", "semver 1.0.20", @@ -5197,6 +5203,8 @@ dependencies = [ [[package]] name = "marine-min-it-version" version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147e6e4c9d3dc9afbb06b2e3bc069b63c749733f698d0c364c320a72b133f1d5" dependencies = [ "once_cell", "semver 1.0.20", @@ -5205,8 +5213,7 @@ dependencies = [ [[package]] name = "marine-min-it-version" version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147e6e4c9d3dc9afbb06b2e3bc069b63c749733f698d0c364c320a72b133f1d5" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "once_cell", "semver 1.0.20", @@ -5232,6 +5239,7 @@ dependencies = [ [[package]] name = "marine-module-info-parser" version = "0.15.0" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "anyhow", "chrono", @@ -5247,33 +5255,34 @@ dependencies = [ [[package]] name = "marine-module-interface" version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92d2243bf0d3aea6401d9e57a1ee17677b624337981322e0153cc2d54744080" dependencies = [ "anyhow", "itertools 0.10.5", - "marine-it-interfaces 0.9.1", + "marine-it-interfaces 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "nom", "semver 1.0.20", "serde", "thiserror", "walrus", - "wasmer-interface-types-fl 0.28.0", + "wasmer-interface-types-fl 0.27.0", ] [[package]] name = "marine-module-interface" version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92d2243bf0d3aea6401d9e57a1ee17677b624337981322e0153cc2d54744080" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "anyhow", "itertools 0.10.5", - "marine-it-interfaces 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "marine-it-interfaces 0.9.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "nom", "semver 1.0.20", "serde", "thiserror", "walrus", - "wasmer-interface-types-fl 0.27.0", + "wasmer-interface-types-fl 0.28.0", ] [[package]] @@ -5377,9 +5386,10 @@ dependencies = [ [[package]] name = "marine-runtime" version = "0.36.2" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "bytesize", - "it-json-serde 0.5.1", + "it-json-serde 0.5.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "it-memory-traits 0.5.0", "itertools 0.10.5", "log", @@ -5387,10 +5397,10 @@ dependencies = [ "marine-call-parameters 0.12.0", "marine-call-parameters 0.13.0", "marine-core 0.30.0", - "marine-module-interface 0.8.1", + "marine-module-interface 0.8.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "marine-rs-sdk 0.14.0", "marine-rs-sdk-main 0.14.0", - "marine-utils 0.5.1", + "marine-utils 0.5.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", "marine-wasm-backend-traits 0.6.0", "marine-wasmtime-backend 0.6.0", "parking_lot", @@ -5437,12 +5447,13 @@ dependencies = [ [[package]] name = "marine-utils" version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce56bfabfd0af5326ff81c32c8d2261aa03b10e00ea6c165de4ebf8a3f998e4" [[package]] name = "marine-utils" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce56bfabfd0af5326ff81c32c8d2261aa03b10e00ea6c165de4ebf8a3f998e4" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" [[package]] name = "marine-wasm-backend-traits" @@ -5462,6 +5473,7 @@ dependencies = [ [[package]] name = "marine-wasm-backend-traits" version = "0.6.0" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "anyhow", "futures", @@ -5493,6 +5505,7 @@ dependencies = [ [[package]] name = "marine-wasmtime-backend" version = "0.6.0" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" dependencies = [ "anyhow", "futures", diff --git a/Cargo.toml b/Cargo.toml index 66a37c6123..00cbd62e55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,10 +110,10 @@ fluence-spell-dtos = "=0.7.5" fluence-spell-distro = "=0.7.5" # marine -fluence-app-service = { version = "=0.35.2", path = "../marine/crates/fluence-app-service", features = ["wasmtime"] } +fluence-app-service = { version = "=0.35.2", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call", features = ["wasmtime"] } marine-utils = "0.5.1" -marine-it-parser = { version = "0.16.0", path = "../marine/crates/it-parser" } -marine-module-info-parser = { version = "0.15.0", path = "../marine/crates/module-info-parser" } +marine-it-parser = { version = "0.16.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } +marine-module-info-parser = { version = "0.15.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } # avm avm-server = "=0.37.0" From 4e917b0018dc152be45df3a02bb02031d32ba60b Mon Sep 17 00:00:00 2001 From: Valery Antopol Date: Wed, 27 Mar 2024 23:53:47 +0400 Subject: [PATCH 03/33] fmt --- crates/spell-service-api/src/lib.rs | 3 ++- particle-builtins/src/builtins.rs | 3 ++- particle-services/src/app_services.rs | 23 ++++++++++++++--------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/crates/spell-service-api/src/lib.rs b/crates/spell-service-api/src/lib.rs index a40096c82f..2f2a088cd7 100644 --- a/crates/spell-service-api/src/lib.rs +++ b/crates/spell-service-api/src/lib.rs @@ -362,7 +362,8 @@ mod tests { None, workers.clone(), scope.clone(), - ).expect("Unable to create ParticleAppServices"); + ) + .expect("Unable to create ParticleAppServices"); (pas, repo, root_key_pair.get_peer_id()) } diff --git a/particle-builtins/src/builtins.rs b/particle-builtins/src/builtins.rs index 97435721aa..51940fc40c 100644 --- a/particle-builtins/src/builtins.rs +++ b/particle-builtins/src/builtins.rs @@ -125,7 +125,8 @@ where health_registry, workers.clone(), scope.clone(), - ).expect("TODO async-marine: handle error from ParticleAppServices"); + ) + .expect("TODO async-marine: handle error from ParticleAppServices"); Self { connectivity, diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index 6812fe270d..9205ef7793 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -19,7 +19,11 @@ use std::time::{Duration, Instant}; use std::{collections::HashMap, sync::Arc}; use derivative::Derivative; -use fluence_app_service::{AppService, AppServiceConfig, AppServiceError, AppServiceFactory, CallParameters, EpochTicker, MarineConfig, MarineError, MarineWASIConfig, ModuleDescriptor, SecurityTetraplet, ServiceInterface, WasmtimeConfig}; +use fluence_app_service::{ + AppService, AppServiceConfig, AppServiceError, AppServiceFactory, CallParameters, EpochTicker, + MarineConfig, MarineError, MarineWASIConfig, ModuleDescriptor, SecurityTetraplet, + ServiceInterface, WasmtimeConfig, +}; use humantime_serde::re::humantime::format_duration as pretty; use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; use serde::{Deserialize, Serialize}; @@ -237,8 +241,8 @@ impl ParticleAppServices { .async_wasm_stack(2 * 1024 * 1024) .max_wasm_stack(2 * 1024 * 1024); - let (app_service_factory, epoch_ticker) = AppServiceFactory::new(wasmtime_config) - .map_err(ServiceError::Engine)?; + let (app_service_factory, epoch_ticker) = + AppServiceFactory::new(wasmtime_config).map_err(ServiceError::Engine)?; Ok(Self { config, vault, @@ -251,7 +255,7 @@ impl ParticleAppServices { metrics, health, app_service_factory, - app_service_epoch_ticker: epoch_ticker + app_service_epoch_ticker: epoch_ticker, }) } @@ -487,13 +491,13 @@ impl ParticleAppServices { let old_mem_usage = ServicesMetricsBuiltin::get_used_memory(&old_memory); // TODO async-marine: set execution timeout https://github.com/fluencelabs/fluence/issues/1212 let call_time_start = Instant::now(); - let result = tokio::runtime::Handle::current().block_on(service - .call_async( + let result = tokio::runtime::Handle::current() + .block_on(service.call_async( function_name.clone(), JValue::Array(function_args.function_args), params, - ) - ).map_err(|e| { + )) + .map_err(|e| { if let Some(metrics) = self.metrics.as_ref() { let stats = ServiceCallStats::Fail { timestamp }; // If the called function is unknown we don't want to save info @@ -1133,7 +1137,8 @@ impl ParticleAppServices { self.config.envs ); - self.app_service_factory.new_app_service(app_config, service_id, self.config.envs.clone()) + self.app_service_factory + .new_app_service(app_config, service_id, self.config.envs.clone()) .await .map_err(ServiceError::Engine) } From 4a7a6fc3c3b824e7a40ad70a538b560ee654eb17 Mon Sep 17 00:00:00 2001 From: Valery Antopol Date: Thu, 28 Mar 2024 18:54:44 +0400 Subject: [PATCH 04/33] fix build --- Cargo.lock | 443 ++++-------------- Cargo.toml | 3 +- aquamarine/Cargo.toml | 2 + aquamarine/src/aqua_runtime.rs | 25 +- aquamarine/src/lib.rs | 4 +- crates/connected-client/Cargo.toml | 1 + .../connected-client/src/connected_client.rs | 5 +- crates/local-vm/Cargo.toml | 1 + crates/local-vm/src/local_vm.rs | 25 +- crates/nox-tests/tests/local_vm.rs | 4 +- nox/src/main.rs | 3 +- nox/src/node.rs | 3 +- 12 files changed, 146 insertions(+), 373 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8eef59de47..44a47ad9cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,26 +95,36 @@ dependencies = [ [[package]] name = "air-interpreter-interface" version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ca7926759c89514cbc1fdffe7477585e71eef42eedcedd695511e518b74cb9" dependencies = [ - "air-interpreter-sede", + "air-interpreter-sede 0.1.0", "air-interpreter-value", "fluence-it-types", "marine-call-parameters 0.14.0", - "marine-rs-sdk 0.14.0", + "marine-rs-sdk", "serde", "serde_bytes", "serde_json", ] +[[package]] +name = "air-interpreter-sede" +version = "0.1.0" +dependencies = [ + "marine-rs-sdk", + "rmp-serde", + "serde", + "serde_bytes", + "serde_json", + "thiserror", + "unsigned-varint 0.8.0", +] + [[package]] name = "air-interpreter-sede" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "433b1ca3538f5f6a6083646b2aa61cd57a08c1558091f6be47b2299fc7b28261" dependencies = [ - "marine-rs-sdk 0.10.3", "rmp-serde", "serde", "serde_bytes", @@ -126,8 +136,6 @@ dependencies = [ [[package]] name = "air-interpreter-value" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3158e53f5ca496d825120e111e110a546ed05e3116d37125655a9e20b230529" dependencies = [ "serde", "serde_json", @@ -145,8 +153,6 @@ dependencies = [ [[package]] name = "air-utils" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3705bf46663ca316391c8c666d96edf4c13f5d1054f4e7487a752e2051b85165" [[package]] name = "allocator-api2" @@ -338,6 +344,7 @@ dependencies = [ "control-macro", "enum_dispatch", "eyre", + "fluence-app-service", "fluence-keypair", "fluence-libp2p", "fs-utils", @@ -346,6 +353,7 @@ dependencies = [ "humantime 2.1.0", "libp2p", "log", + "marine-wasmtime-backend", "now-millis", "parking_lot", "particle-args", @@ -729,8 +737,6 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "avm-data-store" version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2bbb779d135467217968e752b092d2a00d649f452b1015aac332284d9b5aa9" dependencies = [ "avm-interface", "serde", @@ -740,11 +746,9 @@ dependencies = [ [[package]] name = "avm-interface" version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1767525a79ab972c3a40c6dc807f6eebcc323932e9846648b3b58f9940a54057" dependencies = [ "air-interpreter-interface", - "air-interpreter-sede", + "air-interpreter-sede 0.1.0", "air-utils", "log", "maplit", @@ -758,11 +762,9 @@ dependencies = [ [[package]] name = "avm-server" version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e5beb65a102486cfb868133876548b191ecba16110158d5116fca9b721ca7c" dependencies = [ "air-interpreter-interface", - "air-interpreter-sede", + "air-interpreter-sede 0.1.0", "air-utils", "avm-data-store", "avm-interface", @@ -770,12 +772,15 @@ dependencies = [ "fluence-keypair", "log", "maplit", - "marine-runtime 0.35.0", + "marine-runtime", + "marine-wasm-backend-traits", + "marine-wasmtime-backend", "parking_lot", "polyplets", "serde", "serde_json", "thiserror", + "tokio", "tracing", ] @@ -1578,6 +1583,7 @@ dependencies = [ "libp2p-swarm", "local-vm", "log", + "marine-wasmtime-backend", "parking_lot", "particle-protocol", "rand 0.8.5", @@ -2530,14 +2536,14 @@ dependencies = [ [[package]] name = "fluence-app-service" version = "0.35.2" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "log", "maplit", - "marine-min-it-version 0.3.2 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-runtime 0.36.2", - "marine-wasm-backend-traits 0.6.0", - "marine-wasmtime-backend 0.6.0", + "marine-min-it-version", + "marine-runtime", + "marine-wasm-backend-traits", + "marine-wasmtime-backend", "serde", "serde_derive", "serde_json", @@ -2615,7 +2621,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3794dff0e7e2851fee56651bf45f8d57c8be3c77c285a5f16fd86d4d6ed1037" dependencies = [ "eyre", - "marine-rs-sdk 0.14.0", + "marine-rs-sdk", "marine-sqlite-connector", "serde", "thiserror", @@ -3666,40 +3672,13 @@ dependencies = [ [[package]] name = "it-json-serde" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74b6ed688d9de56b4e4cb5aca2bd7a883909f1be8d8d6ba40e3a2d25b9feba5" -dependencies = [ - "serde", - "serde_derive", - "serde_json", - "thiserror", - "wasmer-interface-types-fl 0.27.0", -] - -[[package]] -name = "it-json-serde" -version = "0.5.1" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "serde", "serde_derive", "serde_json", "thiserror", - "wasmer-interface-types-fl 0.28.0", -] - -[[package]] -name = "it-lilo" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20108e77e11eeb1ef019f54c3868e0f2e9227295502f0702fa2e7e730ea748f8" -dependencies = [ - "anyhow", - "fluence-it-types", - "it-memory-traits 0.4.0", - "log", - "paste", - "thiserror", + "wasmer-interface-types-fl", ] [[package]] @@ -3712,21 +3691,12 @@ dependencies = [ "async-recursion", "fluence-it-types", "futures", - "it-memory-traits 0.5.0", + "it-memory-traits", "log", "paste", "thiserror", ] -[[package]] -name = "it-memory-traits" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d563f2a6baee17cf471b7951dfb96ab17fecc5e8947de39f1057cf3fb4cc906d" -dependencies = [ - "thiserror", -] - [[package]] name = "it-memory-traits" version = "0.5.0" @@ -4833,6 +4803,7 @@ dependencies = [ "libp2p", "log", "maplit", + "marine-wasmtime-backend", "now-millis", "parking_lot", "particle-args", @@ -4961,151 +4932,76 @@ dependencies = [ "serde", ] -[[package]] -name = "marine-core" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f40fac4650a022a2ce8d7b6df5614062fc32cb25fb44e61027997e90a3aff6" -dependencies = [ - "anyhow", - "bytesize", - "it-lilo 0.6.0", - "it-memory-traits 0.4.0", - "log", - "marine-it-generator 0.16.0", - "marine-it-interfaces 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "marine-it-parser 0.15.1", - "marine-min-it-version 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "marine-module-info-parser 0.14.0", - "marine-module-interface 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "marine-utils 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "marine-wasm-backend-traits 0.5.1", - "marine-wasmtime-backend 0.5.1", - "multimap 0.8.3", - "once_cell", - "paste", - "semver 1.0.20", - "serde", - "thiserror", - "wasmer-interface-types-fl 0.27.0", -] - [[package]] name = "marine-core" version = "0.30.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "anyhow", "bytesize", "futures", - "it-lilo 0.7.0", - "it-memory-traits 0.5.0", + "it-lilo", + "it-memory-traits", "log", - "marine-it-generator 0.17.0", - "marine-it-interfaces 0.9.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-it-parser 0.16.0", - "marine-min-it-version 0.3.2 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-module-info-parser 0.15.0", - "marine-module-interface 0.8.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-utils 0.5.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-wasm-backend-traits 0.6.0", - "marine-wasmtime-backend 0.6.0", + "marine-it-generator", + "marine-it-interfaces", + "marine-it-parser", + "marine-min-it-version", + "marine-module-info-parser", + "marine-module-interface", + "marine-utils", + "marine-wasm-backend-traits", + "marine-wasmtime-backend", "multimap 0.8.3", "once_cell", "paste", "semver 1.0.20", "serde", "thiserror", - "wasmer-interface-types-fl 0.28.0", -] - -[[package]] -name = "marine-it-generator" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bdd0119dc71f98e2f0a4bef305e43b9a4d9b9adbead12bc05b0fac1d5a247c" -dependencies = [ - "it-lilo 0.6.0", - "marine-it-parser 0.15.1", - "marine-macro-impl 0.14.0", - "once_cell", - "serde", - "serde_json", - "thiserror", - "walrus", - "wasmer-interface-types-fl 0.27.0", + "wasmer-interface-types-fl", ] [[package]] name = "marine-it-generator" version = "0.17.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ - "it-lilo 0.7.0", - "marine-it-parser 0.16.0", + "it-lilo", + "marine-it-parser", "marine-macro-impl 0.14.0", "once_cell", "serde", "serde_json", "thiserror", "walrus", - "wasmer-interface-types-fl 0.28.0", + "wasmer-interface-types-fl", ] [[package]] name = "marine-it-interfaces" version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c610d90a031911c17b2babc32c9fad7261bae6ab0bf118051cd665b5d9bcfbe" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "multimap 0.8.3", - "wasmer-interface-types-fl 0.27.0", -] - -[[package]] -name = "marine-it-interfaces" -version = "0.9.1" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" -dependencies = [ - "multimap 0.8.3", - "wasmer-interface-types-fl 0.28.0", -] - -[[package]] -name = "marine-it-parser" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921afa7f139791b24c4cb91c918d1ef7411ef40c3b801309ec43f6b2c89b107b" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "marine-it-interfaces 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "marine-module-interface 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "marine-wasm-backend-traits 0.5.1", - "nom", - "semver 1.0.20", - "serde", - "thiserror", - "walrus", - "wasmer-interface-types-fl 0.27.0", + "wasmer-interface-types-fl", ] [[package]] name = "marine-it-parser" version = "0.16.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "anyhow", "itertools 0.10.5", - "marine-it-interfaces 0.9.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-module-interface 0.8.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-wasm-backend-traits 0.6.0", + "marine-it-interfaces", + "marine-module-interface", + "marine-wasm-backend-traits", "nom", "semver 1.0.20", "serde", "thiserror", "walrus", - "wasmer-interface-types-fl 0.28.0", + "wasmer-interface-types-fl", ] [[package]] @@ -5203,49 +5099,22 @@ dependencies = [ [[package]] name = "marine-min-it-version" version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147e6e4c9d3dc9afbb06b2e3bc069b63c749733f698d0c364c320a72b133f1d5" -dependencies = [ - "once_cell", - "semver 1.0.20", -] - -[[package]] -name = "marine-min-it-version" -version = "0.3.2" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "once_cell", "semver 1.0.20", ] -[[package]] -name = "marine-module-info-parser" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b312830884d07fc495a43e867d9641163897f0b0b047842cf1172cc61f57075" -dependencies = [ - "anyhow", - "chrono", - "derivative", - "marine-rs-sdk-main 0.14.0", - "marine-wasm-backend-traits 0.5.1", - "semver 1.0.20", - "serde", - "thiserror", - "walrus", -] - [[package]] name = "marine-module-info-parser" version = "0.15.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "anyhow", "chrono", "derivative", "marine-rs-sdk-main 0.14.0", - "marine-wasm-backend-traits 0.6.0", + "marine-wasm-backend-traits", "semver 1.0.20", "serde", "thiserror", @@ -5255,47 +5124,17 @@ dependencies = [ [[package]] name = "marine-module-interface" version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92d2243bf0d3aea6401d9e57a1ee17677b624337981322e0153cc2d54744080" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "anyhow", "itertools 0.10.5", - "marine-it-interfaces 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "marine-it-interfaces", "nom", "semver 1.0.20", "serde", "thiserror", "walrus", - "wasmer-interface-types-fl 0.27.0", -] - -[[package]] -name = "marine-module-interface" -version = "0.8.1" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "marine-it-interfaces 0.9.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "nom", - "semver 1.0.20", - "serde", - "thiserror", - "walrus", - "wasmer-interface-types-fl 0.28.0", -] - -[[package]] -name = "marine-rs-sdk" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034cab8adf708e87db08f093e0c7b8ea49359cc875ed2a778c1bf245b5d9d9f8" -dependencies = [ - "marine-call-parameters 0.10.3", - "marine-macro 0.10.3", - "marine-rs-sdk-main 0.10.3", - "marine-timestamp-macro 0.10.3", - "serde", + "wasmer-interface-types-fl", ] [[package]] @@ -5307,7 +5146,7 @@ dependencies = [ "marine-call-parameters 0.14.0", "marine-macro 0.14.0", "marine-rs-sdk-main 0.14.0", - "marine-timestamp-macro 0.14.0", + "marine-timestamp-macro", "serde", ] @@ -5351,58 +5190,26 @@ dependencies = [ "serde", ] -[[package]] -name = "marine-runtime" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c599c7c13e976170a1211e31fe2fb4557e0479cbdba331b19a5a9e87f145f52" -dependencies = [ - "bytesize", - "it-json-serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "it-memory-traits 0.4.0", - "itertools 0.10.5", - "log", - "marine-call-parameters 0.10.3", - "marine-call-parameters 0.12.0", - "marine-call-parameters 0.13.0", - "marine-core 0.29.0", - "marine-module-interface 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "marine-rs-sdk 0.14.0", - "marine-rs-sdk-main 0.14.0", - "marine-utils 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "marine-wasm-backend-traits 0.5.1", - "marine-wasmtime-backend 0.5.1", - "parking_lot", - "safe-transmute", - "serde", - "serde_derive", - "serde_json", - "serde_with 2.3.3", - "thiserror", - "toml 0.5.11", - "wasmer-interface-types-fl 0.27.0", -] - [[package]] name = "marine-runtime" version = "0.36.2" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "bytesize", - "it-json-serde 0.5.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "it-memory-traits 0.5.0", + "it-json-serde", + "it-memory-traits", "itertools 0.10.5", "log", "marine-call-parameters 0.10.3", "marine-call-parameters 0.12.0", "marine-call-parameters 0.13.0", - "marine-core 0.30.0", - "marine-module-interface 0.8.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-rs-sdk 0.14.0", + "marine-core", + "marine-module-interface", + "marine-rs-sdk", "marine-rs-sdk-main 0.14.0", - "marine-utils 0.5.1 (git+https://github.com/fluencelabs/marine?branch=feat/async-call)", - "marine-wasm-backend-traits 0.6.0", - "marine-wasmtime-backend 0.6.0", + "marine-utils", + "marine-wasm-backend-traits", + "marine-wasmtime-backend", "parking_lot", "safe-transmute", "serde", @@ -5411,7 +5218,7 @@ dependencies = [ "serde_with 2.3.3", "thiserror", "toml 0.5.11", - "wasmer-interface-types-fl 0.28.0", + "wasmer-interface-types-fl", ] [[package]] @@ -5421,17 +5228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c4d82c7e8c07f59aa526271b810c97ec7f79d14a77725025618a79b0b1d9051" dependencies = [ "bytesize", - "marine-rs-sdk 0.14.0", -] - -[[package]] -name = "marine-timestamp-macro" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f812a03cb13b79ab75e38053a77ecc4b4738a1b485b650d971dec3dbbcb2561" -dependencies = [ - "chrono", - "quote", + "marine-rs-sdk", ] [[package]] @@ -5447,74 +5244,36 @@ dependencies = [ [[package]] name = "marine-utils" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce56bfabfd0af5326ff81c32c8d2261aa03b10e00ea6c165de4ebf8a3f998e4" - -[[package]] -name = "marine-utils" -version = "0.5.1" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" - -[[package]] -name = "marine-wasm-backend-traits" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "220bc47cfabb8b4ab97bf2bd7bbab9738857b69beeda0a1ac5776c600b64bb46" -dependencies = [ - "anyhow", - "it-memory-traits 0.4.0", - "multimap 0.8.3", - "paste", - "thiserror", - "wasmer-interface-types-fl 0.27.0", - "wasmparser 0.101.1", -] +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" [[package]] name = "marine-wasm-backend-traits" version = "0.6.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "anyhow", "futures", - "it-memory-traits 0.5.0", + "it-memory-traits", "multimap 0.8.3", "paste", "thiserror", - "wasmer-interface-types-fl 0.28.0", + "wasmer-interface-types-fl", "wasmparser 0.101.1", ] -[[package]] -name = "marine-wasmtime-backend" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa0dc5a7da0e3334f3ce5b341ba4354341af9a1f9efae24884a1b931efdf23e" -dependencies = [ - "anyhow", - "it-memory-traits 0.4.0", - "log", - "marine-wasm-backend-traits 0.5.1", - "multimap 0.8.3", - "paste", - "wasmer-interface-types-fl 0.27.0", - "wasmtime", - "wasmtime-wasi", -] - [[package]] name = "marine-wasmtime-backend" version = "0.6.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#e8d89e3de1f21e0678e3722e2e1e31ba74fba2ac" +source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" dependencies = [ "anyhow", "futures", - "it-memory-traits 0.5.0", + "it-memory-traits", "log", - "marine-wasm-backend-traits 0.6.0", + "marine-wasm-backend-traits", "multimap 0.8.3", "paste", - "wasmer-interface-types-fl 0.28.0", + "wasmer-interface-types-fl", "wasmtime", "wasmtime-wasi", ] @@ -6436,8 +6195,8 @@ dependencies = [ "libipld", "log", "maplit", - "marine-it-parser 0.16.0", - "marine-module-info-parser 0.15.0", + "marine-it-parser", + "marine-module-info-parser", "parking_lot", "particle-args", "particle-execution", @@ -6454,7 +6213,7 @@ dependencies = [ name = "particle-protocol" version = "0.3.0" dependencies = [ - "air-interpreter-sede", + "air-interpreter-sede 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "asynchronous-codec 0.7.0", "base64 0.21.7", "derivative", @@ -6706,8 +6465,6 @@ dependencies = [ [[package]] name = "polyplets" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77452f7f8d029801e32bc975404918f45c338183416a2aa2cb3d59c5c922446" dependencies = [ "marine-call-parameters 0.14.0", "serde", @@ -9387,28 +9144,6 @@ dependencies = [ "leb128", ] -[[package]] -name = "wasmer-interface-types-fl" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62958478f282fbf2b05c12f9630972bd8194937de1ab22d6a59d43093be32886" -dependencies = [ - "anyhow", - "fluence-it-types", - "it-lilo 0.6.0", - "it-memory-traits 0.4.0", - "it-to-bytes", - "itertools 0.10.5", - "log", - "nom", - "safe-transmute", - "semver 1.0.20", - "serde", - "serde_json", - "thiserror", - "wast 8.0.0", -] - [[package]] name = "wasmer-interface-types-fl" version = "0.28.0" @@ -9418,8 +9153,8 @@ dependencies = [ "anyhow", "fluence-it-types", "futures", - "it-lilo 0.7.0", - "it-memory-traits 0.5.0", + "it-lilo", + "it-memory-traits", "it-to-bytes", "itertools 0.10.5", "log", diff --git a/Cargo.toml b/Cargo.toml index 00cbd62e55..8769075f7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,9 +114,10 @@ fluence-app-service = { version = "=0.35.2", git = "https://github.com/fluencela marine-utils = "0.5.1" marine-it-parser = { version = "0.16.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } marine-module-info-parser = { version = "0.15.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } +marine-wasmtime-backend = { version = "0.6.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } # avm -avm-server = "=0.37.0" +avm-server = { version = "=0.37.0", path = "../aquavm/avm/server" } air-interpreter-wasm = "=0.62.0" # libp2p diff --git a/aquamarine/Cargo.toml b/aquamarine/Cargo.toml index 96b75fa0f0..328e331862 100644 --- a/aquamarine/Cargo.toml +++ b/aquamarine/Cargo.toml @@ -20,6 +20,8 @@ workers = { workspace = true } types = { workspace = true } avm-server = { workspace = true } +marine-wasmtime-backend = { workspace = true } +fluence-app-service = { workspace = true } libp2p = { workspace = true } fluence-keypair = { workspace = true } diff --git a/aquamarine/src/aqua_runtime.rs b/aquamarine/src/aqua_runtime.rs index a0664b8cb2..f489d2c24a 100644 --- a/aquamarine/src/aqua_runtime.rs +++ b/aquamarine/src/aqua_runtime.rs @@ -21,6 +21,7 @@ use avm_server::avm_runner::{AVMRunner, RawAVMOutcome}; use avm_server::{ AVMMemoryStats, AVMRuntimeLimits, CallRequests, CallResults, ParticleParameters, RunnerError, }; +use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; use fluence_keypair::KeyPair; use libp2p::PeerId; use tracing::Level; @@ -55,24 +56,38 @@ pub trait AquaRuntime: Sized + Send + 'static { fn memory_stats(&self) -> AVMMemoryStats; } -impl AquaRuntime for AVMRunner { +impl AquaRuntime for AVMRunner { type Config = VmConfig; type Error = RunnerError; /// Creates `AVM` in background (on blocking threadpool) fn create_runtime(config: Self::Config, waker: Waker) -> Result { + let mut wasmtime_config = WasmtimeConfig::default(); + // TODO async-marine: impl proper configuration + // TODO async-marine: move to the right place + // TODO async-marine: maybe use the same as for ParticleAppServices + wasmtime_config + .debug_info(true) + .wasm_backtrace(true) + .epoch_interruption(true) + .async_wasm_stack(2 * 1024 * 1024) + .max_wasm_stack(2 * 1024 * 1024); + let backend = WasmtimeWasmBackend::new(wasmtime_config) + .map_err(|e| Self::Error::MarineError( + fluence_app_service::MarineError::EngineError(e.into())))?; let avm_runtime_limits = AVMRuntimeLimits::new( config.air_size_limit, config.particle_size_limit, config.call_result_size_limit, config.hard_limit_enabled, ); - let vm: AVMRunner = AVMRunner::new( + let vm: AVMRunner = tokio::runtime::Handle::current().block_on(AVMRunner::new( config.air_interpreter, config.max_heap_size, avm_runtime_limits, i32::MAX, - )?; + backend, + ))?; waker.wake(); Ok(vm) } @@ -131,7 +146,7 @@ impl AquaRuntime for AVMRunner { call_results: CallResults, key_pair: &KeyPair, ) -> Result { - AVMRunner::call( + tokio::runtime::Handle::current().block_on(AVMRunner::call( self, air, prev_data, @@ -143,7 +158,7 @@ impl AquaRuntime for AVMRunner { call_results, key_pair, particle_params.particle_id.to_string(), - ) + )) } fn memory_stats(&self) -> AVMMemoryStats { diff --git a/aquamarine/src/lib.rs b/aquamarine/src/lib.rs index 55dd954e88..2a35b6d3d8 100644 --- a/aquamarine/src/lib.rs +++ b/aquamarine/src/lib.rs @@ -46,11 +46,13 @@ mod particle_effects; mod health; mod vm_pool; +use marine_wasmtime_backend::WasmtimeWasmBackend; + pub use crate::aqua_runtime::AquaRuntime; pub use crate::aquamarine::{AquamarineApi, AquamarineBackend}; pub use crate::config::{DataStoreConfig, VmConfig, VmPoolConfig}; pub use crate::particle_effects::{InterpretationStats, ParticleEffects, RemoteRoutingEffects}; -pub use avm_server::avm_runner::AVMRunner; +pub type AVMRunner = avm_server::avm_runner::AVMRunner; pub use error::AquamarineApiError; pub use particle_data_store::{DataStoreError, ParticleDataStore}; pub use plumber::Plumber; diff --git a/crates/connected-client/Cargo.toml b/crates/connected-client/Cargo.toml index b06de0fde5..5ae008668f 100644 --- a/crates/connected-client/Cargo.toml +++ b/crates/connected-client/Cargo.toml @@ -9,6 +9,7 @@ particle-protocol = { workspace = true } fluence-libp2p = { workspace = true } test-constants = { workspace = true } local-vm = { workspace = true } +marine-wasmtime-backend = { workspace = true } fluence-keypair = { workspace = true } libp2p = { workspace = true, features = ["identify"] } diff --git a/crates/connected-client/src/connected_client.rs b/crates/connected-client/src/connected_client.rs index 5287d9f5a0..e731333370 100644 --- a/crates/connected-client/src/connected_client.rs +++ b/crates/connected-client/src/connected_client.rs @@ -24,6 +24,7 @@ use fluence_keypair::KeyPair; use fluence_libp2p::Transport; use libp2p::{core::Multiaddr, PeerId}; use local_vm::{make_particle, make_vm, read_args, ParticleDataStore}; +use marine_wasmtime_backend::WasmtimeWasmBackend; use particle_protocol::Particle; use serde_json::{Value as JValue, Value}; use tempfile::TempDir; @@ -35,7 +36,7 @@ use crate::client::Client; use crate::event::ClientEvent; #[allow(clippy::upper_case_acronyms)] -type AVM = local_vm::AVMRunner; +type AVM = local_vm::AVMRunner; pub struct ConnectedClient { pub client: Client, @@ -158,7 +159,7 @@ impl ConnectedClient { self.local_vm .get_or_init(|| async { let dir = self.tmp_dir.path(); - tokio::sync::Mutex::new(make_vm(dir)) + tokio::sync::Mutex::new(make_vm(dir).await) }) .await } diff --git a/crates/local-vm/Cargo.toml b/crates/local-vm/Cargo.toml index fc03ac6c73..6c8065af2b 100644 --- a/crates/local-vm/Cargo.toml +++ b/crates/local-vm/Cargo.toml @@ -16,6 +16,7 @@ air-interpreter-fs = { workspace = true } fluence-keypair = { workspace = true } air-interpreter-wasm = { workspace = true } avm-server = { workspace = true } +marine-wasmtime-backend = { workspace = true } libp2p = { workspace = true } fstrings = { workspace = true } serde_json = { workspace = true } diff --git a/crates/local-vm/src/local_vm.rs b/crates/local-vm/src/local_vm.rs index 916d6db092..111d61a645 100644 --- a/crates/local-vm/src/local_vm.rs +++ b/crates/local-vm/src/local_vm.rs @@ -22,6 +22,7 @@ use std::{collections::HashMap, time::Duration}; use avm_server::avm_runner::{AVMRunner, RawAVMOutcome}; use avm_server::{CallResults, CallServiceResult}; +use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; use fstrings::f; use libp2p::PeerId; use serde_json::{json, Value as JValue}; @@ -170,11 +171,25 @@ pub fn host_call(data: &HashMap, args: Args) -> (CallServiceResu (outcome, result.returned) } -pub fn make_vm(tmp_dir_path: &Path) -> AVMRunner { +pub fn make_wasm_backend() -> WasmtimeWasmBackend { + let mut wasmtime_config = WasmtimeConfig::default(); + // TODO async-marine: impl proper configuration + wasmtime_config + .debug_info(true) + .wasm_backtrace(true) + .epoch_interruption(true) + .async_wasm_stack(2 * 1024 * 1024) + .max_wasm_stack(2 * 1024 * 1024); + WasmtimeWasmBackend::new(wasmtime_config) + .expect("Cannot create WasmtimeWasmBackend") +} + +pub async fn make_vm(tmp_dir_path: &Path) -> AVMRunner { let interpreter = air_interpreter_path(tmp_dir_path); write_default_air_interpreter(&interpreter).expect("write air interpreter"); - AVMRunner::new(interpreter, None, <_>::default(), i32::MAX) + AVMRunner::new(interpreter, None, <_>::default(), i32::MAX, make_wasm_backend()) + .await .map_err(|err| { log::error!("\n\n\nFailed to create local AVM: {:#?}\n\n\n", err); @@ -236,7 +251,7 @@ pub async fn make_particle( service_in: &HashMap, script: String, relay: impl Into>, - local_vm: &mut AVMRunner, + local_vm: &mut AVMRunner, data_store: Arc, generated: bool, particle_ttl: Duration, @@ -289,6 +304,7 @@ pub async fn make_particle( key_pair, id.clone(), ) + .await .expect("execute & make particle"); data_store @@ -330,7 +346,7 @@ pub async fn make_particle( pub async fn read_args( particle: Particle, peer_id: PeerId, - local_vm: &mut AVMRunner, + local_vm: &mut AVMRunner, data_store: Arc, key_pair: &KeyPair, ) -> Option, Vec>> { @@ -363,6 +379,7 @@ pub async fn read_args( key_pair, particle.id.clone(), ) + .await .expect("execute & make particle"); data_store diff --git a/crates/nox-tests/tests/local_vm.rs b/crates/nox-tests/tests/local_vm.rs index 6fd0e37109..a1228f5a5e 100644 --- a/crates/nox-tests/tests/local_vm.rs +++ b/crates/nox-tests/tests/local_vm.rs @@ -53,8 +53,8 @@ async fn make() { create_dir(&local_vm_path_a).expect("Could not create tmp dir"); create_dir(&local_vm_path_b).expect("Could not create tmp dir"); - let mut local_vm_a = make_vm(local_vm_path_a.as_path()); - let mut local_vm_b = make_vm(local_vm_path_b.as_path()); + let mut local_vm_a = make_vm(local_vm_path_a.as_path()).await; + let mut local_vm_b = make_vm(local_vm_path_b.as_path()).await; let script = r#"(call client_b ("return" "") [a b c])"#.to_string(); let data = hashmap! { diff --git a/nox/src/main.rs b/nox/src/main.rs index 75ca409b18..a581190cbb 100644 --- a/nox/src/main.rs +++ b/nox/src/main.rs @@ -36,8 +36,7 @@ use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use air_interpreter_fs::write_default_air_interpreter; -use aquamarine::{DataStoreConfig, VmConfig}; -use avm_server::avm_runner::AVMRunner; +use aquamarine::{DataStoreConfig, VmConfig, AVMRunner}; use config_utils::to_peer_id; use core_manager::{CoreManager, CoreManagerFunctions, DevCoreManager, StrictCoreManager}; use fs_utils::to_abs_path; diff --git a/nox/src/node.rs b/nox/src/node.rs index 69f9e81b27..8afb4073bf 100644 --- a/nox/src/node.rs +++ b/nox/src/node.rs @@ -735,14 +735,13 @@ mod tests { use std::sync::Arc; use std::time::Duration; - use avm_server::avm_runner::AVMRunner; use libp2p::core::Multiaddr; use libp2p::PeerId; use maplit::hashmap; use serde_json::json; use air_interpreter_fs::{air_interpreter_path, write_default_air_interpreter}; - use aquamarine::{DataStoreConfig, VmConfig}; + use aquamarine::{AVMRunner, DataStoreConfig, VmConfig}; use config_utils::to_peer_id; use connected_client::ConnectedClient; use core_manager::DummyCoreManager; From 83092fee10ea04bcb8bbf6fee5f23da822593338 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 2 Apr 2024 14:44:36 +0300 Subject: [PATCH 05/33] remove block_on for marine call --- Cargo.lock | 22 +- Cargo.toml | 6 +- aquamarine/src/aqua_runtime.rs | 23 +- crates/local-vm/src/local_vm.rs | 27 ++- crates/nox-tests/tests/services.rs | 2 +- crates/spell-service-api/src/lib.rs | 74 +++--- crates/system-services/Cargo.toml | 1 + crates/system-services/src/deployer.rs | 166 +++++++------ crates/system-services/src/distro.rs | 157 +++++++----- crates/system-services/src/lib.rs | 49 ++-- nox/src/main.rs | 2 +- nox/src/node.rs | 3 +- particle-builtins/src/builtins.rs | 118 +++++---- particle-services/Cargo.toml | 1 + particle-services/src/app_services.rs | 324 ++++++++++++++----------- particle-services/src/persistence.rs | 4 +- sorcerer/src/script_executor.rs | 36 ++- sorcerer/src/sorcerer.rs | 18 +- sorcerer/src/spell_builtins.rs | 35 ++- sorcerer/src/worker_builins.rs | 33 +-- spell-storage/src/storage.rs | 7 +- 21 files changed, 669 insertions(+), 439 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44a47ad9cc..1fdde05966 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,8 +95,9 @@ dependencies = [ [[package]] name = "air-interpreter-interface" version = "0.19.0" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" dependencies = [ - "air-interpreter-sede 0.1.0", + "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", "air-interpreter-value", "fluence-it-types", "marine-call-parameters 0.14.0", @@ -109,8 +110,9 @@ dependencies = [ [[package]] name = "air-interpreter-sede" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433b1ca3538f5f6a6083646b2aa61cd57a08c1558091f6be47b2299fc7b28261" dependencies = [ - "marine-rs-sdk", "rmp-serde", "serde", "serde_bytes", @@ -122,9 +124,9 @@ dependencies = [ [[package]] name = "air-interpreter-sede" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433b1ca3538f5f6a6083646b2aa61cd57a08c1558091f6be47b2299fc7b28261" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" dependencies = [ + "marine-rs-sdk", "rmp-serde", "serde", "serde_bytes", @@ -136,6 +138,7 @@ dependencies = [ [[package]] name = "air-interpreter-value" version = "0.1.0" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" dependencies = [ "serde", "serde_json", @@ -153,6 +156,7 @@ dependencies = [ [[package]] name = "air-utils" version = "0.3.0" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" [[package]] name = "allocator-api2" @@ -737,6 +741,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "avm-data-store" version = "0.7.9" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" dependencies = [ "avm-interface", "serde", @@ -746,9 +751,10 @@ dependencies = [ [[package]] name = "avm-interface" version = "0.32.1" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" dependencies = [ "air-interpreter-interface", - "air-interpreter-sede 0.1.0", + "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", "air-utils", "log", "maplit", @@ -762,9 +768,10 @@ dependencies = [ [[package]] name = "avm-server" version = "0.37.0" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" dependencies = [ "air-interpreter-interface", - "air-interpreter-sede 0.1.0", + "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", "air-utils", "avm-data-store", "avm-interface", @@ -6249,6 +6256,7 @@ dependencies = [ "fluence-keypair", "fluence-libp2p", "fs-utils", + "futures", "health", "humantime-serde", "json-utils", @@ -6465,6 +6473,7 @@ dependencies = [ [[package]] name = "polyplets" version = "0.7.0" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" dependencies = [ "marine-call-parameters 0.14.0", "serde", @@ -8132,6 +8141,7 @@ name = "system-services" version = "0.1.0" dependencies = [ "aqua-ipfs-distro", + "async-trait", "decider-distro", "eyre", "fluence-app-service", diff --git a/Cargo.toml b/Cargo.toml index 8769075f7d..01d5d0d6b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,11 +113,11 @@ fluence-spell-distro = "=0.7.5" fluence-app-service = { version = "=0.35.2", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call", features = ["wasmtime"] } marine-utils = "0.5.1" marine-it-parser = { version = "0.16.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } -marine-module-info-parser = { version = "0.15.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } -marine-wasmtime-backend = { version = "0.6.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } +marine-module-info-parser = { version = "0.15.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } +marine-wasmtime-backend = { version = "0.6.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } # avm -avm-server = { version = "=0.37.0", path = "../aquavm/avm/server" } +avm-server = { git = "https://github.com/fluencelabs/aquavm", version = "=0.37.0", branch = "feat/use-async-marine" } air-interpreter-wasm = "=0.62.0" # libp2p diff --git a/aquamarine/src/aqua_runtime.rs b/aquamarine/src/aqua_runtime.rs index f489d2c24a..701d6bbefb 100644 --- a/aquamarine/src/aqua_runtime.rs +++ b/aquamarine/src/aqua_runtime.rs @@ -21,9 +21,9 @@ use avm_server::avm_runner::{AVMRunner, RawAVMOutcome}; use avm_server::{ AVMMemoryStats, AVMRuntimeLimits, CallRequests, CallResults, ParticleParameters, RunnerError, }; -use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; use fluence_keypair::KeyPair; use libp2p::PeerId; +use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; use tracing::Level; use crate::config::VmConfig; @@ -72,22 +72,23 @@ impl AquaRuntime for AVMRunner { .epoch_interruption(true) .async_wasm_stack(2 * 1024 * 1024) .max_wasm_stack(2 * 1024 * 1024); - let backend = WasmtimeWasmBackend::new(wasmtime_config) - .map_err(|e| Self::Error::MarineError( - fluence_app_service::MarineError::EngineError(e.into())))?; + let backend = WasmtimeWasmBackend::new(wasmtime_config).map_err(|e| { + Self::Error::MarineError(fluence_app_service::MarineError::EngineError(e.into())) + })?; let avm_runtime_limits = AVMRuntimeLimits::new( config.air_size_limit, config.particle_size_limit, config.call_result_size_limit, config.hard_limit_enabled, ); - let vm: AVMRunner = tokio::runtime::Handle::current().block_on(AVMRunner::new( - config.air_interpreter, - config.max_heap_size, - avm_runtime_limits, - i32::MAX, - backend, - ))?; + let vm: AVMRunner = + tokio::runtime::Handle::current().block_on(AVMRunner::new( + config.air_interpreter, + config.max_heap_size, + avm_runtime_limits, + i32::MAX, + backend, + ))?; waker.wake(); Ok(vm) } diff --git a/crates/local-vm/src/local_vm.rs b/crates/local-vm/src/local_vm.rs index 111d61a645..3294b60420 100644 --- a/crates/local-vm/src/local_vm.rs +++ b/crates/local-vm/src/local_vm.rs @@ -22,9 +22,9 @@ use std::{collections::HashMap, time::Duration}; use avm_server::avm_runner::{AVMRunner, RawAVMOutcome}; use avm_server::{CallResults, CallServiceResult}; -use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; use fstrings::f; use libp2p::PeerId; +use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; use serde_json::{json, Value as JValue}; use air_interpreter_fs::{air_interpreter_path, write_default_air_interpreter}; @@ -180,24 +180,29 @@ pub fn make_wasm_backend() -> WasmtimeWasmBackend { .epoch_interruption(true) .async_wasm_stack(2 * 1024 * 1024) .max_wasm_stack(2 * 1024 * 1024); - WasmtimeWasmBackend::new(wasmtime_config) - .expect("Cannot create WasmtimeWasmBackend") + WasmtimeWasmBackend::new(wasmtime_config).expect("Cannot create WasmtimeWasmBackend") } pub async fn make_vm(tmp_dir_path: &Path) -> AVMRunner { let interpreter = air_interpreter_path(tmp_dir_path); write_default_air_interpreter(&interpreter).expect("write air interpreter"); - AVMRunner::new(interpreter, None, <_>::default(), i32::MAX, make_wasm_backend()) - .await - .map_err(|err| { - log::error!("\n\n\nFailed to create local AVM: {:#?}\n\n\n", err); + AVMRunner::new( + interpreter, + None, + <_>::default(), + i32::MAX, + make_wasm_backend(), + ) + .await + .map_err(|err| { + log::error!("\n\n\nFailed to create local AVM: {:#?}\n\n\n", err); - println!("\n\n\nFailed to create local AVM: {err:#?}\n\n\n"); + println!("\n\n\nFailed to create local AVM: {err:#?}\n\n\n"); - err - }) - .expect("vm should be created") + err + }) + .expect("vm should be created") } pub fn wrap_script( diff --git a/crates/nox-tests/tests/services.rs b/crates/nox-tests/tests/services.rs index 9a99fdf84e..b0cc8239c6 100644 --- a/crates/nox-tests/tests/services.rs +++ b/crates/nox-tests/tests/services.rs @@ -59,7 +59,7 @@ async fn test_system_service_override() { config, }; let name = service_name.clone(); - let init: system_services::InitService = Box::new(move |call, status| { + let init: dyn system_services::InitService = Box::new(move |call, status| { let name = name.clone(); let service_status = status .services diff --git a/crates/spell-service-api/src/lib.rs b/crates/spell-service-api/src/lib.rs index 2f2a088cd7..05ebe90fe1 100644 --- a/crates/spell-service-api/src/lib.rs +++ b/crates/spell-service-api/src/lib.rs @@ -111,24 +111,24 @@ impl SpellServiceApi { Self { services } } - pub fn set_script(&self, params: CallParams, script: String) -> Result<(), CallError> { + pub async fn set_script(&self, params: CallParams, script: String) -> Result<(), CallError> { let function = Function { name: "set_script", args: vec![json!(script)], }; - let _ = self.call::(params, function)?; + let _ = self.call::(params, function).await?; Ok(()) } - pub fn get_script(&self, params: CallParams) -> Result { + pub async fn get_script(&self, params: CallParams) -> Result { let function = Function { name: "get_script", args: vec![], }; - let script_value = self.call::(params, function)?; + let script_value = self.call::(params, function).await?; Ok(script_value.value) } - pub fn set_trigger_config( + pub async fn set_trigger_config( &self, params: CallParams, config: TriggerConfig, @@ -137,39 +137,43 @@ impl SpellServiceApi { name: "set_trigger_config", args: vec![json!(config)], }; - let _ = self.call::(params, function)?; + let _ = self.call::(params, function).await?; Ok(()) } - pub fn get_trigger_config(&self, params: CallParams) -> Result { + pub async fn get_trigger_config(&self, params: CallParams) -> Result { let function = Function { name: "get_trigger_config", args: vec![], }; - let trigger_config_value = self.call::(params, function)?; + let trigger_config_value = self.call::(params, function).await?; Ok(trigger_config_value.config) } // TODO: use `Map` for init_data instead of `Value` - pub fn update_kv(&self, params: CallParams, kv_data: Value) -> Result<(), CallError> { + pub async fn update_kv(&self, params: CallParams, kv_data: Value) -> Result<(), CallError> { let function = Function { name: "set_json_fields", args: vec![json!(kv_data.to_string())], }; - let _ = self.call::(params, function)?; + let _ = self.call::(params, function).await?; Ok(()) } - pub fn get_string(&self, params: CallParams, key: String) -> Result, CallError> { + pub async fn get_string( + &self, + params: CallParams, + key: String, + ) -> Result, CallError> { let function = Function { name: "get_string", args: vec![json!(key)], }; - let result = self.call::(params, function)?; + let result = self.call::(params, function).await?; Ok((!result.absent).then_some(result.value)) } - pub fn set_string( + pub async fn set_string( &self, params: CallParams, key: String, @@ -179,60 +183,68 @@ impl SpellServiceApi { name: "set_string", args: vec![json!(key), json!(value)], }; - let _ = self.call::(params, function)?; + let _ = self.call::(params, function).await?; Ok(()) } /// Load the counter (how many times the spell was run) - pub fn get_counter(&self, params: CallParams) -> Result, CallError> { + pub async fn get_counter(&self, params: CallParams) -> Result, CallError> { let function = Function { name: "get_u32", args: vec![json!("hw_counter")], }; - let result = self.call::(params, function)?; + let result = self.call::(params, function).await?; Ok((!result.absent).then_some(result.value)) } /// Update the counter (how many times the spell was run) /// TODO: permission check here or not? - pub fn set_counter(&self, params: CallParams, counter: u32) -> Result<(), CallError> { + pub async fn set_counter(&self, params: CallParams, counter: u32) -> Result<(), CallError> { let function = Function { name: "set_u32", args: vec![json!("hw_counter"), json!(counter)], }; - let _ = self.call::(params, function)?; + let _ = self.call::(params, function).await?; Ok(()) } - pub fn set_trigger_event(&self, params: CallParams, event: String) -> Result<(), CallError> { + pub async fn set_trigger_event( + &self, + params: CallParams, + event: String, + ) -> Result<(), CallError> { self.set_string(params, "hw_trigger".to_string(), event) + .await } - pub fn store_error(&self, params: CallParams, args: Vec) -> Result<(), CallError> { + pub async fn store_error(&self, params: CallParams, args: Vec) -> Result<(), CallError> { let function = Function { name: "store_error", args, }; - let _ = self.call::(params, function)?; + let _ = self.call::(params, function).await?; Ok(()) } - fn call(&self, params: CallParams, function: Function) -> Result + async fn call(&self, params: CallParams, function: Function) -> Result where T: DeserializeOwned + SpellValueT, { use CallError::*; let spell_id = params.spell_id; - let result = self.services.call_function( - params.peer_scope, - &spell_id, - function.name, - function.args, - params.particle_id, - params.init_peer_id, - params.ttl, - ); + let result = self + .services + .call_function( + params.peer_scope, + &spell_id, + function.name, + function.args, + params.particle_id, + params.init_peer_id, + params.ttl, + ) + .await; match result { FunctionOutcome::NotDefined { .. } => Err(ServiceNotFound { spell_id, diff --git a/crates/system-services/Cargo.toml b/crates/system-services/Cargo.toml index c7f11b268e..78277d7549 100644 --- a/crates/system-services/Cargo.toml +++ b/crates/system-services/Cargo.toml @@ -19,6 +19,7 @@ libp2p = { workspace = true } log = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } +async-trait = { workspace = true } fluence-spell-dtos = { workspace = true } tracing = { workspace = true } diff --git a/crates/system-services/src/deployer.rs b/crates/system-services/src/deployer.rs index a159b538b0..8d12979f12 100644 --- a/crates/system-services/src/deployer.rs +++ b/crates/system-services/src/deployer.rs @@ -1,6 +1,7 @@ use crate::distro::*; -use crate::CallService; -use crate::{DeploymentStatus, PackageDistro, ServiceDistro, ServiceStatus, SpellDistro}; +use crate::{CallService, FunctionName, ServiceName}; +use crate::{Deployment, PackageDistro, ServiceDistro, ServiceStatus, SpellDistro}; +use async_trait::async_trait; use eyre::eyre; use futures::{FutureExt, StreamExt, TryStreamExt}; use libp2p::PeerId; @@ -88,16 +89,17 @@ impl Deployer { let services = self.services.clone(); let root_worker_id = self.host_peer_id; - let call: CallService = Box::new(move |srv, fnc, args| { - call_service(&services, PeerScope::Host, root_worker_id, &srv, &fnc, args) - }); - + let call: &dyn CallService = &CallServiceParams { + services: &services, + peer_scope: PeerScope::Host, + init_peer_id: root_worker_id, + }; let parallelism = available_parallelism() .map(|x| x.get()) .unwrap_or(DEFAULT_PARALLELISM); futures::stream::iter(self.system_service_distros.distros.values()) - .map(|distro| async { self.deploy_package(&call, distro.clone()).await }.boxed()) + .map(|distro| async { self.deploy_package(call, distro.clone()).await }.boxed()) .boxed() .buffer_unordered(parallelism) .try_collect::>() @@ -106,7 +108,11 @@ impl Deployer { Ok(()) } - async fn deploy_package(&self, call: &CallService, package: PackageDistro) -> eyre::Result<()> { + async fn deploy_package( + &self, + call_service: &dyn CallService, + package: PackageDistro, + ) -> eyre::Result<()> { let mut services = HashMap::new(); for service_distro in package.services { let name = service_distro.name.clone(); @@ -120,10 +126,10 @@ impl Deployer { let result = self.deploy_system_spell(spell_distro).await?; spells.insert(name, result); } - let status = DeploymentStatus { services, spells }; + let status = Deployment { services, spells }; if let Some(init) = package.init { - init(call, status)?; + init.init(call_service, status).await?; } Ok(()) @@ -131,7 +137,7 @@ impl Deployer { async fn deploy_system_spell(&self, spell_distro: SpellDistro) -> eyre::Result { let spell_name = spell_distro.name.clone(); - match self.find_same_spell(&spell_distro) { + match self.find_same_spell(&spell_distro).await { Some(spell_id) => { tracing::debug!( spell_name, @@ -193,12 +199,16 @@ impl Deployer { ); // update trigger config let config = spell_distro.trigger_config.clone(); - self.spells_api.set_trigger_config(params.clone(), config)?; + self.spells_api + .set_trigger_config(params.clone(), config) + .await?; // update spell script let air = spell_distro.air.to_string(); - self.spells_api.set_script(params.clone(), air)?; + self.spells_api.set_script(params.clone(), air).await?; // update init_data without affecting other keys - self.spells_api.update_kv(params, json!(spell_distro.kv))?; + self.spells_api + .update_kv(params, json!(spell_distro.kv)) + .await?; // resubscribe spell if let Some(trigger_config) = trigger_config { @@ -258,10 +268,11 @@ impl Deployer { } // Two spells are the same if they have the same alias - fn find_same_spell(&self, new_spell: &SpellDistro) -> Option { - let existing_spell = - self.services - .get_service_info(PeerScope::Host, new_spell.name.to_string(), ""); + async fn find_same_spell(&self, new_spell: &SpellDistro) -> Option { + let existing_spell = self + .services + .get_service_info(PeerScope::Host, new_spell.name.to_string(), "") + .await; match existing_spell { Err(ServiceError::NoSuchService(_, _)) => { log::debug!("no existing spell found for {}", new_spell.name); @@ -293,7 +304,10 @@ impl Deployer { let service_name = service_distro.name.clone(); let blueprint_id = self.add_modules(service_distro)?; - match self.find_same_service(service_name.to_string(), &blueprint_id) { + match self + .find_same_service(service_name.to_string(), &blueprint_id) + .await + { ServiceUpdateStatus::NeedUpdate(service_id) => { tracing::debug!(service_name, service_id, "found existing service that needs to be updated; will remove the old service and deploy a new one"); let result = self @@ -345,12 +359,17 @@ impl Deployer { Ok(ServiceStatus::Created(service_id)) } - fn find_same_service(&self, service_name: String, blueprint_id: &str) -> ServiceUpdateStatus { + async fn find_same_service( + &self, + service_name: String, + blueprint_id: &str, + ) -> ServiceUpdateStatus { // Check that the service exist and has the same blueprint. // In this case, we don't create a new one. - let existing_service = - self.services - .get_service_info(PeerScope::Host, service_name.to_string(), ""); + let existing_service = self + .services + .get_service_info(PeerScope::Host, service_name.to_string(), "") + .await; if let Ok(service) = existing_service { if service.service_type == ServiceType::Spell { log::warn!( @@ -402,55 +421,66 @@ impl Deployer { } } -fn call_service( - services: &ParticleAppServices, +struct CallServiceParams<'a> { + services: &'a ParticleAppServices, peer_scope: PeerScope, init_peer_id: PeerId, - service_id: &str, - function_name: &str, - args: Vec, -) -> eyre::Result<()> { - let result = services.call_function( - peer_scope, - service_id, - function_name, - args, - None, - init_peer_id, - DEPLOYER_TTL, - ); - // similar to process_func_outcome in sorcerer/src/utils.rs, but that func is - // to specialized to spell specific - match result { - FunctionOutcome::Ok(result) => { - let call_result: Option> = try { - let result = result.as_object()?; - let is_success = result["success"].as_bool()?; - if !is_success { - if let Some(error) = result["error"].as_str() { - Err(eyre!( - "Call {service_id}.{function_name} returned error: {}", - error - )) +} + +#[async_trait] +impl<'a> CallService for CallServiceParams<'a> { + async fn call( + &self, + service_name: ServiceName, + function_name: FunctionName, + args: Vec, + ) -> eyre::Result<()> { + let service_id = service_name; + let result = self + .services + .call_function( + self.peer_scope, + service_id.as_str(), + function_name.as_str(), + args, + None, + self.init_peer_id, + DEPLOYER_TTL, + ) + .await; + // similar to process_func_outcome in sorcerer/src/utils.rs, but that func is + // to specialized to spell specific + match result { + FunctionOutcome::Ok(result) => { + let call_result: Option> = try { + let result = result.as_object()?; + let is_success = result["success"].as_bool()?; + if !is_success { + if let Some(error) = result["error"].as_str() { + Err(eyre!( + "Call {service_id}.{function_name} returned error: {}", + error + )) + } else { + Err(eyre!("Call {service_id}.{function_name} returned error")) + } } else { - Err(eyre!("Call {service_id}.{function_name} returned error")) + Ok(()) } - } else { - Ok(()) - } - }; - call_result.unwrap_or_else(|| { - Err(eyre!( - "Call {service_id}.{function_name} return invalid result: {result}" - )) - }) - } - FunctionOutcome::NotDefined { .. } => { - Err(eyre!("Service {service_id} ({function_name}) not found")) + }; + call_result.unwrap_or_else(|| { + Err(eyre!( + "Call {service_id}.{function_name} return invalid result: {result}" + )) + }) + } + FunctionOutcome::NotDefined { .. } => { + Err(eyre!("Service {service_id} ({function_name}) not found")) + } + FunctionOutcome::Empty => Err(eyre!( + "Call {service_id}.{function_name} didn't return any result" + )), + FunctionOutcome::Err(err) => Err(eyre!(err)), } - FunctionOutcome::Empty => Err(eyre!( - "Call {service_id}.{function_name} didn't return any result" - )), - FunctionOutcome::Err(err) => Err(eyre!(err)), } } diff --git a/crates/system-services/src/distro.rs b/crates/system-services/src/distro.rs index 8f545b3bdf..712763423b 100644 --- a/crates/system-services/src/distro.rs +++ b/crates/system-services/src/distro.rs @@ -1,3 +1,4 @@ +use async_trait::async_trait; use fluence_app_service::TomlMarineConfig; use fluence_spell_dtos::trigger_config::TriggerConfig; use serde_json::json; @@ -7,10 +8,11 @@ use server_config::system_services_config::{ }; use std::collections::HashMap; use std::sync::Arc; +use trust_graph_distro::Certs; use crate::{ - apply_binary_path_override, CallService, DeploymentStatus, InitService, PackageDistro, - ServiceDistro, ServiceStatus, SpellDistro, + apply_binary_path_override, CallService, Deployment, InitService, PackageDistro, ServiceDistro, + ServiceStatus, SpellDistro, }; #[derive(Debug, Clone)] @@ -41,14 +43,14 @@ impl SystemServiceDistros { let distros: HashMap = config .enable .iter() - .map(|key| { + .map(move |key| { let distro = match key { AquaIpfs => default_aqua_ipfs_distro(&config.aqua_ipfs), TrustGraph => default_trust_graph_distro(), Registry => default_registry_distro(&config.registry), Decider => default_decider_distro(&config.decider, &config.connector), }; - distro.map(|d| (d.name.clone(), d)) + distro.map(move |d| (d.name.clone(), d)) }) .collect::>()?; @@ -90,32 +92,52 @@ impl SystemServiceDistros { } } -pub fn default_trust_graph_distro() -> eyre::Result { - use trust_graph_distro::*; +struct TrustGraphInit<'a> { + name: String, + certs: &'a Certs, +} - fn mk_init(name: String, certs: &'static trust_graph_distro::Certs) -> InitService { - let init = move |call: &CallService, deployment: DeploymentStatus| { - if let Some(ServiceStatus::Created(id)) = deployment.services.get(&name) { - call( - name.clone(), +#[async_trait] +impl<'a> InitService for TrustGraphInit<'a> { + async fn init( + &self, + call_service: &dyn CallService, + deployment: Deployment, + ) -> eyre::Result<()> { + if let Some(ServiceStatus::Created(id)) = deployment.services.get(&self.name) { + call_service + .call( + self.name.clone(), "set_root".to_string(), - vec![json!(certs.root_node), json!(certs.max_chain_length)], - )?; + vec![ + json!(self.certs.root_node), + json!(self.certs.max_chain_length), + ], + ) + .await?; - let timestamp = now_millis::now_sec(); - for cert_chain in &certs.certs { - call( - name.clone(), + let timestamp = now_millis::now_sec(); + for cert_chain in &self.certs.certs { + call_service + .call( + self.name.clone(), "insert_cert".to_string(), vec![json!(cert_chain), json!(timestamp)], - )?; - } - tracing::info!(service_id = id, service_alias = name, "initialized service"); + ) + .await?; } - Ok(()) as eyre::Result<()> - }; - Box::new(init) + tracing::info!( + service_id = id, + service_alias = self.name, + "initialized service" + ); + } + Ok(()) as eyre::Result<()> } +} + +pub fn default_trust_graph_distro<'a>() -> eyre::Result { + use trust_graph_distro::*; let config: TomlMarineConfig = toml::from_slice(CONFIG)?; let service_distro = ServiceDistro { @@ -123,50 +145,69 @@ pub fn default_trust_graph_distro() -> eyre::Result { config, name: TrustGraph.to_string(), }; - let certs: &'static trust_graph_distro::Certs = &trust_graph_distro::KRAS_CERTS; - let init = mk_init(TrustGraph.to_string(), certs); + let certs: &'static Certs = &trust_graph_distro::KRAS_CERTS; + let init = TrustGraphInit { + name: TrustGraph.to_string(), + certs, + }; let package = PackageDistro { name: TrustGraph.to_string(), version: VERSION, services: vec![service_distro], spells: vec![], - init: Some(Arc::new(init)), + init: Some(Arc::new(Box::new(init))), }; Ok(package) } -pub fn default_aqua_ipfs_distro(config: &AquaIpfsConfig) -> eyre::Result { - use aqua_ipfs_distro::*; +struct AquaIpfsConfigInit { + local_api_multiaddr: String, + external_api_multiaddr: String, + name: String, +} - fn mk_init(name: String, config: &AquaIpfsConfig) -> InitService { - let local_api_multiaddr = config.local_api_multiaddr.clone(); - let external_api_multiaddr = config.external_api_multiaddr.clone(); - let init = move |call: &CallService, deployment: DeploymentStatus| { - if let Some(ServiceStatus::Created(id) | ServiceStatus::Existing(id)) = - deployment.services.get(&name) - { - let set_local_result = call( - name.clone(), +#[async_trait] +impl InitService for AquaIpfsConfigInit { + async fn init( + &self, + call_service: &dyn CallService, + deployment: Deployment, + ) -> eyre::Result<()> { + if let Some(ServiceStatus::Created(id) | ServiceStatus::Existing(id)) = + deployment.services.get(&self.name) + { + let set_local_result = call_service + .call( + self.name.clone(), "set_local_api_multiaddr".to_string(), - vec![json!(local_api_multiaddr)], - ); + vec![json!(self.local_api_multiaddr)], + ) + .await; - let set_external_result = call( - name.clone(), + let set_external_result = call_service + .call( + self.name.clone(), "set_external_api_multiaddr".to_string(), - vec![json!(external_api_multiaddr)], - ); + vec![json!(self.external_api_multiaddr)], + ) + .await; - // try to set local and external api multiaddrs, and only then produce an error - set_local_result?; - set_external_result?; + // try to set local and external api multiaddrs, and only then produce an error + set_local_result?; + set_external_result?; - tracing::info!(service_id = id, service_alias = name, "initialized service"); - } - Ok(()) - }; - Box::new(init) + tracing::info!( + service_id = id, + service_alias = self.name, + "initialized service" + ); + } + Ok(()) } +} + +pub fn default_aqua_ipfs_distro(config: &AquaIpfsConfig) -> eyre::Result { + use aqua_ipfs_distro::*; let mut marine_config: TomlMarineConfig = toml::from_slice(CONFIG)?; apply_binary_path_override( @@ -182,13 +223,21 @@ pub fn default_aqua_ipfs_distro(config: &AquaIpfsConfig) -> eyre::Result eyre::Result( decider_config: &DeciderConfig, connector_config: &ConnectorConfig, ) -> eyre::Result { diff --git a/crates/system-services/src/lib.rs b/crates/system-services/src/lib.rs index d5b545131b..b23a20c01d 100644 --- a/crates/system-services/src/lib.rs +++ b/crates/system-services/src/lib.rs @@ -4,6 +4,11 @@ mod deployer; mod distro; +use async_trait::async_trait; +use std::collections::HashMap; +use std::fmt; +use std::sync::Arc; + pub use deployer::Deployer; pub use distro::SystemServiceDistros; pub use distro::Versions; @@ -11,13 +16,19 @@ pub use distro::Versions; use fluence_app_service::TomlMarineConfig; use fluence_spell_dtos::trigger_config::TriggerConfig; use serde_json::Value; -use std::collections::HashMap; -use std::fmt; -use std::sync::Arc; type ServiceName = String; type FunctionName = String; +/// Status of package deployment for each services and spells of the package +#[derive(Clone, Debug)] +pub struct Deployment { + /// Statuses of spells deployment + pub spells: HashMap, + /// Statuses of services deployment + pub services: HashMap, +} + /// Call service functions. Accepts /// - service name /// - function name @@ -27,14 +38,27 @@ type FunctionName = String; /// The functions called via this callback must return a result with execution status in field `status: bool` /// and error message in the field `error: string`. /// Otherwise, the output will be consider invalid. -pub type CallService = - Box) -> eyre::Result<()> + Send + Sync>; +#[async_trait] +pub trait CallService: Send + Sync { + async fn call( + &self, + service_name: ServiceName, + function_name: FunctionName, + args: Vec, + ) -> eyre::Result<()>; +} /// Initialization function to initialize services /// - accepts `DeploymentStatus` of services and spells to be able to update or initialize the services /// - accepts `CallService` to be able to call installed services for initialization. -pub type InitService = - Box eyre::Result<()> + Send + Sync>; +#[async_trait] +pub trait InitService: Send + Sync { + async fn init( + &self, + call_service: &dyn CallService, + deployment: Deployment, + ) -> eyre::Result<()>; +} /// Package distribution description /// Contains enough information about all services and spells used by the package for installation @@ -52,7 +76,7 @@ pub struct PackageDistro { /// List of spells needed by the package pub spells: Vec, /// Optionally, initialization function for the services. - pub init: Option>, + pub init: Option>>, } impl fmt::Debug for PackageDistro { @@ -125,15 +149,6 @@ pub enum ServiceStatus { Existing(String), } -/// Status of package deployment for each services and spells of the package -#[derive(Clone, Debug)] -pub struct DeploymentStatus { - /// Statuses of spells deployment - pub spells: HashMap, - /// Statuses of services deployment - pub services: HashMap, -} - /// Override a binary path to a binary for a module in the service configuration fn apply_binary_path_override( config: &mut TomlMarineConfig, diff --git a/nox/src/main.rs b/nox/src/main.rs index a581190cbb..3d7a67499b 100644 --- a/nox/src/main.rs +++ b/nox/src/main.rs @@ -36,7 +36,7 @@ use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use air_interpreter_fs::write_default_air_interpreter; -use aquamarine::{DataStoreConfig, VmConfig, AVMRunner}; +use aquamarine::{AVMRunner, DataStoreConfig, VmConfig}; use config_utils::to_peer_id; use core_manager::{CoreManager, CoreManagerFunctions, DevCoreManager, StrictCoreManager}; use fs_utils::to_abs_path; diff --git a/nox/src/node.rs b/nox/src/node.rs index 8afb4073bf..a8a09e558f 100644 --- a/nox/src/node.rs +++ b/nox/src/node.rs @@ -360,7 +360,8 @@ impl Node { scopes.clone(), spell_service_api.clone(), spell_metrics, - ); + ) + .await; let allowed_binaries = config .allowed_effectors diff --git a/particle-builtins/src/builtins.rs b/particle-builtins/src/builtins.rs index 51940fc40c..5226ee4d99 100644 --- a/particle-builtins/src/builtins.rs +++ b/particle-builtins/src/builtins.rs @@ -152,7 +152,7 @@ where let end = start.elapsed().as_secs(); match result { - FunctionOutcome::NotDefined { args, params } => self.call_service(args, params), + FunctionOutcome::NotDefined { args, params } => self.call_service(args, params).await, result => { if let Some(metrics) = self.services.metrics.as_ref() { metrics.observe_builtins(result.not_err(), end as f64); @@ -204,19 +204,19 @@ where ("kad", "neigh_with_addrs") => wrap(self.neighborhood_with_addresses(args).await), ("kad", "merge") => wrap(self.kad_merge(args.function_args)), - ("srv", "list") => ok(self.list_services(particle)), + ("srv", "list") => ok(self.list_services(particle).await), ("srv", "create") => wrap(self.create_service(args, particle).await), - ("srv", "get_interface") => wrap(self.get_interface(args, particle)), - ("srv", "resolve_alias") => wrap(self.resolve_alias(args, particle)), - ("srv", "resolve_alias_opt") => wrap(self.resolve_alias_opt(args, particle)), + ("srv", "get_interface") => wrap(self.get_interface(args, particle).await), + ("srv", "resolve_alias") => wrap(self.resolve_alias(args, particle).await), + ("srv", "resolve_alias_opt") => wrap(self.resolve_alias_opt(args, particle).await), ("srv", "add_alias") => wrap_unit(self.add_alias(args, particle).await), ("srv", "remove") => wrap_unit(self.remove_service(args, particle).await), - ("srv", "info") => wrap(self.get_service_info(args, particle)), + ("srv", "info") => wrap(self.get_service_info(args, particle).await), - ("dist", "add_module_from_vault") => wrap(self.add_module_from_vault(args, particle)), - ("dist", "add_module") => wrap(self.add_module(args, particle)), - ("dist", "add_module_bytes_from_vault") => wrap(self.add_module_bytes_from_vault(args, particle)), - ("dist", "add_blueprint") => wrap(self.add_blueprint(args, particle)), + ("dist", "add_module_from_vault") => wrap(self.add_module_from_vault(args, particle).await), + ("dist", "add_module") => wrap(self.add_module(args, particle).await), + ("dist", "add_module_bytes_from_vault") => wrap(self.add_module_bytes_from_vault(args, particle).await), + ("dist", "add_blueprint") => wrap(self.add_blueprint(args, particle).await), ("dist", "make_module_config") => wrap(make_module_config(args)), ("dist", "load_module_config") => wrap(self.load_module_config_from_vault(args, particle)), ("dist", "default_module_config") => wrap(self.default_module_config(args)), @@ -241,8 +241,8 @@ where ("debug", "stringify") => self.stringify(args.function_args), - ("stat", "service_memory") => wrap(self.service_mem_stats(args, particle)), - ("stat", "service_stat") => wrap(self.service_stat(args, particle)), + ("stat", "service_memory") => wrap(self.service_mem_stats(args, particle).await), + ("stat", "service_stat") => wrap(self.service_stat(args, particle).await), ("math", "add") => binary(args, |x: i64, y: i64| -> R { math::add(x, y) }), ("math", "sub") => binary(args, |x: i64, y: i64| -> R { math::sub(x, y) }), @@ -284,7 +284,7 @@ where ("subnet", "resolve") => wrap(self.subnet_resolve(args).await), ("run-console", "print") => { - self.guard_protected(&particle)?; + self.guard_protected(&particle).await?; let function_args = args.function_args.iter(); let decider = function_args.filter_map(JValue::as_str).any(|s| s.contains("decider")); @@ -304,7 +304,7 @@ where // a worker spell. Otherwise we allow the call to go and find an aqua-ipfs service // since it can be a user-defined service which isn't the same as system aqua-ipfs. if matches!(particle.peer_scope, PeerScope::Host) { - self.guard_protected(&particle)?; + self.guard_protected(&particle).await?; } FunctionOutcome::NotDefined { args, params: particle } } @@ -378,7 +378,7 @@ where let peer_id = PeerId::from_str(peer_id.as_str())?; let addrs: Vec = Args::next_opt("addresses", &mut args)?.unwrap_or_default(); - self.guard_protected(¶ms)?; + self.guard_protected(¶ms).await?; let contact = Contact::new(peer_id, addrs); @@ -629,23 +629,27 @@ where Ok(JValue::Array(slice)) } - fn add_module(&self, args: Args, params: ParticleParams) -> Result { + async fn add_module(&self, args: Args, params: ParticleParams) -> Result { let mut args = args.function_args.into_iter(); let module_bytes: String = Args::next("module_bytes", &mut args)?; let config = Args::next("config", &mut args)?; - self.guard_protected(¶ms)?; + self.guard_protected(¶ms).await?; let hash = self.modules.add_module_base64(module_bytes, config)?; Ok(json!(hash)) } - fn add_module_from_vault(&self, args: Args, params: ParticleParams) -> Result { + async fn add_module_from_vault( + &self, + args: Args, + params: ParticleParams, + ) -> Result { let mut args = args.function_args.into_iter(); let module_path: String = Args::next("module_path", &mut args)?; let config: TomlMarineNamedModuleConfig = Args::next("config", &mut args)?; - self.guard_protected(¶ms)?; + self.guard_protected(¶ms).await?; let module_hash = self.modules.add_module_from_vault( &self.services.vault, @@ -658,7 +662,7 @@ where Ok(json!(module_hash)) } - fn add_module_bytes_from_vault( + async fn add_module_bytes_from_vault( &self, args: Args, params: ParticleParams, @@ -667,7 +671,7 @@ where let module_name: String = Args::next("module_name", &mut args)?; let module_path: String = Args::next("module_path", &mut args)?; - self.guard_protected(¶ms)?; + self.guard_protected(¶ms).await?; let module_hash = self.modules.add_module_from_vault( &self.services.vault, @@ -680,11 +684,11 @@ where Ok(json!(module_hash)) } - fn add_blueprint(&self, args: Args, params: ParticleParams) -> Result { + async fn add_blueprint(&self, args: Args, params: ParticleParams) -> Result { let mut args = args.function_args.into_iter(); let blueprint: String = Args::next("blueprint", &mut args)?; - self.guard_protected(¶ms)?; + self.guard_protected(¶ms).await?; let blueprint = AddBlueprint::decode(blueprint.as_bytes()).map_err(|err| { JError::new(format!("Error deserializing blueprint from IPLD: {err}")) @@ -800,7 +804,7 @@ where let mut args = args.function_args.into_iter(); let blueprint_id: String = Args::next("blueprint_id", &mut args)?; - self.guard_protected(¶ms)?; + self.guard_protected(¶ms).await?; let service_id = self .services @@ -819,7 +823,7 @@ where let mut args = args.function_args.into_iter(); let service_id_or_alias: String = Args::next("service_id_or_alias", &mut args)?; - self.guard_protected(¶ms)?; + self.guard_protected(¶ms).await?; self.services .remove_service( @@ -834,26 +838,30 @@ where Ok(()) } - fn list_services(&self, params: ParticleParams) -> JValue { + async fn list_services(&self, params: ParticleParams) -> JValue { Array( self.services .list_services(params.peer_scope) + .await .iter() .map(|info| json!(Service::from(info, self.scopes.clone()))) .collect(), ) } - fn call_service(&self, function_args: Args, particle: ParticleParams) -> FunctionOutcome { - self.services.call_service(function_args, particle, true) + async fn call_service(&self, function_args: Args, particle: ParticleParams) -> FunctionOutcome { + self.services + .call_service(function_args, particle, true) + .await } - fn get_interface(&self, args: Args, params: ParticleParams) -> Result { + async fn get_interface(&self, args: Args, params: ParticleParams) -> Result { let mut args = args.function_args.into_iter(); let service_id: String = Args::next("service_id", &mut args)?; Ok(self .services - .get_interface(params.peer_scope, service_id, ¶ms.id)?) + .get_interface(params.peer_scope, service_id, ¶ms.id) + .await?) } async fn add_alias(&self, args: Args, params: ParticleParams) -> Result<(), JError> { @@ -862,7 +870,7 @@ where let alias: String = Args::next("alias", &mut args)?; let service_id: String = Args::next("service_id", &mut args)?; - self.guard_protected(¶ms)?; + self.guard_protected(¶ms).await?; self.services .add_alias( @@ -883,12 +891,13 @@ where Ok(()) } - fn resolve_alias(&self, args: Args, params: ParticleParams) -> Result { + async fn resolve_alias(&self, args: Args, params: ParticleParams) -> Result { let mut args = args.function_args.into_iter(); let alias: String = Args::next("alias", &mut args)?; - let service_id = - self.services - .resolve_alias(params.peer_scope, alias.clone(), ¶ms.id)?; + let service_id = self + .services + .resolve_alias(params.peer_scope, alias.clone(), ¶ms.id) + .await?; log::debug!( "Resolved alias {} to service {:?} {}", @@ -900,24 +909,30 @@ where Ok(JValue::String(service_id)) } - fn resolve_alias_opt(&self, args: Args, params: ParticleParams) -> Result { + async fn resolve_alias_opt( + &self, + args: Args, + params: ParticleParams, + ) -> Result { let mut args = args.function_args.into_iter(); let alias: String = Args::next("alias", &mut args)?; let service_id_opt = self .services .resolve_alias(params.peer_scope, alias, ¶ms.id) + .await .map(|id| vec![JValue::String(id)]) .unwrap_or_default(); Ok(Array(service_id_opt)) } - fn get_service_info(&self, args: Args, params: ParticleParams) -> Result { + async fn get_service_info(&self, args: Args, params: ParticleParams) -> Result { let mut args = args.function_args.into_iter(); let service_id_or_alias: String = Args::next("service_id_or_alias", &mut args)?; - let info = - self.services - .get_service_info(params.peer_scope, service_id_or_alias, ¶ms.id)?; + let info = self + .services + .get_service_info(params.peer_scope, service_id_or_alias, ¶ms.id) + .await?; Ok(json!(Service::from(&info, self.scopes.clone()))) } @@ -930,22 +945,28 @@ where self.connectivity.as_ref() } - fn service_mem_stats(&self, args: Args, params: ParticleParams) -> Result { + async fn service_mem_stats( + &self, + args: Args, + params: ParticleParams, + ) -> Result { let mut args = args.function_args.into_iter(); let service_id_or_alias: String = Args::next("service_id", &mut args)?; self.services .get_service_mem_stats(params.peer_scope, service_id_or_alias, ¶ms.id) + .await .map(Array) } - fn service_stat(&self, args: Args, params: ParticleParams) -> Result { + async fn service_stat(&self, args: Args, params: ParticleParams) -> Result { let mut args = args.function_args.into_iter(); let service_id_or_alias: String = Args::next("service_id", &mut args)?; // Resolve aliases; also checks that the requested service exists. - let service_id = - self.services - .to_service_id(params.peer_scope, service_id_or_alias, ¶ms.id)?; + let service_id = self + .services + .to_service_id(params.peer_scope, service_id_or_alias, ¶ms.id) + .await?; let metrics = self .services .metrics @@ -1090,8 +1111,8 @@ where Ok(json!(result)) } - fn guard_protected(&self, particle: &ParticleParams) -> Result<(), JError> { - if self.is_worker_spell(particle) + async fn guard_protected(&self, particle: &ParticleParams) -> Result<(), JError> { + if self.is_worker_spell(particle).await || self.scopes.is_host(particle.init_peer_id) || self.scopes.is_management(particle.init_peer_id) { @@ -1108,13 +1129,14 @@ where // 2. init_peer_id must be a local peer id for the host (either host id or a worker id) // 3. There must be a spell service with alias "worker-spell" on the init_peer_id // 4. The spell service must have the same spell_id as in the particle and be of type "spell" - fn is_worker_spell(&self, particle: &ParticleParams) -> bool { + async fn is_worker_spell(&self, particle: &ParticleParams) -> bool { let result: Option<_> = try { let local_scope = self.scopes.scope(particle.init_peer_id).ok()?; let spell_id = ParticleParams::get_spell_id(&particle.id)?; let (worker_service, _) = self .services .get_service(local_scope, "worker-spell".to_string(), &particle.id) + .await .ok()?; worker_service.service_type == ServiceType::Spell && worker_service.service_id == spell_id diff --git a/particle-services/Cargo.toml b/particle-services/Cargo.toml index c84aee7415..2c4153434b 100644 --- a/particle-services/Cargo.toml +++ b/particle-services/Cargo.toml @@ -20,6 +20,7 @@ peer-metrics = { workspace = true } uuid-utils = { workspace = true } now-millis = { workspace = true } workers = { workspace = true } +futures = { workspace = true } fluence-app-service = { workspace = true } diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index 9205ef7793..fd20fc4390 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -24,8 +24,8 @@ use fluence_app_service::{ MarineConfig, MarineError, MarineWASIConfig, ModuleDescriptor, SecurityTetraplet, ServiceInterface, WasmtimeConfig, }; +use futures::{stream, StreamExt}; use humantime_serde::re::humantime::format_duration as pretty; -use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value as JValue}; use tokio::runtime::Handle; @@ -85,18 +85,18 @@ pub struct ServiceInfo { #[derivative(Debug)] pub struct Service { #[derivative(Debug(format_with = "fmt_service"))] - pub service: Mutex, + pub service: tokio::sync::Mutex, pub service_id: String, pub blueprint_id: String, pub service_type: ServiceType, pub owner_id: PeerId, - pub aliases: RwLock>, + pub aliases: tokio::sync::RwLock>, pub peer_scope: PeerScope, } impl Service { pub fn new( - service: Mutex, + service: tokio::sync::Mutex, service_id: String, blueprint_id: String, service_type: ServiceType, @@ -110,36 +110,36 @@ impl Service { blueprint_id, service_type, owner_id, - aliases: RwLock::new(aliases), + aliases: tokio::sync::RwLock::new(aliases), peer_scope, } } - pub fn remove_alias(&self, alias: &str) { - let mut aliases = self.aliases.write(); + pub async fn remove_alias(&self, alias: &str) { + let mut aliases = self.aliases.write().await; if let Some(pos) = aliases.iter().position(|x| *x == alias) { aliases.remove(pos); } } - pub fn add_alias(&self, alias: String) { - self.aliases.write().push(alias); + pub async fn add_alias(&self, alias: String) { + self.aliases.write().await.push(alias); } - pub fn get_info(&self, id: &str) -> ServiceInfo { + pub async fn get_info(&self, id: &str) -> ServiceInfo { ServiceInfo { id: id.to_string(), blueprint_id: self.blueprint_id.clone(), service_type: self.service_type.clone(), owner_id: self.owner_id, - aliases: self.aliases.read().clone(), + aliases: self.aliases.read().await.clone(), peer_scope: self.peer_scope, } } } impl Deref for Service { - type Target = Mutex; + type Target = tokio::sync::Mutex; fn deref(&self) -> &Self::Target { &self.service @@ -147,7 +147,7 @@ impl Deref for Service { } fn fmt_service( - _: &Mutex, + _: &tokio::sync::Mutex, f: &mut std::fmt::Formatter<'_>, ) -> Result<(), std::fmt::Error> { f.debug_struct("Mutex").finish() @@ -164,8 +164,8 @@ pub struct VmDescriptor<'a> { #[derive(Derivative)] #[derivative(Debug, Clone, Default)] struct Services { - services: Arc>>>, - aliases: Arc>>, + services: Arc>>>, + aliases: Arc>>, } #[derive(Derivative)] @@ -177,7 +177,7 @@ pub struct ParticleAppServices { root_services: Services, #[derivative(Debug = "ignore")] root_runtime_handle: Handle, - worker_services: Arc>>, + worker_services: Arc>>, modules: ModuleRepository, #[derivative(Debug = "ignore")] workers: Arc, @@ -191,14 +191,18 @@ pub struct ParticleAppServices { app_service_epoch_ticker: EpochTicker, } -fn resolve_alias(services: &Services, alias: &String, particle_id: &str) -> Option { +async fn resolve_alias( + services: &Services, + alias: &String, + particle_id: &str, +) -> Option { if alias == "spell" || alias == "self" { if let Some(spell_id) = ParticleParams::get_spell_id(particle_id) { return Some(spell_id); } } - services.aliases.read().get(alias).cloned() + services.aliases.read().await.get(alias).cloned() } fn get_service( @@ -293,29 +297,30 @@ impl ParticleAppServices { Ok(service_id) } - pub fn service_exists(&self, peer_scope: &PeerScope, service_id: &str) -> bool { - let services = self.get_services(peer_scope); + pub async fn service_exists(&self, peer_scope: &PeerScope, service_id: &str) -> bool { + let services = self.get_services(peer_scope).await; match services { - Ok(services) => services.services.read().get(service_id).is_some(), + Ok(services) => services.services.read().await.get(service_id).is_some(), Err(_) => false, } } - pub fn get_service_info( + pub async fn get_service_info( &self, peer_scope: PeerScope, service_id_or_alias: String, particle_id: &str, ) -> Result { - let (service, service_id) = - self.get_service(peer_scope, service_id_or_alias, particle_id)?; + let (service, service_id) = self + .get_service(peer_scope, service_id_or_alias, particle_id) + .await?; - Ok(service.get_info(&service_id)) + Ok(service.get_info(&service_id).await) } pub async fn remove_services(&self, peer_scope: PeerScope) -> Result<(), ServiceError> { - let services = self.get_services(&peer_scope)?; - let service_ids: Vec = services.services.read().keys().cloned().collect(); + let services = self.get_services(&peer_scope).await?; + let service_ids: Vec = services.services.read().await.keys().cloned().collect(); for srv_id in service_ids { //TODO: can be parallelized @@ -329,10 +334,10 @@ impl ParticleAppServices { ) } } - let services = self.get_services(&peer_scope)?; + let services = self.get_services(&peer_scope).await?; - let mut aliases = services.aliases.write(); - let mut services = services.services.write(); + let mut aliases = services.aliases.write().await; + let mut services = services.services.write().await; aliases.clear(); services.clear(); @@ -350,8 +355,9 @@ impl ParticleAppServices { ) -> Result<(), ServiceError> { let removal_start_time = Instant::now(); let service_id = { - let (service, service_id) = - self.get_service(peer_scope, service_id_or_alias.to_string(), particle_id)?; + let (service, service_id) = self + .get_service(peer_scope, service_id_or_alias.to_string(), particle_id) + .await?; // tmp hack to forbid spell removal via srv.remove if service.service_type.is_spell() && !allow_remove_spell { @@ -399,15 +405,15 @@ impl ParticleAppServices { err ) } - let services = self.get_services(&peer_scope)?; - let mut aliases = services.aliases.write(); - let mut services = services.services.write(); + let services = self.get_services(&peer_scope).await?; + let mut aliases = services.aliases.write().await; + let mut services = services.services.write().await; let service = services.remove(service_id.as_str()).unwrap(); - let service_aliases = service.aliases.read(); + let service_aliases = service.aliases.read().await; for alias in service_aliases.iter() { aliases.remove(alias.as_str()); } - let service_type = self.get_service_type(&service, &service.peer_scope); + let service_type = self.get_service_type(&service, &service.peer_scope).await; let removal_end_time = removal_start_time.elapsed().as_secs(); if let Some(metrics) = self.metrics.as_ref() { @@ -417,7 +423,7 @@ impl ParticleAppServices { Ok(()) } - pub fn call_service( + pub async fn call_service( &self, function_args: Args, particle: ParticleParams, @@ -426,7 +432,9 @@ impl ParticleAppServices { let peer_scope = particle.peer_scope; let timestamp = particle.timestamp; - let service = self.get_service(peer_scope, function_args.service_id.clone(), &particle.id); + let service = self + .get_service(peer_scope, function_args.service_id.clone(), &particle.id) + .await; let (service, service_id) = match service { Ok(found) => found, @@ -449,7 +457,7 @@ impl ParticleAppServices { // )); // } // Metrics collection are enables for services with aliases which are installed on root worker or worker spells. - let service_type = self.get_service_type(service.as_ref(), &peer_scope); + let service_type = self.get_service_type(service.as_ref(), &peer_scope).await; // TODO: move particle vault creation to aquamarine::particle_functions if create_vault { @@ -486,36 +494,39 @@ impl ParticleAppServices { let function_name = function_args.function_name; let lock_acquire_start = Instant::now(); - let mut service = service.lock(); + let mut service = service.lock().await; let old_memory = service.module_memory_stats(); let old_mem_usage = ServicesMetricsBuiltin::get_used_memory(&old_memory); // TODO async-marine: set execution timeout https://github.com/fluencelabs/fluence/issues/1212 let call_time_start = Instant::now(); - let result = tokio::runtime::Handle::current() - .block_on(service.call_async( + + let result = service + .call_async( function_name.clone(), JValue::Array(function_args.function_args), params, - )) - .map_err(|e| { - if let Some(metrics) = self.metrics.as_ref() { - let stats = ServiceCallStats::Fail { timestamp }; - // If the called function is unknown we don't want to save info - // about it in a separate entry. - let function_name = if is_unknown_function(&e) { - None - } else { - Some(function_name.clone()) - }; - metrics.observe_service_state_failed( - service_id.clone(), - function_name, - service_type.clone(), - stats, - ); - } - ServiceError::Engine(e) - })?; + ) + .await; + + let result = result.map_err(|e| { + if let Some(metrics) = self.metrics.as_ref() { + let stats = ServiceCallStats::Fail { timestamp }; + // If the called function is unknown we don't want to save info + // about it in a separate entry. + let function_name = if is_unknown_function(&e) { + None + } else { + Some(function_name.clone()) + }; + metrics.observe_service_state_failed( + service_id.clone(), + function_name, + service_type.clone(), + stats, + ); + } + ServiceError::Engine(e) + })?; if let Some(metrics) = self.metrics.as_ref() { let call_time_sec = call_time_start.elapsed().as_secs_f64(); @@ -545,7 +556,7 @@ impl ParticleAppServices { // TODO: is it safe? #[allow(clippy::too_many_arguments)] - pub fn call_function( + pub async fn call_function( &self, peer_scope: PeerScope, service_id: &str, @@ -574,7 +585,7 @@ impl ParticleAppServices { token: "host_call".to_string(), }; - self.call_service(args, particle, false) + self.call_service(args, particle, false).await } async fn add_alias_inner( @@ -584,30 +595,30 @@ impl ParticleAppServices { service_id: ServiceId, ) -> Result<(), ServiceError> { let service = { - let services = self.get_or_create_services(peer_scope); - let mut aliases_service_id_mapping = services.aliases.write(); - let services_id_mapping = services.services.write(); + let services = self.get_or_create_services(peer_scope).await; + let mut aliases_service_id_mapping = services.aliases.write().await; + let services_id_mapping = services.services.write().await; let service = get_service(&services_id_mapping, peer_scope, service_id.clone())?; - service.add_alias(alias.clone()); + service.add_alias(alias.clone()).await; aliases_service_id_mapping.insert(alias, service_id); - PersistedService::from_service(service.as_ref()) + PersistedService::from_service(service.as_ref()).await }; service.persist(&self.config.services_dir).await } - fn get_or_create_services(&self, peer_scope: PeerScope) -> Services { + async fn get_or_create_services(&self, peer_scope: PeerScope) -> Services { match peer_scope { - PeerScope::WorkerId(worker_id) => self.get_or_create_worker_services(worker_id), + PeerScope::WorkerId(worker_id) => self.get_or_create_worker_services(worker_id).await, PeerScope::Host => self.root_services.clone(), } } - fn get_services(&self, peer_scope: &PeerScope) -> Result { + async fn get_services(&self, peer_scope: &PeerScope) -> Result { match peer_scope { PeerScope::WorkerId(worker_id) => { - let worker_services = self.worker_services.read(); + let worker_services = self.worker_services.read().await; let services = worker_services .get(worker_id) @@ -620,14 +631,14 @@ impl ParticleAppServices { } } - pub fn get_service( + pub async fn get_service( &self, peer_scope: PeerScope, id_or_alias: String, particle_id: &str, ) -> Result<(Arc, String), ServiceError> { - let services = self.get_services(&peer_scope)?; - let services_id_mapping = services.services.read(); + let services = self.get_services(&peer_scope).await?; + let services_id_mapping = services.services.read().await; // retrieve service by service id let service = get_service(&services_id_mapping, peer_scope, id_or_alias.clone()).ok(); @@ -638,6 +649,7 @@ impl ParticleAppServices { // retrieve service by alias let resolved_id = resolve_alias(&services, &id_or_alias, particle_id) + .await .ok_or(NoSuchService(id_or_alias.clone(), peer_scope))?; let service = get_service(&services_id_mapping, peer_scope, resolved_id.clone())?; @@ -645,10 +657,10 @@ impl ParticleAppServices { Ok((service, resolved_id)) } - fn get_service_id(&self, peer_scope: PeerScope, alias: &str) -> Option { - let services = self.get_services(&peer_scope); + async fn get_service_id(&self, peer_scope: PeerScope, alias: &str) -> Option { + let services = self.get_services(&peer_scope).await; match services { - Ok(services) => services.aliases.read().get(alias).cloned(), + Ok(services) => services.aliases.read().await.get(alias).cloned(), Err(_) => None, } } @@ -660,11 +672,11 @@ impl ParticleAppServices { service_id: &str, ) -> Result<(), ServiceError> { let service = { - let services = self.get_or_create_services(peer_scope); - let services_id_mapping = services.services.write(); + let services = self.get_or_create_services(peer_scope).await; + let services_id_mapping = services.services.write().await; let service = get_service(&services_id_mapping, peer_scope, service_id.to_string())?; - service.remove_alias(&alias); - PersistedService::from_service(service.as_ref()) + service.remove_alias(&alias).await; + PersistedService::from_service(service.as_ref()).await }; service.persist(&self.config.services_dir).await @@ -700,7 +712,7 @@ impl ParticleAppServices { } // alias can't be equal to any existent service id - if self.service_exists(&peer_scope, &alias) { + if self.service_exists(&peer_scope, &alias).await { return Err(AliasAsServiceId(alias)); } @@ -713,11 +725,11 @@ impl ParticleAppServices { return Err(ForbiddenAlias(alias)); } - if !self.service_exists(&peer_scope, &service_id) { + if !self.service_exists(&peer_scope, &service_id).await { return Err(NoSuchService(service_id, peer_scope)); } - let prev_srv_id = self.get_service_id(peer_scope, &alias); + let prev_srv_id = self.get_service_id(peer_scope, &alias).await; if let Some(srv_id) = prev_srv_id { self.remove_alias(alias.clone(), peer_scope, &srv_id) .await?; @@ -729,44 +741,52 @@ impl ParticleAppServices { Ok(()) } - pub fn resolve_alias( + pub async fn resolve_alias( &self, peer_scope: PeerScope, alias: String, particle_id: &str, ) -> Result { - let services = self.get_or_create_services(peer_scope); - resolve_alias(&services, &alias, particle_id).ok_or_else(|| NoSuchAlias(alias, peer_scope)) + let services = self.get_or_create_services(peer_scope).await; + resolve_alias(&services, &alias, particle_id) + .await + .ok_or_else(|| NoSuchAlias(alias, peer_scope)) } - pub fn to_service_id( + pub async fn to_service_id( &self, peer_scope: PeerScope, service_id_or_alias: String, particle_id: &str, ) -> Result { - let (_, service_id) = self.get_service(peer_scope, service_id_or_alias, particle_id)?; + let (_, service_id) = self + .get_service(peer_scope, service_id_or_alias, particle_id) + .await?; Ok(service_id) } - pub fn get_service_owner( + pub async fn get_service_owner( &self, peer_scope: PeerScope, id_or_alias: String, particle_id: &str, ) -> Result { - let (service, _) = self.get_service(peer_scope, id_or_alias, particle_id)?; + let (service, _) = self + .get_service(peer_scope, id_or_alias, particle_id) + .await?; Ok(service.owner_id) } - pub fn check_service_worker_id( + pub async fn check_service_worker_id( &self, peer_scope: PeerScope, id_or_alias: String, particle_id: &str, ) -> Result<(), ServiceError> { - let (service, _) = self.get_service(peer_scope, id_or_alias.clone(), particle_id)?; + let (service, _) = self + .get_service(peer_scope, id_or_alias.clone(), particle_id) + .await?; if service.peer_scope != peer_scope { Err(ServiceError::CallServiceFailedWrongWorker { @@ -778,66 +798,86 @@ impl ParticleAppServices { } } - pub fn get_interface( + pub async fn get_interface( &self, peer_scope: PeerScope, service_id: String, particle_id: &str, ) -> Result { - let (service, _) = self.get_service(peer_scope, service_id, particle_id)?; + let (service, _) = self + .get_service(peer_scope, service_id, particle_id) + .await?; Ok(self.modules.get_facade_interface(&service.blueprint_id)?) } - pub fn list_services_all(&self) -> Vec { - let root_info: Vec = self - .root_services - .services - .read() - .iter() - .map(|(id, service)| service.get_info(id)) - .collect(); + pub async fn list_services_all(&self) -> Vec { + let root_services = self.root_services.services.read().await; + + let root_info: Vec = stream::iter(root_services.iter()) + .then(|(id, service)| async { service.get_info(id).await }) + .collect() + .await; + + drop(root_services); + + let worker_services = self.worker_services.read().await; + + let mut result: Vec = futures::stream::iter(worker_services.iter()) + .then(|(_, services)| async { + let services = services.services.read().await; + let services: Vec = futures::stream::iter(services.iter()) + .then(|(id, service)| { + let id = id.clone(); + let service = service.clone(); + async move { service.get_info(id.as_str()).await } + }) + .collect() + .await; - let mut result: Vec = self - .worker_services - .read() - .values() - .flat_map(|services| { - let services = services.services.read(); services - .iter() - .map(|(id, service)| service.get_info(id)) - .collect::>() }) - .collect(); + .fold(Vec::new(), |mut acc, item| async { + acc.extend(item); + acc + }) + .await; result.extend(root_info); result } - pub fn list_services(&self, peer_scope: PeerScope) -> Vec { - let services = self.get_services(&peer_scope); + pub async fn list_services(&self, peer_scope: PeerScope) -> Vec { + let services = self.get_services(&peer_scope).await; match services { - Ok(services) => services - .services - .read() - .iter() - .map(|(id, srv)| srv.get_info(id)) - .collect(), + Ok(services) => { + let services = services.services.read().await; + + futures::stream::iter(services.iter()) + .then(|(id, srv)| { + let srv = srv.clone(); + let id = id.clone(); + async move { srv.get_info(&id).await } + }) + .collect() + .await + } Err(_) => { vec![] } } } - pub fn get_service_mem_stats( + pub async fn get_service_mem_stats( &self, peer_scope: PeerScope, service_id: String, particle_id: &str, ) -> Result, JError> { - let (service, _) = self.get_service(peer_scope, service_id, particle_id)?; + let (service, _) = self + .get_service(peer_scope, service_id, particle_id) + .await?; - let lock = service.service.lock(); + let lock = service.service.lock().await; let stats = lock.module_memory_stats(); let stats = stats .modules @@ -903,8 +943,8 @@ impl ParticleAppServices { match service.peer_scope { PeerScope::WorkerId(worker_id) => { - let services = self.get_or_create_worker_services(worker_id); - let mut aliases = services.aliases.write(); + let services = self.get_or_create_worker_services(worker_id).await; + let mut aliases = services.aliases.write().await; for alias in service.aliases.iter() { let old = aliases.insert(alias.clone(), service.service_id.clone()); if let Some(old) = old { @@ -918,7 +958,7 @@ impl ParticleAppServices { } } PeerScope::Host => { - let mut aliases = self.root_services.aliases.write(); + let mut aliases = self.root_services.aliases.write().await; for alias in service.aliases.iter() { let old = aliases.insert(alias.clone(), service.service_id.clone()); if let Some(old) = old { @@ -979,7 +1019,7 @@ impl ParticleAppServices { let stats = ServiceMemoryStat::new(&stats); let service = Service::new( - Mutex::new(service), + tokio::sync::Mutex::new(service), service_id.clone(), blueprint_id, service_type, @@ -989,13 +1029,14 @@ impl ParticleAppServices { ); let service = Arc::new(service); // Save created service to disk, so it is recreated on restart - let persisted_service = PersistedService::from_service(&service); + let persisted_service = PersistedService::from_service(&service).await; persisted_service.persist(&self.config.services_dir).await?; - let service_type = self.get_service_type(&service, &peer_scope); - let services = self.get_or_create_services(peer_scope); + let service_type = self.get_service_type(&service, &peer_scope).await; + let services = self.get_or_create_services(peer_scope).await; let replaced = services .services .write() + .await .insert(service_id.clone(), service); if let Some(m) = self.metrics.as_ref() { @@ -1006,12 +1047,12 @@ impl ParticleAppServices { Ok(replaced) } - fn get_or_create_worker_services(&self, worker_id: WorkerId) -> Services { - let workers_services = self.worker_services.upgradable_read(); + async fn get_or_create_worker_services(&self, worker_id: WorkerId) -> Services { + let workers_services = self.worker_services.read().await; let worker_services = workers_services.get(&worker_id); match worker_services { None => { - let mut workers_services = RwLockUpgradableReadGuard::upgrade(workers_services); + let mut workers_services = self.worker_services.write().await; //we double check it, because it can be created in another thread let services = workers_services.get(&worker_id); match services { @@ -1143,13 +1184,18 @@ impl ParticleAppServices { .map_err(ServiceError::Engine) } - fn get_service_type(&self, service: &Service, peer_scope: &PeerScope) -> MetricServiceType { + async fn get_service_type( + &self, + service: &Service, + peer_scope: &PeerScope, + ) -> MetricServiceType { let allowed_alias = match peer_scope { - PeerScope::Host => service.aliases.read().first().cloned(), + PeerScope::Host => service.aliases.read().await.first().cloned(), _ => { if service .aliases .read() + .await .first() .map(|alias| alias == "worker-spell") .unwrap_or(false) diff --git a/particle-services/src/persistence.rs b/particle-services/src/persistence.rs index 69af5f90f2..9195982643 100644 --- a/particle-services/src/persistence.rs +++ b/particle-services/src/persistence.rs @@ -46,12 +46,12 @@ pub struct PersistedService { } impl PersistedService { - pub fn from_service(service: &Service) -> Self { + pub async fn from_service(service: &Service) -> Self { PersistedService { service_id: service.service_id.clone(), service_type: Some(service.service_type.clone()), blueprint_id: service.blueprint_id.clone(), - aliases: service.aliases.read().clone(), + aliases: service.aliases.read().await.clone(), owner_id: service.owner_id, peer_scope: service.peer_scope, } diff --git a/sorcerer/src/script_executor.rs b/sorcerer/src/script_executor.rs index c3b61bbdd7..148cebbbb6 100644 --- a/sorcerer/src/script_executor.rs +++ b/sorcerer/src/script_executor.rs @@ -27,7 +27,11 @@ use spell_event_bus::api::{TriggerEvent, TriggerInfoAqua}; use spell_service_api::CallParams; impl Sorcerer { - fn get_spell_counter(&self, peer_scope: PeerScope, spell_id: String) -> Result { + async fn get_spell_counter( + &self, + peer_scope: PeerScope, + spell_id: String, + ) -> Result { let init_peer_id = self.scopes.to_peer_id(peer_scope); let params = CallParams::local( peer_scope, @@ -35,13 +39,13 @@ impl Sorcerer { init_peer_id, self.spell_script_particle_ttl, ); - let counter = self.spell_service_api.get_counter(params)?; + let counter = self.spell_service_api.get_counter(params).await?; // If the counter does not exist, consider it to be 0. // It will be incremented afterwards to 1 anyway. Ok(counter.unwrap_or(0u32)) } - fn set_spell_next_counter( + async fn set_spell_next_counter( &self, peer_scope: PeerScope, spell_id: String, @@ -56,10 +60,15 @@ impl Sorcerer { ); self.spell_service_api .set_counter(params, next_counter) + .await .map_err(|e| JError::new(e.to_string())) } - fn get_spell_script(&self, peer_scope: PeerScope, spell_id: String) -> Result { + async fn get_spell_script( + &self, + peer_scope: PeerScope, + spell_id: String, + ) -> Result { let init_peer_id = self.scopes.to_peer_id(peer_scope); let params = CallParams::local( peer_scope, @@ -69,11 +78,12 @@ impl Sorcerer { ); self.spell_service_api .get_script(params) + .await .map_err(|e| JError::new(e.to_string())) } #[instrument(level = tracing::Level::INFO, skip_all)] - pub(crate) fn make_spell_particle( + pub(crate) async fn make_spell_particle( &self, peer_scope: PeerScope, spell_id: String, @@ -86,9 +96,10 @@ impl Sorcerer { peer_scope, })?; - let spell_counter = self.get_spell_counter(peer_scope, spell_id.clone())?; - self.set_spell_next_counter(peer_scope, spell_id.clone(), spell_counter + 1)?; - let spell_script = self.get_spell_script(peer_scope, spell_id.clone())?; + let spell_counter = self.get_spell_counter(peer_scope, spell_id.clone()).await?; + self.set_spell_next_counter(peer_scope, spell_id.clone(), spell_counter + 1) + .await?; + let spell_script = self.get_spell_script(peer_scope, spell_id.clone()).await?; let init_peer_id: PeerId = match peer_scope { PeerScope::WorkerId(worker_id) => worker_id.into(), PeerScope::Host => self.scopes.get_host_peer_id(), @@ -110,7 +121,7 @@ impl Sorcerer { Ok(particle) } - pub(crate) fn store_trigger( + pub(crate) async fn store_trigger( &self, event: TriggerEvent, peer_scope: PeerScope, @@ -125,6 +136,7 @@ impl Sorcerer { ); self.spell_service_api .set_trigger_event(params, serialized_event) + .await .map_err(|e| JError::new(e.to_string())) } @@ -136,9 +148,11 @@ impl Sorcerer { .get_scope(event.spell_id.clone()) .expect("Scope not found"); - let particle = self.make_spell_particle(peer_scope, event.spell_id.clone())?; + let particle = self + .make_spell_particle(peer_scope, event.spell_id.clone()) + .await?; - self.store_trigger(event.clone(), peer_scope)?; + self.store_trigger(event.clone(), peer_scope).await?; if let Some(m) = &self.spell_metrics { m.observe_spell_cast(); } diff --git a/sorcerer/src/sorcerer.rs b/sorcerer/src/sorcerer.rs index f746d8920d..1562bb0e70 100644 --- a/sorcerer/src/sorcerer.rs +++ b/sorcerer/src/sorcerer.rs @@ -63,7 +63,7 @@ pub struct Sorcerer { impl Sorcerer { #[allow(clippy::too_many_arguments)] - pub fn new( + pub async fn new( services: ParticleAppServices, modules: ModuleRepository, aquamarine: AquamarineApi, @@ -77,6 +77,7 @@ impl Sorcerer { ) -> (Self, HashMap, String) { let (spell_storage, spell_version) = SpellStorage::create(&config.dir_config.spell_base_dir, &services, &modules) + .await .expect("Spell storage creation"); let sorcerer = Self { @@ -104,16 +105,17 @@ impl Sorcerer { for spell_id in spells { log::info!("Rescheduling spell {} on {:?} peer", spell_id, peer_scope); let result: Result<(), JError> = try { - let spell_owner = - self.services - .get_service_owner(peer_scope, spell_id.clone(), "")?; + let spell_owner = self + .services + .get_service_owner(peer_scope, spell_id.clone(), "") + .await?; let params = CallParams::local( peer_scope, spell_id.clone(), spell_owner, self.spell_script_particle_ttl, ); - let config = self.spell_service_api.get_trigger_config(params)?; + let config = self.spell_service_api.get_trigger_config(params).await?; let period = config.clock.period_sec; let config = from_user_config(&config)?; if let Some(config) = config.and_then(|c| c.into_rescheduled()) { @@ -346,7 +348,7 @@ impl Sorcerer { let spell_service_api = self.spell_service_api.clone(); ServiceFunction::Immut(Box::new(move |args, params| { let spell_service_api = spell_service_api.clone(); - async move { wrap(get_spell_arg(args, params, spell_service_api)) }.boxed() + async move { wrap(get_spell_arg(args, params, spell_service_api).await) }.boxed() })) } @@ -354,7 +356,7 @@ impl Sorcerer { let spell_service_api = self.spell_service_api.clone(); ServiceFunction::Immut(Box::new(move |args, params| { let spell_service_api = spell_service_api.clone(); - async move { wrap_unit(store_error(args, params, spell_service_api)) }.boxed() + async move { wrap_unit(store_error(args, params, spell_service_api).await) }.boxed() })) } @@ -362,7 +364,7 @@ impl Sorcerer { let spell_service_api = self.spell_service_api.clone(); ServiceFunction::Immut(Box::new(move |args, params| { let spell_service_api = spell_service_api.clone(); - async move { wrap_unit(store_response(args, params, spell_service_api)) }.boxed() + async move { wrap_unit(store_response(args, params, spell_service_api).await) }.boxed() })) } diff --git a/sorcerer/src/spell_builtins.rs b/sorcerer/src/spell_builtins.rs index 6a5d91cfc8..b0fa6718c3 100644 --- a/sorcerer/src/spell_builtins.rs +++ b/sorcerer/src/spell_builtins.rs @@ -82,7 +82,7 @@ pub async fn install_spell( let params = CallParams::local(peer_scope, spell_id.clone(), owner_id, ttl); // Save the script to the spell - spell_service_api.set_script(params.clone(), script)?; + spell_service_api.set_script(params.clone(), script).await?; // Save init_data to the spell's KV let self_particle_id = format!("spell_{spell_id}_0"); let self_params = CallParams::new( @@ -92,9 +92,13 @@ pub async fn install_spell( Some(self_particle_id), ttl, ); - spell_service_api.update_kv(self_params.clone(), init_data)?; + spell_service_api + .update_kv(self_params.clone(), init_data) + .await?; // Save trigger config - spell_service_api.set_trigger_config(params, user_config)?; + spell_service_api + .set_trigger_config(params, user_config) + .await?; if let Some(config) = config { // Scheduling the spell @@ -130,7 +134,7 @@ pub struct SpellInfo { pub trigger_config: TriggerConfig, } -pub fn get_spell_info( +pub async fn get_spell_info( spell_service_api: &SpellServiceApi, peer_scope: PeerScope, ttl: Duration, @@ -140,10 +144,12 @@ pub fn get_spell_info( let params = CallParams::local(peer_scope, spell_id.clone(), init_peer_id, ttl); let trigger_config = spell_service_api .get_trigger_config(params.clone()) + .await .map_err(|e| JError::new(f!("Failed to get trigger_config for spell {spell_id}: {e}")))?; let script = spell_service_api .get_script(params) + .await .map_err(|e| JError::new(f!("Failed to get trigger_config for spell {spell_id}: {e}")))?; Ok(SpellInfo { script, @@ -290,7 +296,9 @@ pub(crate) async fn spell_remove( } }; - let spell_id = services.to_service_id(params.peer_scope, spell_id, ¶ms.id)?; + let spell_id = services + .to_service_id(params.peer_scope, spell_id, ¶ms.id) + .await?; remove_spell( ¶ms.id, @@ -343,7 +351,9 @@ pub(crate) async fn spell_update_config( } } - let spell_id = services.to_service_id(peer_scope, spell_id_or_alias.clone(), ¶ms.id)?; + let spell_id = services + .to_service_id(peer_scope, spell_id_or_alias.clone(), ¶ms.id) + .await?; let user_config: TriggerConfig = Args::next("config", &mut args)?; let config = api::from_user_config(&user_config)?; @@ -354,7 +364,9 @@ pub(crate) async fn spell_update_config( init_peer_id, Duration::from_millis(params.ttl as u64), ); - spell_service_api.set_trigger_config(params, user_config)?; + spell_service_api + .set_trigger_config(params, user_config) + .await?; let result: Result<(), EventBusError> = try { // we unsubscribe the spell from the current config anyway @@ -383,7 +395,7 @@ pub(crate) fn get_spell_id(params: ParticleParams) -> Result { Ok(json!(parse_spell_id_from(¶ms)?)) } -pub(crate) fn get_spell_arg( +pub(crate) async fn get_spell_arg( args: Args, params: ParticleParams, spell_service_api: SpellServiceApi, @@ -394,6 +406,7 @@ pub(crate) fn get_spell_arg( let str_value = spell_service_api .get_string(call_params, key.clone()) + .await .map_err(|e| JError::new(f!("Failed to get argument {key} for spell {spell_id}: {e}"))) .and_then(|value| value.ok_or_else(|| JError::new("value not found")))?; @@ -404,7 +417,7 @@ pub(crate) fn get_spell_arg( }) } -pub(crate) fn store_error( +pub(crate) async fn store_error( mut args: Args, params: ParticleParams, spell_service_api: SpellServiceApi, @@ -415,6 +428,7 @@ pub(crate) fn store_error( let call_params = CallParams::from(spell_id.clone(), params); spell_service_api .store_error(call_params, args.function_args.clone()) + .await .map_err(|e| { JError::new(format!( "Failed to store error {:?} for spell {}: {}", @@ -423,7 +437,7 @@ pub(crate) fn store_error( }) } -pub(crate) fn store_response( +pub(crate) async fn store_response( args: Args, params: ParticleParams, spell_service_api: SpellServiceApi, @@ -435,6 +449,7 @@ pub(crate) fn store_response( let call_params = CallParams::from(spell_id.clone(), params); spell_service_api .update_kv(call_params, response.clone()) + .await .map_err(|err| { JError::new(format!( "Failed to store response {response} for spell {spell_id}: {err}" diff --git a/sorcerer/src/worker_builins.rs b/sorcerer/src/worker_builins.rs index 5aa7f70566..f22f8099d3 100644 --- a/sorcerer/src/worker_builins.rs +++ b/sorcerer/src/worker_builins.rs @@ -179,6 +179,7 @@ pub(crate) async fn deactivate_deal( ), TriggerConfig::default(), ) + .await .map_err(|e| { JError::new(format!( "Deal deactivation failed due to failure to stop spell {spell_id} : {e}" @@ -216,26 +217,30 @@ pub(crate) async fn activate_deal( return Err(JError::new("Deal has already been activated")); } - let installation_spell_id = services.resolve_alias( - PeerScope::WorkerId(worker_id), - "worker-spell".to_string(), - ¶ms.id, - )?; + let installation_spell_id = services + .resolve_alias( + PeerScope::WorkerId(worker_id), + "worker-spell".to_string(), + ¶ms.id, + ) + .await?; // same as in decider-distro let mut worker_config = TriggerConfig::default(); worker_config.clock.start_sec = 1; worker_config.clock.period_sec = worker_period_sec; - spell_service_api.set_trigger_config( - CallParams::local( - PeerScope::WorkerId(worker_id), - installation_spell_id.clone(), - worker_id.into(), - Duration::from_millis(params.ttl as u64), - ), - worker_config.clone(), - )?; + spell_service_api + .set_trigger_config( + CallParams::local( + PeerScope::WorkerId(worker_id), + installation_spell_id.clone(), + worker_id.into(), + Duration::from_millis(params.ttl as u64), + ), + worker_config.clone(), + ) + .await?; let trigger_config = from_user_config(&worker_config)?.ok_or(JError::new( "Deal activation failed due to failure to parse trigger config", diff --git a/spell-storage/src/storage.rs b/spell-storage/src/storage.rs index 0fe1505565..15ecece1ef 100644 --- a/spell-storage/src/storage.rs +++ b/spell-storage/src/storage.rs @@ -25,7 +25,7 @@ pub struct SpellStorage { } impl SpellStorage { - pub fn create( + pub async fn create( spells_base_dir: &Path, services: &ParticleAppServices, modules: &ModuleRepository, @@ -37,7 +37,7 @@ impl SpellStorage { } else { Self::load_spell_service_from_crate(modules)? }; - let (registered_spells, scope_mapping) = Self::restore_spells(services); + let (registered_spells, scope_mapping) = Self::restore_spells(services).await; Ok(( Self { @@ -103,7 +103,7 @@ impl SpellStorage { )) } - fn restore_spells( + async fn restore_spells( services: &ParticleAppServices, ) -> ( HashMap>, @@ -114,6 +114,7 @@ impl SpellStorage { let spell_services = services .list_services_all() + .await .into_iter() .filter(|s| s.service_type.is_spell()); From a86027a6aed5bc4bd70635be64695e7bfbc94de2 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Fri, 5 Apr 2024 20:33:38 +0300 Subject: [PATCH 06/33] aquavm async --- Cargo.lock | 1 + aquamarine/src/aqua_runtime.rs | 24 ++++++---- aquamarine/src/particle_executor.rs | 20 ++++---- aquamarine/src/plumber.rs | 9 ++-- aquamarine/src/spawner.rs | 24 +++++----- crates/nox-tests/tests/services.rs | 66 +++++++++++++++++---------- crates/spell-service-api/src/lib.rs | 36 +++++++++------ crates/toy-vms/Cargo.toml | 1 + crates/toy-vms/src/easy_vm.rs | 10 ++-- particle-services/src/app_services.rs | 30 ++++++++---- 10 files changed, 136 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1fdde05966..4ce0fd241e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8607,6 +8607,7 @@ name = "toy-vms" version = "0.1.0" dependencies = [ "aquamarine", + "async-trait", "avm-server", "fluence-keypair", "fluence-libp2p", diff --git a/aquamarine/src/aqua_runtime.rs b/aquamarine/src/aqua_runtime.rs index 701d6bbefb..edf8a07946 100644 --- a/aquamarine/src/aqua_runtime.rs +++ b/aquamarine/src/aqua_runtime.rs @@ -14,6 +14,7 @@ * limitations under the License. */ +use async_trait::async_trait; use std::str::FromStr; use std::{error::Error, task::Waker}; @@ -30,6 +31,7 @@ use crate::config::VmConfig; use crate::error::{ExecutionError, FieldError}; use crate::particle_effects::ParticleEffects; +#[async_trait] pub trait AquaRuntime: Sized + Send + 'static { type Config: Clone + Send + 'static; type Error: Error + Send + Sync + 'static; @@ -42,11 +44,11 @@ pub trait AquaRuntime: Sized + Send + 'static { particle_id: String, ) -> ParticleEffects; - fn call( + async fn call( &mut self, - air: impl Into, - prev_data: impl Into>, - current_data: impl Into>, + air: impl Into + Send, + prev_data: impl Into> + Send, + current_data: impl Into> + Send, particle_params: ParticleParameters<'_>, call_results: CallResults, key_pair: &KeyPair, @@ -56,6 +58,7 @@ pub trait AquaRuntime: Sized + Send + 'static { fn memory_stats(&self) -> AVMMemoryStats; } +#[async_trait] impl AquaRuntime for AVMRunner { type Config = VmConfig; type Error = RunnerError; @@ -138,16 +141,16 @@ impl AquaRuntime for AVMRunner { } #[inline] - fn call( + async fn call( &mut self, - air: impl Into, - prev_data: impl Into>, - current_data: impl Into>, + air: impl Into + Send, + prev_data: impl Into> + Send, + current_data: impl Into> + Send, particle_params: ParticleParameters<'_>, call_results: CallResults, key_pair: &KeyPair, ) -> Result { - tokio::runtime::Handle::current().block_on(AVMRunner::call( + AVMRunner::call( self, air, prev_data, @@ -159,7 +162,8 @@ impl AquaRuntime for AVMRunner { call_results, key_pair, particle_params.particle_id.to_string(), - )) + ) + .await } fn memory_stats(&self) -> AVMMemoryStats { diff --git a/aquamarine/src/particle_executor.rs b/aquamarine/src/particle_executor.rs index 11a12b9c15..47f9b345cb 100644 --- a/aquamarine/src/particle_executor.rs +++ b/aquamarine/src/particle_executor.rs @@ -256,7 +256,7 @@ async fn avm_call<'a, RT: AquaRuntime>( prev_data: Vec, ) -> Result, JoinError> { spawner - .spawn_avm_call(move || { + .spawn_avm_call(async move { let particle_id = particle.id.clone(); let now = Instant::now(); let memory_size_before = vm.memory_stats().memory_size; @@ -268,14 +268,16 @@ async fn avm_call<'a, RT: AquaRuntime>( ttl: particle.ttl, }; let current_data = &particle.data[..]; - let avm_outcome = vm.call( - &particle.script, - prev_data, - current_data, - particle_params.clone(), - call_results.clone(), - &key_pair, - ); + let avm_outcome = vm + .call( + &particle.script, + prev_data, + current_data, + particle_params.clone(), + call_results.clone(), + &key_pair, + ) + .await; let memory_size_after = vm.memory_stats().memory_size; let interpretation_time = now.elapsed(); diff --git a/aquamarine/src/plumber.rs b/aquamarine/src/plumber.rs index 35b7dcdf9b..34cfb0321c 100644 --- a/aquamarine/src/plumber.rs +++ b/aquamarine/src/plumber.rs @@ -691,6 +691,7 @@ mod tests { struct VMMock; + #[async_trait] impl AquaRuntime for VMMock { type Config = (); type Error = Infallible; @@ -710,11 +711,11 @@ mod tests { } } - fn call( + async fn call( &mut self, - _air: impl Into, - _prev_data: impl Into>, - _current_data: impl Into>, + _air: impl Into + Send, + _prev_data: impl Into> + Send, + _current_data: impl Into> + Send, _particle_params: ParticleParameters<'_>, _call_results: CallResults, _key_pair: &KeyPair, diff --git a/aquamarine/src/spawner.rs b/aquamarine/src/spawner.rs index 6e88768be7..70e0b36d0d 100644 --- a/aquamarine/src/spawner.rs +++ b/aquamarine/src/spawner.rs @@ -49,10 +49,10 @@ pub(crate) trait SpawnFunctions { /// /// - `F`: The type of the closure. /// - `R`: The type of the result returned by the closure. - fn spawn_avm_call(&self, func: F) -> JoinHandle + fn spawn_avm_call(&self, fut: F) -> JoinHandle where - F: FnOnce() -> R + Send + 'static, - R: Send + 'static; + F: Future + Send + 'static, + F::Output: Send + 'static; /// Shift execution to the specific pool /// @@ -122,12 +122,13 @@ impl SpawnFunctions for RootSpawner { .expect("Failed to spawn a task") } - fn spawn_avm_call(&self, func: F) -> JoinHandle + fn spawn_avm_call(&self, fut: F) -> JoinHandle where - F: FnOnce() -> R + Send + 'static, - R: Send + 'static, + F: Future + Send + 'static, + F::Output: Send + 'static, { - self.runtime_handle.spawn_blocking(func) + self.runtime_handle + .spawn_blocking(|| Handle::current().block_on(fut)) } fn wrap(&self, fut: F) -> TokioContext @@ -178,12 +179,13 @@ impl SpawnFunctions for WorkerSpawner { .expect("Failed to spawn a task") } - fn spawn_avm_call(&self, func: F) -> JoinHandle + fn spawn_avm_call(&self, fut: F) -> JoinHandle where - F: FnOnce() -> R + Send + 'static, - R: Send + 'static, + F: Future + Send + 'static, + F::Output: Send + 'static, { - self.runtime_handle.spawn(async { func() }) + let fut = async { fut.await }; + self.runtime_handle.spawn(fut) } fn wrap(&self, fut: F) -> TokioContext diff --git a/crates/nox-tests/tests/services.rs b/crates/nox-tests/tests/services.rs index b0cc8239c6..f92e4b108d 100644 --- a/crates/nox-tests/tests/services.rs +++ b/crates/nox-tests/tests/services.rs @@ -24,8 +24,9 @@ use std::assert_matches::assert_matches; use base64::{engine::general_purpose::STANDARD as base64, Engine}; use connected_client::ConnectedClient; use created_swarm::{make_swarms, make_swarms_with_cfg}; +use jsonrpsee::core::async_trait; use service_modules::{load_module, Hash}; -use system_services::{PackageDistro, ServiceDistro}; +use system_services::{CallService, Deployment, InitService, PackageDistro, ServiceDistro}; #[tokio::test] async fn test_system_service_override() { @@ -59,30 +60,45 @@ async fn test_system_service_override() { config, }; let name = service_name.clone(); - let init: dyn system_services::InitService = Box::new(move |call, status| { - let name = name.clone(); - let service_status = status - .services - .get(&name) - .expect("deployment status for the service"); - assert_matches!( - service_status, - system_services::ServiceStatus::Created(_), - "wrong deployment status" - ); - let result: eyre::Result<_> = call(name.clone(), "not".to_string(), vec![json!(false)]); - assert!( - result.is_err(), - "must be error due to the the call interface restrictions" - ); - let error = result.unwrap_err().to_string(); - assert_eq!( - error, - format!("Call {}.not return invalid result: true", name), - "the service call must return invalid result due to the call interface restrictions" - ); - Ok(()) - }); + + struct Test { + name: String, + } + #[async_trait] + impl InitService for Test { + async fn init( + &self, + call_service: &dyn CallService, + deployment: Deployment, + ) -> eyre::Result<()> { + let name = self.name.clone(); + let service_status = deployment + .services + .get(&name) + .expect("deployment status for the service"); + assert_matches!( + service_status, + system_services::ServiceStatus::Created(_), + "wrong deployment status" + ); + let result: eyre::Result<_> = call_service + .call(name.clone(), "not".to_string(), vec![json!(false)]) + .await; + assert!( + result.is_err(), + "must be error due to the the call interface restrictions" + ); + let error = result.unwrap_err().to_string(); + assert_eq!( + error, + format!("Call {}.not return invalid result: true", name), + "the service call must return invalid result due to the call interface restrictions" + ); + Ok(()) + } + } + + let init = Box::new(Test { name }); let package = PackageDistro { name: service_name.clone(), version: "some-version", diff --git a/crates/spell-service-api/src/lib.rs b/crates/spell-service-api/src/lib.rs index 05ebe90fe1..d26ab8f22f 100644 --- a/crates/spell-service-api/src/lib.rs +++ b/crates/spell-service-api/src/lib.rs @@ -396,7 +396,9 @@ mod tests { let (pas, repo, local_pid) = create_pas(management_pid, base_dir.into_path()).await; let api = SpellServiceApi::new(pas.clone()); - let (storage, _) = spell_storage::SpellStorage::create(Path::new(""), &pas, &repo).unwrap(); + let (storage, _) = spell_storage::SpellStorage::create(Path::new(""), &pas, &repo) + .await + .unwrap(); let spell_service_blueprint_id = storage.get_blueprint(); let spell_id = create_spell(&pas, spell_service_blueprint_id, local_pid) .await @@ -408,7 +410,7 @@ mod tests { #[tokio::test] async fn test_counter() { let (api, params) = setup().await; - let result1 = api.get_counter(params.clone()); + let result1 = api.get_counter(params.clone()).await; assert!( result1.is_ok(), "must be able to get a counter of an empty spell" @@ -419,13 +421,13 @@ mod tests { "the counter of an empty spell must be zero" ); let new_counter = 7; - let result2 = api.set_counter(params.clone(), new_counter); + let result2 = api.set_counter(params.clone(), new_counter).await; assert!( result2.is_ok(), "must be able to set a counter of an empty spell: {:?}", result2.unwrap_err() ); - let result3 = api.get_counter(params); + let result3 = api.get_counter(params).await; assert!( result3.is_ok(), "must be able to get a counter of an empty spell again" @@ -441,9 +443,11 @@ mod tests { async fn test_script() { let (api, params) = setup().await; let script_original = "(noop)".to_string(); - let result1 = api.set_script(params.clone(), script_original.clone()); + let result1 = api + .set_script(params.clone(), script_original.clone()) + .await; assert!(result1.is_ok(), "must be able to update script"); - let script = api.get_script(params); + let script = api.get_script(params).await; assert!(script.is_ok(), "must be able to load script"); assert_eq!(script.unwrap(), script_original, "scripts must be equal"); } @@ -452,9 +456,11 @@ mod tests { async fn test_trigger_config() { let (api, params) = setup().await; let trigger_config_original = TriggerConfig::default(); - let result1 = api.set_trigger_config(params.clone(), trigger_config_original.clone()); + let result1 = api + .set_trigger_config(params.clone(), trigger_config_original.clone()) + .await; assert!(result1.is_ok(), "must be able to set trigger config"); - let result2 = api.get_trigger_config(params); + let result2 = api.get_trigger_config(params).await; assert!(result2.is_ok(), "must be able to get trigger config"); assert_eq!( result2.unwrap(), @@ -470,7 +476,7 @@ mod tests { "a1" => json!(1), "b1" => json!("test"), }; - let result1 = api.update_kv(host_params.clone(), json!(init_data)); + let result1 = api.update_kv(host_params.clone(), json!(init_data)).await; assert!( result1.is_err(), "must NOT be able to update kv without h/hw key prefixes calling from host" @@ -484,13 +490,13 @@ mod tests { host_params.ttl, ); - let result1 = api.update_kv(params.clone(), json!(init_data)); + let result1 = api.update_kv(params.clone(), json!(init_data)).await; assert!( result1.is_ok(), "must be able to update kv calling as a spell" ); - let result = api.get_string(params.clone(), "a1".to_string()); + let result = api.get_string(params.clone(), "a1".to_string()).await; assert!(result.is_ok(), "must be able to add get_string"); assert_eq!( result.unwrap().unwrap(), @@ -498,7 +504,7 @@ mod tests { "must be able to add get_string" ); - let result = api.get_string(params, "b1".to_string()); + let result = api.get_string(params, "b1".to_string()).await; assert!(result.is_ok(), "must be able to add get_string"); assert_eq!( result.unwrap().unwrap(), @@ -516,14 +522,16 @@ mod tests { "timestamp": 1 })] }); - let result = api.set_trigger_event(params.clone(), trigger_event.to_string()); + let result = api + .set_trigger_event(params.clone(), trigger_event.to_string()) + .await; assert!(result.is_ok(), "must be able to set trigger event"); let function = super::Function { name: "get_string", args: vec![json!("hw_trigger")], }; - let result = api.call::(params, function); + let result = api.call::(params, function).await; assert!(result.is_ok(), "must be able to add get_string"); let trigger_event_read: Result = serde_json::from_str(&result.unwrap().value); diff --git a/crates/toy-vms/Cargo.toml b/crates/toy-vms/Cargo.toml index 6ba245732c..d4f6cfdc7a 100644 --- a/crates/toy-vms/Cargo.toml +++ b/crates/toy-vms/Cargo.toml @@ -15,3 +15,4 @@ avm-server = { workspace = true } futures = { workspace = true } serde_json = { workspace = true } itertools = { workspace = true } +async-trait = { workspace = true } diff --git a/crates/toy-vms/src/easy_vm.rs b/crates/toy-vms/src/easy_vm.rs index 9471e9e55a..907a6b2f8e 100644 --- a/crates/toy-vms/src/easy_vm.rs +++ b/crates/toy-vms/src/easy_vm.rs @@ -14,6 +14,7 @@ * limitations under the License. */ +use async_trait::async_trait; use std::str::FromStr; use std::{convert::Infallible, task::Waker, time::Duration}; @@ -30,6 +31,7 @@ pub struct EasyVM { delay: Option, } +#[async_trait] impl AquaRuntime for EasyVM { type Config = Option; type Error = Infallible; @@ -55,11 +57,11 @@ impl AquaRuntime for EasyVM { } } - fn call( + async fn call( &mut self, - air: impl Into, - _prev_data: impl Into>, - current_data: impl Into>, + air: impl Into + Send, + _prev_data: impl Into> + Send, + current_data: impl Into> + Send, particle_params: ParticleParameters<'_>, _call_results: CallResults, _key_pair: &KeyPair, diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index fd20fc4390..e6146c05af 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -1413,15 +1413,24 @@ mod tests { .await .unwrap(); - let inter1 = pas.get_interface(PeerScope::Host, service_id1, "").unwrap(); + let inter1 = pas + .get_interface(PeerScope::Host, service_id1, "") + .await + .unwrap(); // delete module and check that interfaces will be returned anyway let dir = modules_dir(&base_dir.path().to_path_buf().join("persistent")); let module_file = dir.join(format!("{m_hash}.wasm")); tokio::fs::remove_file(module_file.clone()).await.unwrap(); - let inter2 = pas.get_interface(PeerScope::Host, service_id2, "").unwrap(); - let inter3 = pas.get_interface(PeerScope::Host, service_id3, "").unwrap(); + let inter2 = pas + .get_interface(PeerScope::Host, service_id2, "") + .await + .unwrap(); + let inter3 = pas + .get_interface(PeerScope::Host, service_id3, "") + .await + .unwrap(); assert!(!module_file.exists()); assert_eq!(inter1, inter2); @@ -1478,8 +1487,9 @@ mod tests { let (service_1, _) = pas .get_service(PeerScope::Host, service_id1.clone(), "") + .await .unwrap(); - let service_1_aliases: Vec = service_1.aliases.read().clone(); + let service_1_aliases: Vec = service_1.aliases.read().await.clone(); // the service's alias list must contain the alias assert_eq!(service_1_aliases, vec![alias.to_string()]); @@ -1533,12 +1543,14 @@ mod tests { let (service_1, _) = pas .get_service(PeerScope::Host, service_id1.clone(), "") + .await .unwrap(); let (service_2, _) = pas .get_service(PeerScope::Host, service_id2.clone(), "") + .await .unwrap(); - let service_aliases_1 = service_1.aliases.read().clone(); - let service_aliases_2 = service_2.aliases.read().clone(); + let service_aliases_1 = service_1.aliases.read().await.clone(); + let service_aliases_2 = service_2.aliases.read().await.clone(); // the first service's alias list must not contain the alias assert_eq!(service_aliases_1, Vec::::new()); // the second service's alias list must contain the alias @@ -1599,8 +1611,9 @@ mod tests { let (service, _) = pas .get_service(PeerScope::Host, service_id.clone(), "") + .await .unwrap(); - let service_aliases = service.aliases.read().clone(); + let service_aliases = service.aliases.read().await.clone(); // the service's alias list must contain only 1 alias assert_eq!(service_aliases, vec![alias.to_string()]); @@ -1642,8 +1655,9 @@ mod tests { .unwrap(); let (service_1, _) = pas .get_service(PeerScope::Host, service_id1.clone(), "") + .await .unwrap(); - let service_aliases_1 = service_1.aliases.read().clone(); + let service_aliases_1 = service_1.aliases.read().await.clone(); assert_eq!(service_aliases_1.len(), 1); assert_eq!(service_aliases_1[0], alias); From 97018a86320e853f93dee62dc01934a1cd30362b Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Fri, 5 Apr 2024 20:53:05 +0300 Subject: [PATCH 07/33] ticker --- Cargo.lock | 1 + particle-services/Cargo.toml | 5 +++-- particle-services/src/app_services.rs | 13 +++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ce0fd241e..74ef063835 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6275,6 +6275,7 @@ dependencies = [ "tempdir", "tempfile", "thiserror", + "time", "tokio", "tokio-stream", "tokio-util", diff --git a/particle-services/Cargo.toml b/particle-services/Cargo.toml index 2c4153434b..d081344ec5 100644 --- a/particle-services/Cargo.toml +++ b/particle-services/Cargo.toml @@ -36,9 +36,10 @@ derivative = { workspace = true } eyre = { workspace = true } humantime-serde = { workspace = true } health = { workspace = true } -tokio = { workspace = true, features = ["fs"] } +tokio = { workspace = true, features = ["fs", "time"] } tokio-util = { workspace = true, features = ["rt"] } -tokio-stream = { workspace = true, features = ["fs"] } +tokio-stream = { workspace = true, features = ["fs", "time"] } +time = "0.3.30" [dev-dependencies] tempdir = "0.3.7" diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index e6146c05af..4162b97678 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -29,6 +29,7 @@ use humantime_serde::re::humantime::format_duration as pretty; use serde::{Deserialize, Serialize}; use serde_json::{json, Value as JValue}; use tokio::runtime::Handle; +use tokio_stream::wrappers::IntervalStream; use tokio_util::context::TokioContext; use fluence_libp2p::PeerId; @@ -247,6 +248,18 @@ impl ParticleAppServices { let (app_service_factory, epoch_ticker) = AppServiceFactory::new(wasmtime_config).map_err(ServiceError::Engine)?; + + //TODO: make a setting for that + let stream = IntervalStream::new(tokio::time::interval(Duration::from_secs(1))); + let ticket = epoch_ticker.clone(); + tokio::task::spawn(async move { + stream + .for_each(|_| async { + ticket.increment_epoch(); + }) + .await; + }); + Ok(Self { config, vault, From bf5d83fae42c5f9feb21fc1172531708eae36b98 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Mon, 8 Apr 2024 14:19:48 +0300 Subject: [PATCH 08/33] fix lock --- aquamarine/src/spawner.rs | 1 - particle-services/src/app_services.rs | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aquamarine/src/spawner.rs b/aquamarine/src/spawner.rs index 70e0b36d0d..f6e83ca9c0 100644 --- a/aquamarine/src/spawner.rs +++ b/aquamarine/src/spawner.rs @@ -184,7 +184,6 @@ impl SpawnFunctions for WorkerSpawner { F: Future + Send + 'static, F::Output: Send + 'static, { - let fut = async { fut.await }; self.runtime_handle.spawn(fut) } diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index 4162b97678..1a83f8a99a 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -1061,10 +1061,11 @@ impl ParticleAppServices { } async fn get_or_create_worker_services(&self, worker_id: WorkerId) -> Services { - let workers_services = self.worker_services.read().await; - let worker_services = workers_services.get(&worker_id); + let lock = self.worker_services.read().await; + let worker_services = lock.get(&worker_id); match worker_services { None => { + drop(lock); let mut workers_services = self.worker_services.write().await; //we double check it, because it can be created in another thread let services = workers_services.get(&worker_id); From 5ef99f3534b8e22849a5273d5f367eb1c30abfca Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 13:51:59 +0300 Subject: [PATCH 09/33] mark test as heavy --- crates/nox-tests/tests/builtin.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/nox-tests/tests/builtin.rs b/crates/nox-tests/tests/builtin.rs index ce79a9bb1b..721f2fd653 100644 --- a/crates/nox-tests/tests/builtin.rs +++ b/crates/nox-tests/tests/builtin.rs @@ -1839,8 +1839,8 @@ async fn sign_verify() { } */ -#[tokio::test] -async fn sign_invalid_tetraplets() { +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn sign_invalid_tetraplets_heavy() { enable_logs(); let swarms = make_swarms_with_cfg(2, |mut cfg| { cfg.enabled_system_services = vec!["registry".to_string()]; @@ -1848,6 +1848,8 @@ async fn sign_invalid_tetraplets() { }) .await; + let _span = tracing::info_span!("test", context = "test").entered(); + let mut client = ConnectedClient::connect_with_keypair( swarms[0].multiaddr.clone(), Some(swarms[0].management_keypair.clone()), From b9b535446bd0bd1e8adc7c45dd16f5e345885946 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 14:13:32 +0300 Subject: [PATCH 10/33] graceful shutdown --- Cargo.lock | 2 ++ crates/created-swarm/Cargo.toml | 1 + crates/created-swarm/src/swarm.rs | 4 ++++ nox/Cargo.toml | 1 + nox/src/main.rs | 13 ++++++++++--- nox/src/node.rs | 7 +++++++ 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74ef063835..23667328fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1894,6 +1894,7 @@ dependencies = [ "test-constants", "tokio", "tokio-stream", + "tokio-util", "toy-vms", "tracing", ] @@ -5696,6 +5697,7 @@ dependencies = [ "tempfile", "tokio", "tokio-stream", + "tokio-util", "toml 0.8.12", "tracing", "tracing-appender", diff --git a/crates/created-swarm/Cargo.toml b/crates/created-swarm/Cargo.toml index c3f956a153..bb5aafd0bb 100644 --- a/crates/created-swarm/Cargo.toml +++ b/crates/created-swarm/Cargo.toml @@ -31,6 +31,7 @@ libp2p = { workspace = true } tokio = { workspace = true } +tokio-util = { workspace = true } tokio-stream = { workspace = true } futures = { workspace = true } derivative = { workspace = true } diff --git a/crates/created-swarm/src/swarm.rs b/crates/created-swarm/src/swarm.rs index e431efe42d..d5fe203841 100644 --- a/crates/created-swarm/src/swarm.rs +++ b/crates/created-swarm/src/swarm.rs @@ -48,6 +48,7 @@ use server_config::{ use tempfile::TempDir; use test_constants::{EXECUTION_TIMEOUT, IDLE_CONNECTION_TIMEOUT, TRANSPORT_TIMEOUT}; use tokio::sync::oneshot; +use tokio_util::sync::CancellationToken; use toy_vms::EasyVM; use tracing::{Instrument, Span}; @@ -72,6 +73,8 @@ pub struct CreatedSwarm { pub management_keypair: KeyPair, // stop signal pub exit_outlet: oneshot::Sender<()>, + + pub cancellation_token: CancellationToken, // node connectivity #[derivative(Debug = "ignore")] pub connectivity: Connectivity, @@ -204,6 +207,7 @@ where tmp_dir: input_config.tmp_dir.clone(), management_keypair, exit_outlet: started_node.exit_outlet, + cancellation_token: started_node.cancellation_token, connectivity, aquamarine_api, http_listen_addr, diff --git a/nox/Cargo.toml b/nox/Cargo.toml index 8265c00d1c..dff5a3cbc3 100644 --- a/nox/Cargo.toml +++ b/nox/Cargo.toml @@ -42,6 +42,7 @@ libp2p-connection-limits = { workspace = true } prometheus-client = { workspace = true } futures = { workspace = true } tokio = { workspace = true, features = ["full", "tracing"] } +tokio-util = { workspace = true } tokio-stream = { workspace = true } parking_lot = { workspace = true } humantime-serde = { workspace = true } diff --git a/nox/src/main.rs b/nox/src/main.rs index 3d7a67499b..35fa288db7 100644 --- a/nox/src/main.rs +++ b/nox/src/main.rs @@ -26,12 +26,14 @@ unreachable_patterns )] +use axum::async_trait; use base64::{engine::general_purpose::STANDARD as base64, Engine}; use eyre::WrapErr; use libp2p::PeerId; use std::sync::Arc; use tokio::signal; use tokio::sync::oneshot; +use tokio_util::sync::CancellationToken; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; @@ -51,8 +53,9 @@ const AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); const PKG_NAME: &str = env!("CARGO_PKG_NAME"); +#[async_trait] trait Stoppable { - fn stop(self); + async fn stop(self); } #[cfg(feature = "dhat-heap")] @@ -183,7 +186,7 @@ fn main() -> eyre::Result<()> { signal::ctrl_c().await.expect("Failed to listen for event"); log::info!("Shutting down..."); - fluence.stop(); + fluence.stop().await; Ok(()) }) } @@ -221,19 +224,23 @@ async fn start_fluence( let started_node = node.start(peer_id).await.wrap_err("node failed to start")?; struct Fluence { + cancellation_token: CancellationToken, node_exit_outlet: oneshot::Sender<()>, } + #[async_trait] impl Stoppable for Fluence { - fn stop(self) { + async fn stop(self) { self.node_exit_outlet .send(()) .expect("failed to stop node through exit outlet"); + self.cancellation_token.cancelled().await } } Ok(Fluence { node_exit_outlet: started_node.exit_outlet, + cancellation_token: started_node.cancellation_token, }) } diff --git a/nox/src/node.rs b/nox/src/node.rs index a8a09e558f..c503b98cba 100644 --- a/nox/src/node.rs +++ b/nox/src/node.rs @@ -35,6 +35,7 @@ use libp2p_metrics::{Metrics, Recorder}; use prometheus_client::registry::Registry; use tokio::sync::{mpsc, oneshot}; use tokio::task; +use tokio_util::sync::CancellationToken; use tracing::Instrument; use aquamarine::{ @@ -543,6 +544,7 @@ impl Node { } pub struct StartedNode { + pub cancellation_token: CancellationToken, pub exit_outlet: oneshot::Sender<()>, pub http_listen_addr: Option, } @@ -637,6 +639,9 @@ impl Node { Some(self.config), ); + let cancellation_token = CancellationToken::new(); + let task_cancellation_token = cancellation_token.clone(); + task::Builder::new().name(&task_name.clone()).spawn(async move { let mut http_server = if let Some(http_listen_addr) = http_listen_addr { tracing::info!("Starting http endpoint at {}", http_listen_addr); @@ -687,6 +692,7 @@ impl Node { connectivity.cancel().await; aquamarine_backend.abort(); workers.shutdown(); + task_cancellation_token.cancel() }.in_current_span()).expect("Could not spawn task"); // Note: need to be after the start of the node to be able to subscribe spells @@ -711,6 +717,7 @@ impl Node { Ok(StartedNode { exit_outlet, http_listen_addr, + cancellation_token, }) } From 2c0fa647faa191cfa0f6ffc0582a6913b5e7d5aa Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 14:40:15 +0300 Subject: [PATCH 11/33] fix test --- crates/nox-tests/tests/spells.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/nox-tests/tests/spells.rs b/crates/nox-tests/tests/spells.rs index 7c3fcdcea7..9bea27beb8 100644 --- a/crates/nox-tests/tests/spells.rs +++ b/crates/nox-tests/tests/spells.rs @@ -31,6 +31,7 @@ use fluence_spell_dtos::trigger_config::{ClockConfig, TriggerConfig}; use log_utils::enable_logs; use service_modules::load_module; use spell_event_bus::api::{TriggerInfo, TriggerInfoAqua, MAX_PERIOD_SEC}; +use test_constants::TRANSPORT_TIMEOUT; use test_utils::{create_service, create_service_worker}; use workers::CUID; @@ -981,6 +982,7 @@ async fn spell_call_by_alias() { #[tokio::test] async fn spell_trigger_connection_pool() { + enable_logs(); let swarms = make_swarms(1).await; let mut client = ConnectedClient::connect_with_keypair( swarms[0].multiaddr.clone(), @@ -1029,14 +1031,20 @@ async fn spell_trigger_connection_pool() { // This connect should trigger the spell let connect_num = 5; for _ in 0..connect_num { - ConnectedClient::connect_to(swarms[0].multiaddr.clone()) - .await - .unwrap(); + ConnectedClient::connect_with_timeout( + swarms[0].multiaddr.clone(), + None, + TRANSPORT_TIMEOUT, + Duration::ZERO, //make idle timeout infinite to reduce reconnect probability + None, + ) + .await + .unwrap(); } let mut spell1_counter = 0; let mut spell2_counter = 0; - + // we must receive `connect_num` messages from spell1 subscribed on connect and `connect_num` messages // from spell1 subscribed on disconnect, so 2 * `connect_num` messages in total for _ in 0..2 * connect_num { From 607c581e152cfa5ddb5887adf3cdac719dfec4f5 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 14:59:22 +0300 Subject: [PATCH 12/33] fix test --- crates/connected-client/src/behaviour.rs | 28 ++++++++++--------- crates/connected-client/src/client.rs | 5 +++- .../connected-client/src/connected_client.rs | 4 +++ crates/created-swarm/src/swarm.rs | 2 +- crates/nox-tests/tests/spells.rs | 3 +- .../src/libp2p_protocol/upgrade.rs | 11 +++++++- 6 files changed, 36 insertions(+), 17 deletions(-) diff --git a/crates/connected-client/src/behaviour.rs b/crates/connected-client/src/behaviour.rs index b61f89c246..442e5e466c 100644 --- a/crates/connected-client/src/behaviour.rs +++ b/crates/connected-client/src/behaviour.rs @@ -122,21 +122,23 @@ impl ClientBehaviour { } fn on_dial_failure(&mut self, peer_id: Option, error: &DialError) { - log::warn!( - "Failed to connect to {:?}: {:?}, reconnecting", - peer_id, - error - ); + if self.protocol_config.reconnect_enabled { + log::warn!( + "Failed to connect to {:?}: {:?}, reconnecting", + peer_id, + error + ); - if let DialError::Transport(addresses) = error { - let addresses = addresses.iter().map(|(a, _)| a.clone()).collect(); - self.reconnect = async move { - // TODO: move timeout to config - tokio::time::sleep(Duration::from_secs(1)).await; - addresses + if let DialError::Transport(addresses) = error { + let addresses = addresses.iter().map(|(a, _)| a.clone()).collect(); + self.reconnect = async move { + // TODO: move timeout to config + tokio::time::sleep(Duration::from_secs(1)).await; + addresses + } + .boxed() + .into(); } - .boxed() - .into(); } } diff --git a/crates/connected-client/src/client.rs b/crates/connected-client/src/client.rs index 5710fff787..146a2f4bdf 100644 --- a/crates/connected-client/src/client.rs +++ b/crates/connected-client/src/client.rs @@ -139,6 +139,7 @@ impl Client { None, transport_timeout, idle_connection_timeout, + true, ) } @@ -148,13 +149,15 @@ impl Client { key_pair: Option, transport_timeout: Duration, idle_connection_timeout: Duration, + reconnect_enabled: bool, ) -> Result<(Client, JoinHandle<()>), Box> { let (client_outlet, client_inlet) = mpsc::channel(128); let (relay_outlet, mut relay_inlet) = mpsc::channel(128); let (stop_outlet, stop_inlet) = oneshot::channel(); - let protocol_config = ProtocolConfig::new(transport_timeout, transport_timeout); + let protocol_config = + ProtocolConfig::new(transport_timeout, transport_timeout, reconnect_enabled); let client = Client::new(relay_outlet, client_inlet, stop_outlet, key_pair); let mut swarm = client.dial( relay, diff --git a/crates/connected-client/src/connected_client.rs b/crates/connected-client/src/connected_client.rs index e731333370..cd2cd2f32e 100644 --- a/crates/connected-client/src/connected_client.rs +++ b/crates/connected-client/src/connected_client.rs @@ -100,6 +100,7 @@ impl ConnectedClient { timeout, idle_connection_timeout, particle_ttl, + true, ) .await } @@ -114,6 +115,7 @@ impl ConnectedClient { TRANSPORT_TIMEOUT, IDLE_CONNECTION_TIMEOUT, None, + true, ) .await } @@ -124,6 +126,7 @@ impl ConnectedClient { timeout: Duration, idle_connection_timeout: Duration, particle_ttl: Option, + reconnect_enabled: bool, ) -> Result { use core::result::Result; use std::io::{Error, ErrorKind}; @@ -136,6 +139,7 @@ impl ConnectedClient { key_pair.map(Into::into), timeout, idle_connection_timeout, + reconnect_enabled, ) .expect("sender connected"); let result: Result<_, Error> = if let Some(ClientEvent::NewConnection { diff --git a/crates/created-swarm/src/swarm.rs b/crates/created-swarm/src/swarm.rs index d5fe203841..be1b2a2b20 100644 --- a/crates/created-swarm/src/swarm.rs +++ b/crates/created-swarm/src/swarm.rs @@ -393,7 +393,7 @@ pub async fn create_swarm_with_runtime( resolved.node_config.transport_config.transport = Transport::Memory; resolved.node_config.transport_config.socket_timeout = TRANSPORT_TIMEOUT; resolved.node_config.protocol_config = - ProtocolConfig::new(TRANSPORT_TIMEOUT, TRANSPORT_TIMEOUT); + ProtocolConfig::new(TRANSPORT_TIMEOUT, TRANSPORT_TIMEOUT, true); resolved.node_config.bootstrap_nodes = config.bootstraps.clone(); resolved.node_config.bootstrap_config = BootstrapConfig::zero(); diff --git a/crates/nox-tests/tests/spells.rs b/crates/nox-tests/tests/spells.rs index 9bea27beb8..9bc9192b75 100644 --- a/crates/nox-tests/tests/spells.rs +++ b/crates/nox-tests/tests/spells.rs @@ -1037,6 +1037,7 @@ async fn spell_trigger_connection_pool() { TRANSPORT_TIMEOUT, Duration::ZERO, //make idle timeout infinite to reduce reconnect probability None, + false, ) .await .unwrap(); @@ -1044,7 +1045,7 @@ async fn spell_trigger_connection_pool() { let mut spell1_counter = 0; let mut spell2_counter = 0; - + // we must receive `connect_num` messages from spell1 subscribed on connect and `connect_num` messages // from spell1 subscribed on disconnect, so 2 * `connect_num` messages in total for _ in 0..2 * connect_num { diff --git a/particle-protocol/src/libp2p_protocol/upgrade.rs b/particle-protocol/src/libp2p_protocol/upgrade.rs index 3bc4cd8178..b2d0bfbad8 100644 --- a/particle-protocol/src/libp2p_protocol/upgrade.rs +++ b/particle-protocol/src/libp2p_protocol/upgrade.rs @@ -43,6 +43,9 @@ pub struct ProtocolConfig { default = "default_outbound_substream_timeout" )] pub outbound_substream_timeout: Duration, + + #[serde(default)] + pub reconnect_enabled: bool, } impl Default for ProtocolConfig { @@ -50,6 +53,7 @@ impl Default for ProtocolConfig { Self { upgrade_timeout: default_upgrade_timeout(), outbound_substream_timeout: default_outbound_substream_timeout(), + reconnect_enabled: true, } } } @@ -62,10 +66,15 @@ fn default_upgrade_timeout() -> Duration { } impl ProtocolConfig { - pub fn new(upgrade_timeout: Duration, outbound_substream_timeout: Duration) -> Self { + pub fn new( + upgrade_timeout: Duration, + outbound_substream_timeout: Duration, + reconnect_enabled: bool, + ) -> Self { Self { upgrade_timeout, outbound_substream_timeout, + reconnect_enabled, } } } From 6a1736319eb4f44c332a74dd637edf8fc17963d3 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 15:03:21 +0300 Subject: [PATCH 13/33] clippy fix --- crates/chain-connector/src/connector.rs | 2 +- crates/chain-connector/src/function/offer.rs | 8 ++++---- crates/chain-listener/src/listener.rs | 4 ++-- crates/nox-tests/tests/spells.rs | 2 +- nox/src/http.rs | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/chain-connector/src/connector.rs b/crates/chain-connector/src/connector.rs index 42045b3d65..07d52d05cc 100644 --- a/crates/chain-connector/src/connector.rs +++ b/crates/chain-connector/src/connector.rs @@ -689,7 +689,7 @@ mod tests { }))) .with_body(expected_response) .create(); - let commitment_id = CommitmentId(decode_hex(&commitment_id).unwrap().try_into().unwrap()); + let commitment_id = CommitmentId(decode_hex(commitment_id).unwrap().try_into().unwrap()); let status = get_connector(&url) .get_commitment_status(commitment_id) .await diff --git a/crates/chain-connector/src/function/offer.rs b/crates/chain-connector/src/function/offer.rs index e679b7a059..eadce4930e 100644 --- a/crates/chain-connector/src/function/offer.rs +++ b/crates/chain-connector/src/function/offer.rs @@ -61,7 +61,7 @@ mod tests { #[tokio::test] async fn decode_compute_unit() { let data = "aa3046a12a1aac6e840625e6329d70b427328fec36dc8d273e5e6454b85633d50000000000000000000000005e3d0fde6f793b3115a9e7f5ebc195bbeed35d6c00000000000000000000000000000000000000000000000000000000000003e8"; - let compute_unit = super::ComputeUnit::abi_decode(&decode_hex(&data).unwrap(), true); + let compute_unit = super::ComputeUnit::abi_decode(&decode_hex(data).unwrap(), true); assert!(compute_unit.is_ok()); let compute_unit = compute_unit.unwrap(); @@ -80,7 +80,7 @@ mod tests { #[tokio::test] async fn decode_compute_unit_no_deal() { let data = "aa3046a12a1aac6e840625e6329d70b427328fec36dc8d273e5e6454b85633d5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8"; - let compute_unit = super::ComputeUnit::abi_decode(&decode_hex(&data).unwrap(), true); + let compute_unit = super::ComputeUnit::abi_decode(&decode_hex(data).unwrap(), true); assert!(compute_unit.is_ok()); let compute_unit = compute_unit.unwrap(); assert_eq!( @@ -94,7 +94,7 @@ mod tests { #[tokio::test] async fn decode_compute_peer_no_commitment() { let data = "0xaa3046a12a1aac6e840625e6329d70b427328fec36dc8d273e5e6454b85633d5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005b73c5498c1e3b4dba84de0f1833c4a029d90519"; - let compute_peer = ComputePeer::abi_decode(&decode_hex(&data).unwrap(), true); + let compute_peer = ComputePeer::abi_decode(&decode_hex(data).unwrap(), true); assert!(compute_peer.is_ok()); let compute_peer = compute_peer.unwrap(); assert_eq!( @@ -112,7 +112,7 @@ mod tests { #[tokio::test] async fn decode_compute_peer() { let data = "0xaa3046a12a1aac6e840625e6329d70b427328fec36dc8d273e5e6454b85633d5aa3046a12a1aac6e840625e6329d70b427328feceedc8d273e5e6454b85633b5000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000005b73c5498c1e3b4dba84de0f1833c4a029d90519"; - let compute_peer = ComputePeer::abi_decode(&decode_hex(&data).unwrap(), true); + let compute_peer = ComputePeer::abi_decode(&decode_hex(data).unwrap(), true); assert!(compute_peer.is_ok()); let compute_peer = compute_peer.unwrap(); assert_eq!( diff --git a/crates/chain-listener/src/listener.rs b/crates/chain-listener/src/listener.rs index 1b542dbed5..c29298cab7 100644 --- a/crates/chain-listener/src/listener.rs +++ b/crates/chain-listener/src/listener.rs @@ -1036,7 +1036,7 @@ impl ChainListener { .filter(|p| p.id.global_nonce == self.global_nonce) .collect(); - if proofs.len() > 0 { + if !proofs.is_empty() { tracing::info!(target: "chain-listener", "Found {} proofs from polling", proofs.len()); } @@ -1258,7 +1258,7 @@ impl ChainListener { } if stats_updated { - tracing::info!(target: "chain-listener", "Confirmed proofs count: {:?}", self.proof_counter.iter().map(|(cu, count)| format!("{}: {}", cu, count.to_string())).collect::>()); + tracing::info!(target: "chain-listener", "Confirmed proofs count: {:?}", self.proof_counter.iter().map(|(cu, count)| format!("{}: {}", cu, count)).collect::>()); } Ok(()) diff --git a/crates/nox-tests/tests/spells.rs b/crates/nox-tests/tests/spells.rs index 9bc9192b75..b5873c6dea 100644 --- a/crates/nox-tests/tests/spells.rs +++ b/crates/nox-tests/tests/spells.rs @@ -1771,7 +1771,7 @@ async fn create_remove_worker() { let script = r#"(call %init_peer_id% ("getDataSrv" "spell_id") [] spell_id)"#; let config = make_clock_config(0, 1, 0); - let (spell_id, worker_id) = create_spell(&mut client, &script, config, json!({})).await; + let (spell_id, worker_id) = create_spell(&mut client, script, config, json!({})).await; let service = create_service_worker( &mut client, "file_share", diff --git a/nox/src/http.rs b/nox/src/http.rs index 252ac34c78..e9e2253821 100644 --- a/nox/src/http.rs +++ b/nox/src/http.rs @@ -552,11 +552,11 @@ mod tests { .wrap_err("parse config") .unwrap(); - let resolved_config = unresolved_config + + + unresolved_config .resolve() .wrap_err("resolve config") - .unwrap(); - - resolved_config + .unwrap() } } From a31a7670cae1b3460338d2c13ecb838846c7c7af Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 15:08:44 +0300 Subject: [PATCH 14/33] clippy fix --- nox/src/http.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/nox/src/http.rs b/nox/src/http.rs index e9e2253821..1bfaa0ebc3 100644 --- a/nox/src/http.rs +++ b/nox/src/http.rs @@ -552,8 +552,6 @@ mod tests { .wrap_err("parse config") .unwrap(); - - unresolved_config .resolve() .wrap_err("resolve config") From 6397ac53dcdbbcb90ff9f74ea0afb80742f14d18 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 15:34:26 +0300 Subject: [PATCH 15/33] fix --- crates/connected-client/src/behaviour.rs | 14 ++++++++++---- crates/connected-client/src/client.rs | 8 +++++--- particle-protocol/src/libp2p_protocol/upgrade.rs | 11 +---------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/crates/connected-client/src/behaviour.rs b/crates/connected-client/src/behaviour.rs index 442e5e466c..bda396da60 100644 --- a/crates/connected-client/src/behaviour.rs +++ b/crates/connected-client/src/behaviour.rs @@ -48,8 +48,12 @@ pub struct FluenceClientBehaviour { } impl FluenceClientBehaviour { - pub fn new(protocol_config: ProtocolConfig, public_key: PublicKey) -> Self { - let client = ClientBehaviour::new(protocol_config); + pub fn new( + protocol_config: ProtocolConfig, + public_key: PublicKey, + reconnect_enabled: bool, + ) -> Self { + let client = ClientBehaviour::new(protocol_config, reconnect_enabled); let identify = Identify::new(IdentifyConfig::new(PROTOCOL_NAME.into(), public_key)); let ping = Ping::new( PingConfig::new() @@ -79,15 +83,17 @@ pub struct ClientBehaviour { events: VecDeque, reconnect: Option>>, waker: Option, + reconnect_enabled: bool, } impl ClientBehaviour { - pub fn new(protocol_config: ProtocolConfig) -> Self { + pub fn new(protocol_config: ProtocolConfig, reconnect_enabled: bool) -> Self { Self { protocol_config, events: VecDeque::default(), reconnect: None, waker: None, + reconnect_enabled, } } @@ -122,7 +128,7 @@ impl ClientBehaviour { } fn on_dial_failure(&mut self, peer_id: Option, error: &DialError) { - if self.protocol_config.reconnect_enabled { + if self.reconnect_enabled { log::warn!( "Failed to connect to {:?}: {:?}, reconnecting", peer_id, diff --git a/crates/connected-client/src/client.rs b/crates/connected-client/src/client.rs index 146a2f4bdf..de2c27e304 100644 --- a/crates/connected-client/src/client.rs +++ b/crates/connected-client/src/client.rs @@ -102,10 +102,12 @@ impl Client { transport_timeout: Duration, idle_connection_timeout: Duration, protocol_config: ProtocolConfig, + reconnect_enabled: bool, ) -> Result, Box> { let mut swarm = { let public_key = self.key_pair.public(); - let behaviour = FluenceClientBehaviour::new(protocol_config, public_key.into()); + let behaviour = + FluenceClientBehaviour::new(protocol_config, public_key.into(), reconnect_enabled); let kp = self.key_pair.clone().into(); let transport = build_transport(transport, &kp, transport_timeout); @@ -156,8 +158,7 @@ impl Client { let (stop_outlet, stop_inlet) = oneshot::channel(); - let protocol_config = - ProtocolConfig::new(transport_timeout, transport_timeout, reconnect_enabled); + let protocol_config = ProtocolConfig::new(transport_timeout, transport_timeout); let client = Client::new(relay_outlet, client_inlet, stop_outlet, key_pair); let mut swarm = client.dial( relay, @@ -165,6 +166,7 @@ impl Client { transport_timeout, idle_connection_timeout, protocol_config, + reconnect_enabled, )?; let mut stop_inlet = Some(stop_inlet); diff --git a/particle-protocol/src/libp2p_protocol/upgrade.rs b/particle-protocol/src/libp2p_protocol/upgrade.rs index b2d0bfbad8..3bc4cd8178 100644 --- a/particle-protocol/src/libp2p_protocol/upgrade.rs +++ b/particle-protocol/src/libp2p_protocol/upgrade.rs @@ -43,9 +43,6 @@ pub struct ProtocolConfig { default = "default_outbound_substream_timeout" )] pub outbound_substream_timeout: Duration, - - #[serde(default)] - pub reconnect_enabled: bool, } impl Default for ProtocolConfig { @@ -53,7 +50,6 @@ impl Default for ProtocolConfig { Self { upgrade_timeout: default_upgrade_timeout(), outbound_substream_timeout: default_outbound_substream_timeout(), - reconnect_enabled: true, } } } @@ -66,15 +62,10 @@ fn default_upgrade_timeout() -> Duration { } impl ProtocolConfig { - pub fn new( - upgrade_timeout: Duration, - outbound_substream_timeout: Duration, - reconnect_enabled: bool, - ) -> Self { + pub fn new(upgrade_timeout: Duration, outbound_substream_timeout: Duration) -> Self { Self { upgrade_timeout, outbound_substream_timeout, - reconnect_enabled, } } } From 4ff53987d37a18f6c2ae343068019b367b8269f5 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 15:35:26 +0300 Subject: [PATCH 16/33] fix --- crates/created-swarm/src/swarm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/created-swarm/src/swarm.rs b/crates/created-swarm/src/swarm.rs index be1b2a2b20..d5fe203841 100644 --- a/crates/created-swarm/src/swarm.rs +++ b/crates/created-swarm/src/swarm.rs @@ -393,7 +393,7 @@ pub async fn create_swarm_with_runtime( resolved.node_config.transport_config.transport = Transport::Memory; resolved.node_config.transport_config.socket_timeout = TRANSPORT_TIMEOUT; resolved.node_config.protocol_config = - ProtocolConfig::new(TRANSPORT_TIMEOUT, TRANSPORT_TIMEOUT, true); + ProtocolConfig::new(TRANSPORT_TIMEOUT, TRANSPORT_TIMEOUT); resolved.node_config.bootstrap_nodes = config.bootstraps.clone(); resolved.node_config.bootstrap_config = BootstrapConfig::zero(); From 2834702b98a54ef4d0b7e4d978db3c2d898fb18f Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 15:58:32 +0300 Subject: [PATCH 17/33] fix --- crates/connected-client/src/behaviour.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/connected-client/src/behaviour.rs b/crates/connected-client/src/behaviour.rs index bda396da60..a280a7fe6f 100644 --- a/crates/connected-client/src/behaviour.rs +++ b/crates/connected-client/src/behaviour.rs @@ -161,15 +161,17 @@ impl ClientBehaviour { match cp { ConnectedPoint::Dialer { address, .. } => { - let address = address.clone(); - log::warn!( - "Disconnected from {} @ {:?}, reconnecting", - peer_id, - address - ); - self.events.push_front(SwarmEventType::Dial { - opts: address.into(), - }); + if self.reconnect_enabled { + let address = address.clone(); + log::warn!( + "Disconnected from {} @ {:?}, reconnecting", + peer_id, + address + ); + self.events.push_front(SwarmEventType::Dial { + opts: address.into(), + }); + } } ConnectedPoint::Listener { send_back_addr, From c11c806a1c722f54936c03aff4bb8f3b3ed33f03 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 18:45:08 +0300 Subject: [PATCH 18/33] fix --- crates/nox-tests/tests/spells.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/nox-tests/tests/spells.rs b/crates/nox-tests/tests/spells.rs index b5873c6dea..db0b464e83 100644 --- a/crates/nox-tests/tests/spells.rs +++ b/crates/nox-tests/tests/spells.rs @@ -984,9 +984,13 @@ async fn spell_call_by_alias() { async fn spell_trigger_connection_pool() { enable_logs(); let swarms = make_swarms(1).await; - let mut client = ConnectedClient::connect_with_keypair( + let mut client = ConnectedClient::connect_with_timeout( swarms[0].multiaddr.clone(), Some(swarms[0].management_keypair.clone()), + TRANSPORT_TIMEOUT, + Duration::from_secs(60 * 5), //make idle timeout big to reduce reconnect probability + None, + true, ) .await .wrap_err("connect client") @@ -1035,7 +1039,7 @@ async fn spell_trigger_connection_pool() { swarms[0].multiaddr.clone(), None, TRANSPORT_TIMEOUT, - Duration::ZERO, //make idle timeout infinite to reduce reconnect probability + Duration::from_secs(60 * 5), //make idle timeout big to reduce reconnect probability None, false, ) @@ -1064,8 +1068,10 @@ async fn spell_trigger_connection_pool() { if spell_id == spell_id1 { spell1_counter += 1; - } else { + } else if spell_id == spell_id2 { spell2_counter += 1; + } else { + assert!(false) } } } From 52a36e1994efca27be1918e1ca7e62052953c49b Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 9 Apr 2024 18:59:29 +0300 Subject: [PATCH 19/33] fix --- crates/created-swarm/src/swarm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/created-swarm/src/swarm.rs b/crates/created-swarm/src/swarm.rs index d5fe203841..91daa0845f 100644 --- a/crates/created-swarm/src/swarm.rs +++ b/crates/created-swarm/src/swarm.rs @@ -389,7 +389,6 @@ pub async fn create_swarm_with_runtime( UnresolvedConfig::deserialize(node_config).expect("created_swarm: deserialize config"); let mut resolved = node_config.resolve().expect("failed to resolve config"); - resolved.node_config.transport_config.transport = Transport::Memory; resolved.node_config.transport_config.socket_timeout = TRANSPORT_TIMEOUT; resolved.node_config.protocol_config = @@ -400,6 +399,7 @@ pub async fn create_swarm_with_runtime( resolved.node_config.bootstrap_frequency = 1; resolved.metrics_config.metrics_enabled = false; + resolved.node_config.health_config.health_check_enabled = true; resolved.node_config.allow_local_addresses = true; From 72695ec12e4e00df439ce64dbab6aaad14a5c53d Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Wed, 10 Apr 2024 13:53:08 +0300 Subject: [PATCH 20/33] fix --- crates/connected-client/src/behaviour.rs | 4 ++++ crates/nox-tests/tests/spells.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/connected-client/src/behaviour.rs b/crates/connected-client/src/behaviour.rs index a280a7fe6f..04c0a4b467 100644 --- a/crates/connected-client/src/behaviour.rs +++ b/crates/connected-client/src/behaviour.rs @@ -145,6 +145,8 @@ impl ClientBehaviour { .boxed() .into(); } + } else { + log::error!("Failed to connect to {:?}: {:?}", peer_id, error) } } @@ -171,6 +173,8 @@ impl ClientBehaviour { self.events.push_front(SwarmEventType::Dial { opts: address.into(), }); + } else { + log::error!("Disconnected from {} @ {:?}", peer_id, address); } } ConnectedPoint::Listener { diff --git a/crates/nox-tests/tests/spells.rs b/crates/nox-tests/tests/spells.rs index db0b464e83..c2c39d5fd9 100644 --- a/crates/nox-tests/tests/spells.rs +++ b/crates/nox-tests/tests/spells.rs @@ -990,7 +990,7 @@ async fn spell_trigger_connection_pool() { TRANSPORT_TIMEOUT, Duration::from_secs(60 * 5), //make idle timeout big to reduce reconnect probability None, - true, + false, ) .await .wrap_err("connect client") From fa59eac65e44cb9fbd3be72d291e7e316591e948 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Wed, 10 Apr 2024 13:56:14 +0300 Subject: [PATCH 21/33] fix --- crates/nox-tests/tests/spells.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/nox-tests/tests/spells.rs b/crates/nox-tests/tests/spells.rs index c2c39d5fd9..54adfd453b 100644 --- a/crates/nox-tests/tests/spells.rs +++ b/crates/nox-tests/tests/spells.rs @@ -988,9 +988,9 @@ async fn spell_trigger_connection_pool() { swarms[0].multiaddr.clone(), Some(swarms[0].management_keypair.clone()), TRANSPORT_TIMEOUT, - Duration::from_secs(60 * 5), //make idle timeout big to reduce reconnect probability + Duration::from_secs(60 * 5), // it makes idle timeout big to keep connection alive without reconnection None, - false, + false, // reconnects has side effects on test result ) .await .wrap_err("connect client") @@ -1039,9 +1039,9 @@ async fn spell_trigger_connection_pool() { swarms[0].multiaddr.clone(), None, TRANSPORT_TIMEOUT, - Duration::from_secs(60 * 5), //make idle timeout big to reduce reconnect probability + Duration::from_secs(60 * 5), // it makes idle timeout big to keep connection alive without reconnection None, - false, + false, // reconnects has side effects on test result ) .await .unwrap(); @@ -1071,7 +1071,7 @@ async fn spell_trigger_connection_pool() { } else if spell_id == spell_id2 { spell2_counter += 1; } else { - assert!(false) + panic!("Unexpected spell_id {}", spell_id) } } } From 9edeff9987103663cf1a80d57832393bffb039fc Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Wed, 10 Apr 2024 16:52:53 +0300 Subject: [PATCH 22/33] fix --- .config/nextest.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.config/nextest.toml b/.config/nextest.toml index ad9a3a5359..838e6b39dd 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -24,6 +24,10 @@ filter = 'test(heavy)' threads-required = 3 retries = { backoff = "fixed", count = 3, delay = "5s", jitter = true } +[[profile.default.overrides]] +filter = 'package(nox-tests) & test(spell)' +threads-required = 4 + [profile.ci] fail-fast = false From 1573ca13728ce56414bb03f80a2ebc944084ef3a Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Wed, 10 Apr 2024 17:55:24 +0300 Subject: [PATCH 23/33] fix --- .config/nextest.toml | 8 ++++++++ crates/nox-tests/tests/builtin.rs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.config/nextest.toml b/.config/nextest.toml index 838e6b39dd..9cbff1cae2 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -28,6 +28,14 @@ retries = { backoff = "fixed", count = 3, delay = "5s", jitter = true } filter = 'package(nox-tests) & test(spell)' threads-required = 4 +[[profile.default.overrides]] +filter = 'binary_id(/^nox-tests::spells/)' +threads-required = 4 + +[[profile.default.overrides]] +filter = 'binary_id(/^nox-tests::builtin/)' +threads-required = 2 + [profile.ci] fail-fast = false diff --git a/crates/nox-tests/tests/builtin.rs b/crates/nox-tests/tests/builtin.rs index 721f2fd653..29a3533b4e 100644 --- a/crates/nox-tests/tests/builtin.rs +++ b/crates/nox-tests/tests/builtin.rs @@ -910,7 +910,7 @@ async fn array() { .await .unwrap(); log::info!("result {:?}", result); - assert_eq!(result, vec![json!(["hi"])]) + assert_eq!(result, vec![json!(["hi"])]); } #[tokio::test] From fc863da4ae67ef59ab805460b0c9f249db809118 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Thu, 11 Apr 2024 19:16:45 +0300 Subject: [PATCH 24/33] fix config --- Cargo.lock | 3 +- Cargo.toml | 2 + aquamarine/Cargo.toml | 2 +- aquamarine/src/aqua_runtime.rs | 27 ++-- aquamarine/src/aquamarine.rs | 21 ++- aquamarine/src/config.rs | 40 +++++ aquamarine/src/lib.rs | 4 +- aquamarine/src/plumber.rs | 31 +++- aquamarine/src/vm_pool.rs | 8 +- crates/created-swarm/src/swarm.rs | 10 +- crates/peer-metrics/Cargo.toml | 2 +- crates/server-config/Cargo.toml | 5 +- crates/server-config/src/avm_config.rs | 4 + crates/server-config/src/lib.rs | 2 +- crates/server-config/src/node_config.rs | 7 + crates/server-config/src/services_config.rs | 148 +----------------- .../server-config/src/wasm_backend_config.rs | 28 ++++ crates/spell-service-api/src/lib.rs | 5 +- crates/toy-vms/src/easy_vm.rs | 7 +- nox/src/main.rs | 19 ++- nox/src/node.rs | 17 +- particle-builtins/Cargo.toml | 2 +- particle-builtins/src/builtins.rs | 7 +- particle-builtins/src/lib.rs | 2 +- particle-modules/Cargo.toml | 2 +- particle-services/Cargo.toml | 5 +- particle-services/src/app_services.rs | 13 +- particle-services/src/config.rs | 147 +++++++++++++++++ particle-services/src/lib.rs | 3 + 29 files changed, 372 insertions(+), 201 deletions(-) create mode 100644 crates/server-config/src/wasm_backend_config.rs create mode 100644 particle-services/src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 23667328fc..83fe43b565 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6251,6 +6251,8 @@ name = "particle-services" version = "0.1.0" dependencies = [ "base64 0.21.7", + "bytesize", + "cid-utils", "config-utils", "derivative", "eyre", @@ -6272,7 +6274,6 @@ dependencies = [ "peer-metrics", "serde", "serde_json", - "server-config", "service-modules", "tempdir", "tempfile", diff --git a/Cargo.toml b/Cargo.toml index 01d5d0d6b6..f0405f3ca8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,6 +181,8 @@ alloy-sol-types = "0.6.4" alloy-primitives = "0.6.4" alloy_serde_macro = "0.1.2" const-hex = "1.11.3" +bytesize = "1.3.0" + [profile.dev] opt-level = 0 diff --git a/aquamarine/Cargo.toml b/aquamarine/Cargo.toml index 328e331862..dac48f02b9 100644 --- a/aquamarine/Cargo.toml +++ b/aquamarine/Cargo.toml @@ -41,7 +41,7 @@ thiserror = { workspace = true } humantime = "2.1.0" anyhow = "1.0.79" eyre = { workspace = true } -bytesize = "1.3.0" +bytesize = { workspace = true } async-trait = { workspace = true } health = { workspace = true } config = { version = "0.13.4", features = [] } diff --git a/aquamarine/src/aqua_runtime.rs b/aquamarine/src/aqua_runtime.rs index edf8a07946..532d0432fe 100644 --- a/aquamarine/src/aqua_runtime.rs +++ b/aquamarine/src/aqua_runtime.rs @@ -24,7 +24,7 @@ use avm_server::{ }; use fluence_keypair::KeyPair; use libp2p::PeerId; -use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; +use marine_wasmtime_backend::WasmtimeWasmBackend; use tracing::Level; use crate::config::VmConfig; @@ -36,7 +36,11 @@ pub trait AquaRuntime: Sized + Send + 'static { type Config: Clone + Send + 'static; type Error: Error + Send + Sync + 'static; - fn create_runtime(config: Self::Config, waker: Waker) -> Result; + fn create_runtime( + config: Self::Config, + wasm_backend: WasmtimeWasmBackend, + waker: Waker, + ) -> Result; // TODO: move into_effects inside call fn into_effects( @@ -64,20 +68,11 @@ impl AquaRuntime for AVMRunner { type Error = RunnerError; /// Creates `AVM` in background (on blocking threadpool) - fn create_runtime(config: Self::Config, waker: Waker) -> Result { - let mut wasmtime_config = WasmtimeConfig::default(); - // TODO async-marine: impl proper configuration - // TODO async-marine: move to the right place - // TODO async-marine: maybe use the same as for ParticleAppServices - wasmtime_config - .debug_info(true) - .wasm_backtrace(true) - .epoch_interruption(true) - .async_wasm_stack(2 * 1024 * 1024) - .max_wasm_stack(2 * 1024 * 1024); - let backend = WasmtimeWasmBackend::new(wasmtime_config).map_err(|e| { - Self::Error::MarineError(fluence_app_service::MarineError::EngineError(e.into())) - })?; + fn create_runtime( + config: Self::Config, + backend: WasmtimeWasmBackend, + waker: Waker, + ) -> Result { let avm_runtime_limits = AVMRuntimeLimits::new( config.air_size_limit, config.particle_size_limit, diff --git a/aquamarine/src/aquamarine.rs b/aquamarine/src/aquamarine.rs index c680b7b5a5..3fe9f14530 100644 --- a/aquamarine/src/aquamarine.rs +++ b/aquamarine/src/aquamarine.rs @@ -20,6 +20,7 @@ use std::task::Poll; use std::time::Duration; use futures::StreamExt; +use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; use tokio::sync::mpsc; use tokio::task::JoinHandle; use tracing::{instrument, Instrument}; @@ -33,6 +34,7 @@ use workers::{Event, KeyStorage, PeerScopes, Receiver, Workers}; use crate::command::Command; use crate::command::Command::{AddService, Ingest, RemoveService}; +use crate::config::WasmBackendConfig; use crate::error::AquamarineApiError; use crate::vm_pool::VmPool; use crate::{ @@ -53,7 +55,8 @@ impl AquamarineBackend { #[allow(clippy::too_many_arguments)] pub fn new( config: VmPoolConfig, - runtime_config: RT::Config, + vm_config: RT::Config, + avm_wasm_backend_config: WasmBackendConfig, data_store_config: DataStoreConfig, builtins: F, out: EffectsChannel, @@ -75,14 +78,25 @@ impl AquamarineBackend { data_store_config.particles_anomaly_dir, ); let data_store: Arc = Arc::new(data_store); + let mut wasmtime_config = WasmtimeConfig::default(); + wasmtime_config + .debug_info(true) + .wasm_backtrace(true) + .epoch_interruption(true) + .async_wasm_stack(2 * 1024 * 1024) + .max_wasm_stack(2 * 1024 * 1024); + let avm_wasm_backend = + WasmtimeWasmBackend::new(avm_wasm_backend_config.to_wasmtime_config())?; + let vm_pool = VmPool::new( config.pool_size, - runtime_config.clone(), + vm_config.clone(), vm_pool_metrics, health_registry, + avm_wasm_backend.clone(), ); let plumber = Plumber::new( - runtime_config, + vm_config, vm_pool, data_store.clone(), builtins, @@ -90,6 +104,7 @@ impl AquamarineBackend { workers, key_storage, scopes, + avm_wasm_backend, ); let this = Self { inlet, diff --git a/aquamarine/src/config.rs b/aquamarine/src/config.rs index a35e8ee997..aba6a48e19 100644 --- a/aquamarine/src/config.rs +++ b/aquamarine/src/config.rs @@ -16,6 +16,7 @@ use fs_utils::to_abs_path; use libp2p::PeerId; +use marine_wasmtime_backend::WasmtimeConfig; use std::path::PathBuf; use std::time::Duration; @@ -36,6 +37,45 @@ pub struct VmConfig { pub hard_limit_enabled: bool, } +#[derive(Debug, Clone)] +pub struct WasmBackendConfig { + /// Configures whether DWARF debug information will be emitted during compilation. + pub debug_info: bool, + /// Configures whether the errors from the VM should collect the wasm backtrace and parse debug info. + pub wasm_backtrace: bool, + /// Configures the size of the stacks used for asynchronous execution. + pub async_wasm_stack: usize, + /// Configures the maximum amount of stack space available for executing WebAssembly code. + pub max_wasm_stack: usize, + /// Enables the epoch interruption mechanism. + pub epoch_interruption_duration: Option, +} + +impl WasmBackendConfig { + pub fn to_wasmtime_config(&self) -> WasmtimeConfig { + let mut config = WasmtimeConfig::default(); + config + .debug_info(self.debug_info) + .wasm_backtrace(self.wasm_backtrace) + .epoch_interruption(true) + .async_wasm_stack(self.async_wasm_stack) + .max_wasm_stack(self.max_wasm_stack); + config + } +} + +impl Default for WasmBackendConfig { + fn default() -> Self { + Self { + debug_info: true, + wasm_backtrace: true, + async_wasm_stack: 2 * 1024 * 1024, + max_wasm_stack: 2 * 1024 * 1024, + epoch_interruption_duration: Some(Duration::from_secs(1)), + } + } +} + #[derive(Debug, Clone)] pub struct VmPoolConfig { /// Number of VMs to create diff --git a/aquamarine/src/lib.rs b/aquamarine/src/lib.rs index 2a35b6d3d8..dd101eeaa5 100644 --- a/aquamarine/src/lib.rs +++ b/aquamarine/src/lib.rs @@ -46,13 +46,13 @@ mod particle_effects; mod health; mod vm_pool; -use marine_wasmtime_backend::WasmtimeWasmBackend; - pub use crate::aqua_runtime::AquaRuntime; pub use crate::aquamarine::{AquamarineApi, AquamarineBackend}; pub use crate::config::{DataStoreConfig, VmConfig, VmPoolConfig}; pub use crate::particle_effects::{InterpretationStats, ParticleEffects, RemoteRoutingEffects}; pub type AVMRunner = avm_server::avm_runner::AVMRunner; +pub use config::WasmBackendConfig; pub use error::AquamarineApiError; +pub use marine_wasmtime_backend::WasmtimeWasmBackend; pub use particle_data_store::{DataStoreError, ParticleDataStore}; pub use plumber::Plumber; diff --git a/aquamarine/src/plumber.rs b/aquamarine/src/plumber.rs index 34cfb0321c..469866d1a8 100644 --- a/aquamarine/src/plumber.rs +++ b/aquamarine/src/plumber.rs @@ -27,6 +27,7 @@ use std::{ }; use futures::task::Waker; +use marine_wasmtime_backend::WasmtimeWasmBackend; use tokio::runtime::Handle; use tokio::task; use tracing::instrument; @@ -78,6 +79,7 @@ pub struct Plumber { scopes: PeerScopes, cleanup_future: Option>, root_runtime_handle: Handle, + avm_wasm_backend: WasmtimeWasmBackend, } impl Plumber { @@ -90,6 +92,7 @@ impl Plumber { workers: Arc, key_storage: Arc, scope: PeerScopes, + avm_wasm_backend: WasmtimeWasmBackend, ) -> Self { Self { config, @@ -107,6 +110,7 @@ impl Plumber { scopes: scope, cleanup_future: None, root_runtime_handle: Handle::current(), + avm_wasm_backend, } } @@ -176,7 +180,13 @@ impl Plumber { } pub fn create_worker_pool(&mut self, worker_id: WorkerId, thread_count: usize) { - let vm_pool = VmPool::new(thread_count, self.config.clone(), None, None); // TODO: add metrics + let vm_pool = VmPool::new( + thread_count, + self.config.clone(), + None, + None, + self.avm_wasm_backend.clone(), + ); // TODO: add metrics self.worker_vm_pools.insert(worker_id, vm_pool); } @@ -664,6 +674,7 @@ mod tests { use crate::{AquaRuntime, ParticleDataStore, ParticleEffects, Plumber}; use async_trait::async_trait; use avm_server::avm_runner::RawAVMOutcome; + use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; use particle_services::PeerScope; use tracing::Span; @@ -696,7 +707,11 @@ mod tests { type Config = (); type Error = Infallible; - fn create_runtime(_config: Self::Config, _waker: Waker) -> Result { + fn create_runtime( + _config: Self::Config, + _backend: WasmtimeWasmBackend, + _waker: Waker, + ) -> Result { Ok(VMMock) } @@ -741,8 +756,17 @@ mod tests { } async fn plumber() -> Plumber> { + let mut wasmtime_config = WasmtimeConfig::default(); + wasmtime_config + .debug_info(true) + .wasm_backtrace(true) + .epoch_interruption(true) + .async_wasm_stack(2 * 1024 * 1024) + .max_wasm_stack(2 * 1024 * 1024); + let avm_wasm_backend = + WasmtimeWasmBackend::new(wasmtime_config).expect("Could not create wasm backend"); // Pool is of size 1 so it's easier to control tests - let vm_pool = VmPool::new(1, (), None, None); + let vm_pool = VmPool::new(1, (), None, None, avm_wasm_backend.clone()); let builtin_mock = Arc::new(MockF); let root_key_pair: KeyPair = KeyPair::generate_ed25519(); @@ -792,6 +816,7 @@ mod tests { workers.clone(), key_storage.clone(), scope.clone(), + avm_wasm_backend ) } diff --git a/aquamarine/src/vm_pool.rs b/aquamarine/src/vm_pool.rs index 06eaab4ccc..7fe8f035b5 100644 --- a/aquamarine/src/vm_pool.rs +++ b/aquamarine/src/vm_pool.rs @@ -20,6 +20,7 @@ use std::task::{Context, Poll}; use futures::future::BoxFuture; use futures::FutureExt; +use marine_wasmtime_backend::WasmtimeWasmBackend; use tokio::task::JoinError; use health::HealthCheckRegistry; @@ -52,6 +53,7 @@ pub struct VmPool { pool_size: usize, metrics: Option, health: Option, + wasm_backend: WasmtimeWasmBackend, } impl VmPool { @@ -61,6 +63,7 @@ impl VmPool { runtime_config: RT::Config, metrics: Option, health_registry: Option<&mut HealthCheckRegistry>, + wasm_backend: WasmtimeWasmBackend, ) -> Self { let health = health_registry.map(|registry| { let health = VMPoolHealth::new(pool_size); @@ -75,6 +78,7 @@ impl VmPool { pool_size, metrics, health, + wasm_backend, }; this.meter(|m| m.set_pool_size(pool_size)); @@ -145,11 +149,13 @@ impl VmPool { fn create_avm(&self, cx: &Context<'_>) -> RuntimeF { let config = self.runtime_config.clone(); + let wasm_backend = self.wasm_backend.clone(); let waker = cx.waker().clone(); async { let task_result = - tokio::task::spawn_blocking(|| RT::create_runtime(config, waker)).await; //TODO: move waker outside create runtime + tokio::task::spawn_blocking(|| RT::create_runtime(config, wasm_backend, waker)) + .await; //TODO: move waker outside create runtime match task_result { Ok(joined_res) => joined_res.map_err(|e| CreateAVMError::AVMError(Box::new(e))), Err(e) => Err(CreateAVMError::JoinError(e)), diff --git a/crates/created-swarm/src/swarm.rs b/crates/created-swarm/src/swarm.rs index 91daa0845f..c0549b3aa0 100644 --- a/crates/created-swarm/src/swarm.rs +++ b/crates/created-swarm/src/swarm.rs @@ -30,7 +30,7 @@ use libp2p::{core::Multiaddr, PeerId}; use serde::Deserialize; use air_interpreter_fs::{air_interpreter_path, write_default_air_interpreter}; -use aquamarine::{AVMRunner, AquamarineApi, VmConfig}; +use aquamarine::{AVMRunner, AquamarineApi, VmConfig, WasmBackendConfig}; use aquamarine::{AquaRuntime, DataStoreConfig}; use base64::{engine::general_purpose::STANDARD as base64, Engine}; use cid_utils::Hash; @@ -442,6 +442,13 @@ pub async fn create_swarm_with_runtime( listen_on: config.listen_on.clone(), manager: management_peer_id, }); + let avm_wasm_backend_config = WasmBackendConfig{ + debug_info: true, + wasm_backtrace: true, + async_wasm_stack: 2*1024*1024, + max_wasm_stack: 2*1024*1024, + epoch_interruption_duration: Some(Duration::from_secs(1)), + }; let data_store_config = DataStoreConfig::new(tmp_dir.clone()); @@ -455,6 +462,7 @@ pub async fn create_swarm_with_runtime( resolved.clone(), core_manager, vm_config, + avm_wasm_backend_config, data_store_config, "some version", "some version", diff --git a/crates/peer-metrics/Cargo.toml b/crates/peer-metrics/Cargo.toml index 2438d56c18..3c869eef1c 100644 --- a/crates/peer-metrics/Cargo.toml +++ b/crates/peer-metrics/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] prometheus-client = { workspace = true } log = { workspace = true } -bytesize = "1.3.0" +bytesize = { workspace = true } fluence-app-service = { workspace = true } fluence-libp2p = { workspace = true } particle-execution = { workspace = true } diff --git a/crates/server-config/Cargo.toml b/crates/server-config/Cargo.toml index e51bb0dfbe..21c554becc 100644 --- a/crates/server-config/Cargo.toml +++ b/crates/server-config/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] config-utils = { workspace = true } fs-utils = { workspace = true } -cid-utils = { workspace = true } particle-protocol = { workspace = true } fluence-libp2p = { workspace = true, features = ["tokio"] } air-interpreter-fs = { workspace = true } @@ -15,9 +14,12 @@ peer-metrics = { workspace = true } fluence-keypair = { workspace = true } types = { workspace = true } core-manager = { workspace = true } +cid-utils = { workspace = true } +bytesize = { workspace = true } log = "0.4.20" toml = "0.8.12" # otherwise deserialisation of Cargo.toml doesn't work + libp2p = { workspace = true } libp2p-metrics = { workspace = true } libp2p-connection-limits = { workspace = true } @@ -32,7 +34,6 @@ base64 = { workspace = true } num_cpus = { workspace = true } eyre = { workspace = true } derivative = { workspace = true } -bytesize = { version = "1.3.0", features = ["serde"] } serde_with = { workspace = true } config = { version = "0.13.4", default-features = false, features = ["toml"] } clarity = { workspace = true } diff --git a/crates/server-config/src/avm_config.rs b/crates/server-config/src/avm_config.rs index 5be66fa848..62debc278d 100644 --- a/crates/server-config/src/avm_config.rs +++ b/crates/server-config/src/avm_config.rs @@ -1,3 +1,4 @@ +use crate::wasm_backend_config::WasmBackendConfig; use derivative::Derivative; use serde::{Deserialize, Serialize}; use serde_with::serde_as; @@ -30,4 +31,7 @@ pub struct AVMConfig { /// Hard limit AquaVM behavior control knob. #[serde(default)] pub hard_limit_enabled: bool, + + #[serde(default)] + pub wasm_backend: WasmBackendConfig, } diff --git a/crates/server-config/src/lib.rs b/crates/server-config/src/lib.rs index 633311a5a5..59f596b4fd 100644 --- a/crates/server-config/src/lib.rs +++ b/crates/server-config/src/lib.rs @@ -40,6 +40,7 @@ mod node_config; mod resolved_config; mod services_config; pub mod system_services_config; +mod wasm_backend_config; pub use defaults::*; pub use resolved_config::load_config; @@ -52,5 +53,4 @@ pub use network_config::NetworkConfig; pub use node_config::{ChainConfig, ChainListenerConfig, NodeConfig, TransportConfig}; pub use resolved_config::TracingConfig; pub use resolved_config::{ResolvedConfig, UnresolvedConfig}; -pub use services_config::ServicesConfig; pub use system_services_config::{AquaIpfsConfig, DeciderConfig, SystemServicesConfig}; diff --git a/crates/server-config/src/node_config.rs b/crates/server-config/src/node_config.rs index fb9ab9466e..ba0fe73926 100644 --- a/crates/server-config/src/node_config.rs +++ b/crates/server-config/src/node_config.rs @@ -24,6 +24,7 @@ use types::peer_id; use crate::avm_config::AVMConfig; use crate::keys::{decode_key, decode_secret_key, load_key}; +use crate::services_config::ServicesConfig; use crate::system_services_config::{ServiceKey, SystemServicesConfig}; use crate::{BootstrapConfig, KademliaConfig}; @@ -151,6 +152,9 @@ pub struct UnresolvedNodeConfig { #[serde(default = "default_dev_mode_config")] pub dev_mode: DevModeConfig, + + #[serde(default)] + pub services: ServicesConfig, } impl UnresolvedNodeConfig { @@ -220,6 +224,7 @@ impl UnresolvedNodeConfig { http_config: self.http_config, chain_config: self.chain_config, chain_listener_config: self.chain_listener_config, + services: self.services, }; Ok(result) @@ -400,6 +405,8 @@ pub struct NodeConfig { pub chain_config: Option, pub chain_listener_config: Option, + + pub services: ServicesConfig, } #[derive(Clone, Deserialize, Serialize, Derivative, Copy)] diff --git a/crates/server-config/src/services_config.rs b/crates/server-config/src/services_config.rs index 6d5ae45d66..6af50fd43a 100644 --- a/crates/server-config/src/services_config.rs +++ b/crates/server-config/src/services_config.rs @@ -1,147 +1,7 @@ -/* - * Copyright 2020 Fluence Labs Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +use crate::wasm_backend_config::WasmBackendConfig; +use serde::{Deserialize, Serialize}; -use fs_utils::{create_dirs, set_write_only, to_abs_path}; - -use bytesize::ByteSize; -use cid_utils::Hash; -use libp2p::PeerId; -use std::collections::HashMap; -use std::path::{Path, PathBuf}; - -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct ServicesConfig { - /// Peer id of the current node - pub local_peer_id: PeerId, - /// Path of the blueprint directory containing blueprints and wasm modules - pub blueprint_dir: PathBuf, - /// Opaque environment variables to be passed on each service creation - /// TODO: isolate envs of different modules (i.e., module A shouldn't access envs of module B) - pub envs: HashMap, - /// Persistent working dir for services - pub persistent_work_dir: PathBuf, - /// Ephemeral working dir for services - pub ephemeral_work_dir: PathBuf, - /// Dir to store .wasm modules and their configs - pub modules_dir: PathBuf, - /// Dir to persist info about running services - pub services_dir: PathBuf, - /// Dir to store directories shared between services - /// in the span of a single particle execution - pub particles_vault_dir: PathBuf, - /// key that could manage services - pub management_peer_id: PeerId, - /// key to manage builtins services initialization - pub builtins_management_peer_id: PeerId, - /// Default heap size in bytes available for the module unless otherwise specified. - pub default_service_memory_limit: Option, - /// List of allowed effector modules by CID - pub allowed_effectors: HashMap>, - /// Mapping of binary names to their paths for mounted binaries used in developer mode - pub mounted_binaries_mapping: HashMap, - /// Is in the developer mode - pub is_dev_mode: bool, -} - -impl ServicesConfig { - #[allow(clippy::too_many_arguments)] - pub fn new( - local_peer_id: PeerId, - persistent_dir: PathBuf, - ephemeral_dir: PathBuf, - particles_vault_dir: PathBuf, - envs: HashMap, - management_peer_id: PeerId, - builtins_management_peer_id: PeerId, - default_service_memory_limit: Option, - allowed_effectors: HashMap>, - mounted_binaries_mapping: HashMap, - is_dev_mode: bool, - ) -> Result { - let persistent_dir = to_abs_path(persistent_dir); - let ephemeral_dir = to_abs_path(ephemeral_dir); - - let allowed_effectors = allowed_effectors - .into_iter() - .map(|(cid, effector)| { - let effector = effector - .into_iter() - .map(|(name, path_str)| { - let path = Path::new(&path_str); - match path.try_exists() { - Err(err) => log::warn!( - "cannot check binary `{path_str}` for effector `{cid}`: {err}" - ), - Ok(false) => log::warn!( - "binary `{path_str}` for effector `{cid}` does not exist" - ), - _ => {} - }; - (name, path.to_path_buf()) - }) - .collect::<_>(); - (cid, effector) - }) - .collect::<_>(); - - let mounted_binaries_mapping = if !is_dev_mode { - HashMap::new() - } else { - mounted_binaries_mapping - .into_iter() - .map(|(name, path_str)| { - let path = Path::new(&path_str); - match path.try_exists() { - Err(err) => log::warn!("cannot check binary `{path_str}`: {err}"), - Ok(false) => log::warn!("binary `{path_str}` does not exist"), - _ => {} - }; - (name, path.to_path_buf()) - }) - .collect::<_>() - }; - - let this = Self { - local_peer_id, - blueprint_dir: config_utils::blueprint_dir(&persistent_dir), - persistent_work_dir: config_utils::workdir(&persistent_dir), - ephemeral_work_dir: config_utils::workdir(&ephemeral_dir), - modules_dir: config_utils::modules_dir(&persistent_dir), - services_dir: config_utils::services_dir(&persistent_dir), - particles_vault_dir, - envs, - management_peer_id, - builtins_management_peer_id, - default_service_memory_limit, - allowed_effectors, - mounted_binaries_mapping, - is_dev_mode, - }; - - create_dirs(&[ - &this.blueprint_dir, - &this.persistent_work_dir, - &this.ephemeral_work_dir, - &this.modules_dir, - &this.services_dir, - &this.particles_vault_dir, - ])?; - - set_write_only(&this.particles_vault_dir)?; - - Ok(this) - } + pub wasm_backend: WasmBackendConfig, } diff --git a/crates/server-config/src/wasm_backend_config.rs b/crates/server-config/src/wasm_backend_config.rs new file mode 100644 index 0000000000..bf54f7f18f --- /dev/null +++ b/crates/server-config/src/wasm_backend_config.rs @@ -0,0 +1,28 @@ +use serde::{Deserialize, Serialize}; +use std::time::Duration; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct WasmBackendConfig { + /// Configures whether DWARF debug information will be emitted during compilation. + pub debug_info: bool, + /// Configures whether the errors from the VM should collect the wasm backtrace and parse debug info. + pub wasm_backtrace: bool, + /// Configures the size of the stacks used for asynchronous execution. + pub async_wasm_stack: usize, + /// Configures the maximum amount of stack space available for executing WebAssembly code. + pub max_wasm_stack: usize, + /// Enables the epoch interruption mechanism. + pub epoch_interruption_duration: Option, +} + +impl Default for WasmBackendConfig { + fn default() -> Self { + Self { + debug_info: true, + wasm_backtrace: true, + async_wasm_stack: 2 * 1024 * 1024, + max_wasm_stack: 2 * 1024 * 1024, + epoch_interruption_duration: Some(Duration::from_secs(1)), + } + } +} diff --git a/crates/spell-service-api/src/lib.rs b/crates/spell-service-api/src/lib.rs index d26ab8f22f..bd4b3775e7 100644 --- a/crates/spell-service-api/src/lib.rs +++ b/crates/spell-service-api/src/lib.rs @@ -283,14 +283,13 @@ mod tests { use std::path::{Path, PathBuf}; use std::sync::Arc; - use particle_services::{ParticleAppServices, PeerScope, ServiceType}; + use particle_services::{ParticleAppServices, ParticleAppServicesConfig, PeerScope, ServiceType}; use fluence_libp2p::PeerId; use libp2p_identity::Keypair; use tempdir::TempDir; use particle_modules::ModuleRepository; - use server_config::ServicesConfig; use fluence_keypair::KeyPair; use fluence_spell_dtos::trigger_config::TriggerConfig; @@ -346,7 +345,7 @@ mod tests { let workers = Arc::new(workers); let service_memory_limit = server_config::default_service_memory_limit(); - let config = ServicesConfig::new( + let config = ParticleAppServicesConfig::new( root_key_pair.get_peer_id(), persistent_dir, ephemeral_dir, diff --git a/crates/toy-vms/src/easy_vm.rs b/crates/toy-vms/src/easy_vm.rs index 907a6b2f8e..83a73c7ff4 100644 --- a/crates/toy-vms/src/easy_vm.rs +++ b/crates/toy-vms/src/easy_vm.rs @@ -23,6 +23,7 @@ use avm_server::SoftLimitsTriggering; use avm_server::{AVMMemoryStats, CallResults, ParticleParameters}; use itertools::Itertools; +use aquamarine::WasmtimeWasmBackend; use aquamarine::{AquaRuntime, ParticleEffects}; use fluence_keypair::KeyPair; use fluence_libp2p::PeerId; @@ -36,7 +37,11 @@ impl AquaRuntime for EasyVM { type Config = Option; type Error = Infallible; - fn create_runtime(delay: Option, _: Waker) -> Result { + fn create_runtime( + delay: Option, + _backend: WasmtimeWasmBackend, + _: Waker, + ) -> Result { Ok(EasyVM { delay }) } diff --git a/nox/src/main.rs b/nox/src/main.rs index 35fa288db7..898cc8d0c2 100644 --- a/nox/src/main.rs +++ b/nox/src/main.rs @@ -38,7 +38,7 @@ use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use air_interpreter_fs::write_default_air_interpreter; -use aquamarine::{AVMRunner, DataStoreConfig, VmConfig}; +use aquamarine::{AVMRunner, DataStoreConfig, VmConfig, WasmBackendConfig}; use config_utils::to_peer_id; use core_manager::{CoreManager, CoreManagerFunctions, DevCoreManager, StrictCoreManager}; use fs_utils::to_abs_path; @@ -201,6 +201,8 @@ async fn start_fluence( let listen_addrs = config.listen_multiaddrs(); let vm_config = vm_config(&config); + let avm_wasm_backend_config = avm_wasm_backend_config(&config); + let data_store_config = DataStoreConfig::new(config.dir_config.avm_base_dir.clone()); let system_services_config = config.system_services.clone(); @@ -212,6 +214,7 @@ async fn start_fluence( config, core_manager, vm_config, + avm_wasm_backend_config, data_store_config, VERSION, air_interpreter_wasm::VERSION, @@ -271,3 +274,17 @@ fn vm_config(config: &ResolvedConfig) -> VmConfig { config.node_config.avm_config.hard_limit_enabled, ) } + +fn avm_wasm_backend_config(config: &ResolvedConfig) -> WasmBackendConfig { + WasmBackendConfig { + debug_info: config.node_config.services.wasm_backend.debug_info, + wasm_backtrace: config.node_config.services.wasm_backend.wasm_backtrace, + async_wasm_stack: config.node_config.services.wasm_backend.async_wasm_stack, + max_wasm_stack: config.node_config.services.wasm_backend.max_wasm_stack, + epoch_interruption_duration: config + .node_config + .services + .wasm_backend + .epoch_interruption_duration, + } +} diff --git a/nox/src/node.rs b/nox/src/node.rs index c503b98cba..99b1ef93a5 100644 --- a/nox/src/node.rs +++ b/nox/src/node.rs @@ -40,7 +40,7 @@ use tracing::Instrument; use aquamarine::{ AquaRuntime, AquamarineApi, AquamarineApiError, AquamarineBackend, DataStoreConfig, - RemoteRoutingEffects, VmPoolConfig, + RemoteRoutingEffects, VmPoolConfig, WasmBackendConfig, }; use chain_connector::ChainConnector; use chain_listener::ChainListener; @@ -49,7 +49,7 @@ use connection_pool::ConnectionPoolT; use core_manager::CoreManager; use fluence_libp2p::build_transport; use health::HealthCheckRegistry; -use particle_builtins::{Builtins, CustomService, NodeInfo}; +use particle_builtins::{Builtins, CustomService, NodeInfo, ParticleAppServicesConfig}; use particle_execution::ParticleFunctionStatic; use particle_protocol::ExtendedParticle; use peer_metrics::{ @@ -57,7 +57,7 @@ use peer_metrics::{ ServicesMetrics, ServicesMetricsBackend, SpellMetrics, VmPoolMetrics, }; use server_config::system_services_config::ServiceKey; -use server_config::{NetworkConfig, ResolvedConfig, ServicesConfig}; +use server_config::{NetworkConfig, ResolvedConfig}; use sorcerer::Sorcerer; use spell_event_bus::api::{PeerEvent, SpellEventBusApi, TriggerEvent}; use spell_event_bus::bus::SpellEventBus; @@ -162,6 +162,7 @@ impl Node { config: ResolvedConfig, core_manager: Arc, vm_config: RT::Config, + avm_wasm_backend_config: WasmBackendConfig, data_store_config: DataStoreConfig, node_version: &'static str, air_version: &'static str, @@ -201,7 +202,7 @@ impl Node { let workers = Arc::new(workers); - let services_config = ServicesConfig::new( + let services_config = ParticleAppServicesConfig::new( scopes.get_host_peer_id(), config.dir_config.services_persistent_dir.clone(), config.dir_config.services_ephemeral_dir.clone(), @@ -320,6 +321,7 @@ impl Node { let (aquamarine_backend, aquamarine_api) = AquamarineBackend::new( pool_config, vm_config, + avm_wasm_backend_config, data_store_config, Arc::clone(&builtins), effects_out, @@ -522,7 +524,7 @@ impl Node { pub fn builtins( connectivity: Connectivity, - services_config: ServicesConfig, + services_config: ParticleAppServicesConfig, services_metrics: ServicesMetrics, key_storage: Arc, workers: Arc, @@ -749,7 +751,7 @@ mod tests { use serde_json::json; use air_interpreter_fs::{air_interpreter_path, write_default_air_interpreter}; - use aquamarine::{AVMRunner, DataStoreConfig, VmConfig}; + use aquamarine::{AVMRunner, DataStoreConfig, VmConfig, WasmBackendConfig}; use config_utils::to_peer_id; use connected_client::ConnectedClient; use core_manager::DummyCoreManager; @@ -786,6 +788,8 @@ mod tests { None, false, ); + let avm_wasm_backend_config = WasmBackendConfig::default(); + let data_store_config = DataStoreConfig::new(config.dir_config.avm_base_dir.clone()); let system_service_distros = @@ -798,6 +802,7 @@ mod tests { config, core_manager, vm_config, + avm_wasm_backend_config, data_store_config, "some version", "some version", diff --git a/particle-builtins/Cargo.toml b/particle-builtins/Cargo.toml index 2c805fa619..25a0f50567 100644 --- a/particle-builtins/Cargo.toml +++ b/particle-builtins/Cargo.toml @@ -37,7 +37,7 @@ humantime-serde = { workspace = true } rand = { workspace = true } futures = { workspace = true } itertools = { workspace = true } -bytesize = "1.3.0" +bytesize = { workspace = true } derivative = { workspace = true } fluence-app-service = { workspace = true } async-trait = { workspace = true } diff --git a/particle-builtins/src/builtins.rs b/particle-builtins/src/builtins.rs index 5226ee4d99..5ca85cda9e 100644 --- a/particle-builtins/src/builtins.rs +++ b/particle-builtins/src/builtins.rs @@ -42,9 +42,10 @@ use particle_modules::{ AddBlueprint, EffectorsMode, ModuleConfig, ModuleRepository, NamedModuleConfig, WASIConfig, }; use particle_protocol::Contact; -use particle_services::{ParticleAppServices, PeerScope, ServiceInfo, ServiceType}; +use particle_services::{ + ParticleAppServices, ParticleAppServicesConfig, PeerScope, ServiceInfo, ServiceType, +}; use peer_metrics::ServicesMetrics; -use server_config::ServicesConfig; use types::peer_id; use uuid_utils::uuid; use workers::{KeyStorage, PeerScopes, Workers}; @@ -98,7 +99,7 @@ where { pub fn new( connectivity: C, - config: ServicesConfig, + config: ParticleAppServicesConfig, services_metrics: ServicesMetrics, key_storage: Arc, workers: Arc, diff --git a/particle-builtins/src/lib.rs b/particle-builtins/src/lib.rs index 61c966dfda..7c202e2f96 100644 --- a/particle-builtins/src/lib.rs +++ b/particle-builtins/src/lib.rs @@ -32,7 +32,7 @@ pub use builtins::{Builtins, CustomService}; pub use identify::NodeInfo; pub use outcome::{ok, wrap, wrap_unit}; - +pub use particle_services::ParticleAppServicesConfig; mod builtins; mod debug; mod error; diff --git a/particle-modules/Cargo.toml b/particle-modules/Cargo.toml index 4c48c1358e..c000a74754 100644 --- a/particle-modules/Cargo.toml +++ b/particle-modules/Cargo.toml @@ -24,7 +24,7 @@ thiserror = { workspace = true } parking_lot = { workspace = true } eyre = { workspace = true } fstrings = { workspace = true } -bytesize = "1.3.0" +bytesize = { workspace = true } libipld = { workspace = true } [dev-dependencies] diff --git a/particle-services/Cargo.toml b/particle-services/Cargo.toml index d081344ec5..e2cc12c489 100644 --- a/particle-services/Cargo.toml +++ b/particle-services/Cargo.toml @@ -13,7 +13,6 @@ fs-utils = { workspace = true } service-modules = { workspace = true } json-utils = { workspace = true } particle-args = { workspace = true } -server-config = { workspace = true } fluence-libp2p = { workspace = true } particle-execution = { workspace = true } peer-metrics = { workspace = true } @@ -21,6 +20,10 @@ uuid-utils = { workspace = true } now-millis = { workspace = true } workers = { workspace = true } futures = { workspace = true } +bytesize = { workspace = true } +cid-utils = { workspace = true } +libp2p-identity = { workspace = true } +config-utils = { workspace = true } fluence-app-service = { workspace = true } diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index 1a83f8a99a..080aee6b1a 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -42,7 +42,6 @@ use peer_metrics::{ ServiceCallStats, ServiceMemoryStat, ServiceType as MetricServiceType, ServicesMetrics, ServicesMetricsBuiltin, }; -use server_config::ServicesConfig; use types::peer_scope::PeerScope; use uuid_utils::uuid; use workers::{PeerScopes, WorkerId, Workers}; @@ -51,6 +50,7 @@ use crate::error::ServiceError; use crate::error::ServiceError::{AliasAsServiceId, Forbidden, NoSuchAlias}; use crate::health::PersistedServiceHealth; use crate::persistence::{load_persisted_services, remove_persisted_service, PersistedService}; +use crate::ParticleAppServicesConfig; use crate::ServiceError::{ FailedToCreateDirectory, ForbiddenAlias, ForbiddenAliasRoot, ForbiddenAliasWorker, InternalError, NoSuchService, @@ -172,7 +172,7 @@ struct Services { #[derive(Derivative)] #[derivative(Debug, Clone)] pub struct ParticleAppServices { - config: ServicesConfig, + config: ParticleAppServicesConfig, // TODO: move vault to Plumber or Actor pub vault: ParticleVault, root_services: Services, @@ -220,7 +220,7 @@ fn get_service( impl ParticleAppServices { pub fn new( - config: ServicesConfig, + config: ParticleAppServicesConfig, modules: ModuleRepository, metrics: Option, health_registry: Option<&mut HealthCheckRegistry>, @@ -1251,7 +1251,6 @@ mod tests { use config_utils::modules_dir; use fluence_libp2p::RandomPeerId; use particle_modules::{AddBlueprint, ModuleRepository}; - use server_config::ServicesConfig; use service_modules::load_module; use service_modules::Hash; use types::peer_scope::PeerScope; @@ -1259,7 +1258,7 @@ mod tests { use crate::app_services::{ServiceAlias, ServiceType}; use crate::persistence::load_persisted_services; - use crate::{ParticleAppServices, ServiceError}; + use crate::{ParticleAppServices, ParticleAppServicesConfig, ServiceError}; fn create_pid() -> PeerId { let keypair = Keypair::generate_ed25519(); @@ -1277,7 +1276,7 @@ mod tests { let vault_dir = ephemeral_dir.join("vault"); let keypairs_dir = persistent_dir.join("keypairs"); let workers_dir = persistent_dir.join("workers"); - let service_memory_limit = server_config::default_service_memory_limit(); + let service_memory_limit = bytesize::ByteSize::b(bytesize::gib(4_u64) - 1); let key_storage = KeyStorage::from_path(keypairs_dir.clone(), root_keypair.clone().into()) .await .expect("Could not load key storage"); @@ -1302,7 +1301,7 @@ mod tests { let workers = Arc::new(workers); - let config = ServicesConfig::new( + let config = ParticleAppServicesConfig::new( PeerId::from(root_keypair.public()), persistent_dir, ephemeral_dir, diff --git a/particle-services/src/config.rs b/particle-services/src/config.rs new file mode 100644 index 0000000000..269a15dd93 --- /dev/null +++ b/particle-services/src/config.rs @@ -0,0 +1,147 @@ +/* + * Copyright 2020 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use fs_utils::{create_dirs, set_write_only, to_abs_path}; + +use bytesize::ByteSize; +use cid_utils::Hash; +use libp2p_identity::PeerId; +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +#[derive(Debug, Clone)] +pub struct ParticleAppServicesConfig { + /// Peer id of the current node + pub local_peer_id: PeerId, + /// Path of the blueprint directory containing blueprints and wasm modules + pub blueprint_dir: PathBuf, + /// Opaque environment variables to be passed on each service creation + /// TODO: isolate envs of different modules (i.e., module A shouldn't access envs of module B) + pub envs: HashMap, + /// Persistent working dir for services + pub persistent_work_dir: PathBuf, + /// Ephemeral working dir for services + pub ephemeral_work_dir: PathBuf, + /// Dir to store .wasm modules and their configs + pub modules_dir: PathBuf, + /// Dir to persist info about running services + pub services_dir: PathBuf, + /// Dir to store directories shared between services + /// in the span of a single particle execution + pub particles_vault_dir: PathBuf, + /// key that could manage services + pub management_peer_id: PeerId, + /// key to manage builtins services initialization + pub builtins_management_peer_id: PeerId, + /// Default heap size in bytes available for the module unless otherwise specified. + pub default_service_memory_limit: Option, + /// List of allowed effector modules by CID + pub allowed_effectors: HashMap>, + /// Mapping of binary names to their paths for mounted binaries used in developer mode + pub mounted_binaries_mapping: HashMap, + /// Is in the developer mode + pub is_dev_mode: bool, +} + +impl ParticleAppServicesConfig { + #[allow(clippy::too_many_arguments)] + pub fn new( + local_peer_id: PeerId, + persistent_dir: PathBuf, + ephemeral_dir: PathBuf, + particles_vault_dir: PathBuf, + envs: HashMap, + management_peer_id: PeerId, + builtins_management_peer_id: PeerId, + default_service_memory_limit: Option, + allowed_effectors: HashMap>, + mounted_binaries_mapping: HashMap, + is_dev_mode: bool, + ) -> Result { + let persistent_dir = to_abs_path(persistent_dir); + let ephemeral_dir = to_abs_path(ephemeral_dir); + + let allowed_effectors = allowed_effectors + .into_iter() + .map(|(cid, effector)| { + let effector = effector + .into_iter() + .map(|(name, path_str)| { + let path = Path::new(&path_str); + match path.try_exists() { + Err(err) => tracing::warn!( + "cannot check binary `{path_str}` for effector `{cid}`: {err}" + ), + Ok(false) => tracing::warn!( + "binary `{path_str}` for effector `{cid}` does not exist" + ), + _ => {} + }; + (name, path.to_path_buf()) + }) + .collect::<_>(); + (cid, effector) + }) + .collect::<_>(); + + let mounted_binaries_mapping = if !is_dev_mode { + HashMap::new() + } else { + mounted_binaries_mapping + .into_iter() + .map(|(name, path_str)| { + let path = Path::new(&path_str); + match path.try_exists() { + Err(err) => tracing::warn!("cannot check binary `{path_str}`: {err}"), + Ok(false) => tracing::warn!("binary `{path_str}` does not exist"), + _ => {} + }; + (name, path.to_path_buf()) + }) + .collect::<_>() + }; + + let this = Self { + local_peer_id, + blueprint_dir: config_utils::blueprint_dir(&persistent_dir), + persistent_work_dir: config_utils::workdir(&persistent_dir), + ephemeral_work_dir: config_utils::workdir(&ephemeral_dir), + modules_dir: config_utils::modules_dir(&persistent_dir), + services_dir: config_utils::services_dir(&persistent_dir), + particles_vault_dir, + envs, + management_peer_id, + builtins_management_peer_id, + default_service_memory_limit, + allowed_effectors, + mounted_binaries_mapping, + is_dev_mode, + }; + + create_dirs(&[ + &this.blueprint_dir, + &this.persistent_work_dir, + &this.ephemeral_work_dir, + &this.modules_dir, + &this.services_dir, + &this.particles_vault_dir, + ])?; + + set_write_only(&this.particles_vault_dir)?; + + Ok(this) + } +} diff --git a/particle-services/src/lib.rs b/particle-services/src/lib.rs index 1d4e3af080..4363096003 100644 --- a/particle-services/src/lib.rs +++ b/particle-services/src/lib.rs @@ -39,5 +39,8 @@ mod error; mod health; mod persistence; +mod config; + pub use app_services::ServiceInfo; +pub use config::ParticleAppServicesConfig; pub use types::peer_scope::PeerScope; From e9d269949ba49b02d1251f15408f97a7b110d0ab Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Thu, 11 Apr 2024 19:35:03 +0300 Subject: [PATCH 25/33] fix test --- aquamarine/src/plumber.rs | 2 +- crates/server-config/src/wasm_backend_config.rs | 3 ++- crates/spell-service-api/src/lib.rs | 4 +++- nox/src/node.rs | 2 +- nox/tests/http_expected_config.toml | 14 ++++++++++++++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/aquamarine/src/plumber.rs b/aquamarine/src/plumber.rs index 469866d1a8..0fcd71c2ce 100644 --- a/aquamarine/src/plumber.rs +++ b/aquamarine/src/plumber.rs @@ -816,7 +816,7 @@ mod tests { workers.clone(), key_storage.clone(), scope.clone(), - avm_wasm_backend + avm_wasm_backend, ) } diff --git a/crates/server-config/src/wasm_backend_config.rs b/crates/server-config/src/wasm_backend_config.rs index bf54f7f18f..552a10317c 100644 --- a/crates/server-config/src/wasm_backend_config.rs +++ b/crates/server-config/src/wasm_backend_config.rs @@ -11,7 +11,8 @@ pub struct WasmBackendConfig { pub async_wasm_stack: usize, /// Configures the maximum amount of stack space available for executing WebAssembly code. pub max_wasm_stack: usize, - /// Enables the epoch interruption mechanism. + /// Enables the epoch interruption mechanism + #[serde(with = "humantime_serde")] pub epoch_interruption_duration: Option, } diff --git a/crates/spell-service-api/src/lib.rs b/crates/spell-service-api/src/lib.rs index bd4b3775e7..dd1d0b908f 100644 --- a/crates/spell-service-api/src/lib.rs +++ b/crates/spell-service-api/src/lib.rs @@ -283,7 +283,9 @@ mod tests { use std::path::{Path, PathBuf}; use std::sync::Arc; - use particle_services::{ParticleAppServices, ParticleAppServicesConfig, PeerScope, ServiceType}; + use particle_services::{ + ParticleAppServices, ParticleAppServicesConfig, PeerScope, ServiceType, + }; use fluence_libp2p::PeerId; use libp2p_identity::Keypair; diff --git a/nox/src/node.rs b/nox/src/node.rs index 99b1ef93a5..263a74d54b 100644 --- a/nox/src/node.rs +++ b/nox/src/node.rs @@ -789,7 +789,7 @@ mod tests { false, ); let avm_wasm_backend_config = WasmBackendConfig::default(); - + let data_store_config = DataStoreConfig::new(config.dir_config.avm_base_dir.clone()); let system_service_distros = diff --git a/nox/tests/http_expected_config.toml b/nox/tests/http_expected_config.toml index 33105240fc..8cbdaa7205 100644 --- a/nox/tests/http_expected_config.toml +++ b/nox/tests/http_expected_config.toml @@ -63,6 +63,13 @@ outbound_substream_timeout = "10s" [node_config.avm_config] hard_limit_enabled = false +[node_config.avm_config.wasm_backend] +debug_info = true +wasm_backtrace = true +async_wasm_stack = 2097152 +max_wasm_stack = 2097152 +epoch_interruption_duration = "1s" + [node_config.kademlia] max_packet_size = 1677721600 query_timeout = "3s" @@ -116,3 +123,10 @@ curl_binary_path = "/usr/bin/curl" [node_config.http_config] http_port = 18080 + +[node_config.services.wasm_backend] +debug_info = true +wasm_backtrace = true +async_wasm_stack = 2097152 +max_wasm_stack = 2097152 +epoch_interruption_duration = "1s" From 3c027b1e928f680edc5aa800fc072d9cc274108f Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Thu, 11 Apr 2024 19:42:43 +0300 Subject: [PATCH 26/33] change stack type --- crates/server-config/src/wasm_backend_config.rs | 8 ++++---- nox/src/main.rs | 14 ++++++++++++-- nox/tests/http_expected_config.toml | 8 ++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/crates/server-config/src/wasm_backend_config.rs b/crates/server-config/src/wasm_backend_config.rs index 552a10317c..34a0d312e0 100644 --- a/crates/server-config/src/wasm_backend_config.rs +++ b/crates/server-config/src/wasm_backend_config.rs @@ -8,9 +8,9 @@ pub struct WasmBackendConfig { /// Configures whether the errors from the VM should collect the wasm backtrace and parse debug info. pub wasm_backtrace: bool, /// Configures the size of the stacks used for asynchronous execution. - pub async_wasm_stack: usize, + pub async_wasm_stack: bytesize::ByteSize, /// Configures the maximum amount of stack space available for executing WebAssembly code. - pub max_wasm_stack: usize, + pub max_wasm_stack: bytesize::ByteSize, /// Enables the epoch interruption mechanism #[serde(with = "humantime_serde")] pub epoch_interruption_duration: Option, @@ -21,8 +21,8 @@ impl Default for WasmBackendConfig { Self { debug_info: true, wasm_backtrace: true, - async_wasm_stack: 2 * 1024 * 1024, - max_wasm_stack: 2 * 1024 * 1024, + async_wasm_stack: bytesize::ByteSize::mb(2), + max_wasm_stack: bytesize::ByteSize::mb(2), epoch_interruption_duration: Some(Duration::from_secs(1)), } } diff --git a/nox/src/main.rs b/nox/src/main.rs index 898cc8d0c2..1bb3abe489 100644 --- a/nox/src/main.rs +++ b/nox/src/main.rs @@ -279,8 +279,18 @@ fn avm_wasm_backend_config(config: &ResolvedConfig) -> WasmBackendConfig { WasmBackendConfig { debug_info: config.node_config.services.wasm_backend.debug_info, wasm_backtrace: config.node_config.services.wasm_backend.wasm_backtrace, - async_wasm_stack: config.node_config.services.wasm_backend.async_wasm_stack, - max_wasm_stack: config.node_config.services.wasm_backend.max_wasm_stack, + async_wasm_stack: config + .node_config + .services + .wasm_backend + .async_wasm_stack + .as_u64() as usize, + max_wasm_stack: config + .node_config + .services + .wasm_backend + .max_wasm_stack + .as_u64() as usize, epoch_interruption_duration: config .node_config .services diff --git a/nox/tests/http_expected_config.toml b/nox/tests/http_expected_config.toml index 8cbdaa7205..1af8aaafb0 100644 --- a/nox/tests/http_expected_config.toml +++ b/nox/tests/http_expected_config.toml @@ -66,8 +66,8 @@ hard_limit_enabled = false [node_config.avm_config.wasm_backend] debug_info = true wasm_backtrace = true -async_wasm_stack = 2097152 -max_wasm_stack = 2097152 +async_wasm_stack = "2.0 MB" +max_wasm_stack = "2.0 MB" epoch_interruption_duration = "1s" [node_config.kademlia] @@ -127,6 +127,6 @@ http_port = 18080 [node_config.services.wasm_backend] debug_info = true wasm_backtrace = true -async_wasm_stack = 2097152 -max_wasm_stack = 2097152 +async_wasm_stack = "2.0 MB" +max_wasm_stack = "2.0 MB" epoch_interruption_duration = "1s" From 98b761bca7ae193bf8b916558eac4d6f6e638157 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Fri, 12 Apr 2024 15:31:08 +0300 Subject: [PATCH 27/33] cleanup --- aquamarine/src/aquamarine.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/aquamarine/src/aquamarine.rs b/aquamarine/src/aquamarine.rs index 3fe9f14530..eb172ff7ed 100644 --- a/aquamarine/src/aquamarine.rs +++ b/aquamarine/src/aquamarine.rs @@ -78,13 +78,6 @@ impl AquamarineBackend { data_store_config.particles_anomaly_dir, ); let data_store: Arc = Arc::new(data_store); - let mut wasmtime_config = WasmtimeConfig::default(); - wasmtime_config - .debug_info(true) - .wasm_backtrace(true) - .epoch_interruption(true) - .async_wasm_stack(2 * 1024 * 1024) - .max_wasm_stack(2 * 1024 * 1024); let avm_wasm_backend = WasmtimeWasmBackend::new(avm_wasm_backend_config.to_wasmtime_config())?; From dd0e1442005f697ddf167448a425c28663198ceb Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Fri, 12 Apr 2024 15:45:56 +0300 Subject: [PATCH 28/33] cleanup --- aquamarine/src/aquamarine.rs | 4 ++-- aquamarine/src/config.rs | 12 ++++++------ crates/local-vm/src/local_vm.rs | 15 ++++----------- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/aquamarine/src/aquamarine.rs b/aquamarine/src/aquamarine.rs index eb172ff7ed..d14ca3c78f 100644 --- a/aquamarine/src/aquamarine.rs +++ b/aquamarine/src/aquamarine.rs @@ -20,7 +20,7 @@ use std::task::Poll; use std::time::Duration; use futures::StreamExt; -use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; +use marine_wasmtime_backend::{WasmtimeWasmBackend}; use tokio::sync::mpsc; use tokio::task::JoinHandle; use tracing::{instrument, Instrument}; @@ -79,7 +79,7 @@ impl AquamarineBackend { ); let data_store: Arc = Arc::new(data_store); let avm_wasm_backend = - WasmtimeWasmBackend::new(avm_wasm_backend_config.to_wasmtime_config())?; + WasmtimeWasmBackend::new(avm_wasm_backend_config.into())?; let vm_pool = VmPool::new( config.pool_size, diff --git a/aquamarine/src/config.rs b/aquamarine/src/config.rs index aba6a48e19..4019c6e1d4 100644 --- a/aquamarine/src/config.rs +++ b/aquamarine/src/config.rs @@ -51,15 +51,15 @@ pub struct WasmBackendConfig { pub epoch_interruption_duration: Option, } -impl WasmBackendConfig { - pub fn to_wasmtime_config(&self) -> WasmtimeConfig { +impl From for WasmtimeConfig { + fn from(value: WasmBackendConfig) -> Self { let mut config = WasmtimeConfig::default(); config - .debug_info(self.debug_info) - .wasm_backtrace(self.wasm_backtrace) + .debug_info(value.debug_info) + .wasm_backtrace(value.wasm_backtrace) .epoch_interruption(true) - .async_wasm_stack(self.async_wasm_stack) - .max_wasm_stack(self.max_wasm_stack); + .async_wasm_stack(value.async_wasm_stack) + .max_wasm_stack(value.max_wasm_stack); config } } diff --git a/crates/local-vm/src/local_vm.rs b/crates/local-vm/src/local_vm.rs index 3294b60420..0d360e7411 100644 --- a/crates/local-vm/src/local_vm.rs +++ b/crates/local-vm/src/local_vm.rs @@ -24,11 +24,11 @@ use avm_server::avm_runner::{AVMRunner, RawAVMOutcome}; use avm_server::{CallResults, CallServiceResult}; use fstrings::f; use libp2p::PeerId; -use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; +use marine_wasmtime_backend::{WasmtimeWasmBackend}; use serde_json::{json, Value as JValue}; use air_interpreter_fs::{air_interpreter_path, write_default_air_interpreter}; -use aquamarine::ParticleDataStore; +use aquamarine::{ParticleDataStore, WasmBackendConfig}; use fluence_keypair::KeyPair; use now_millis::now_ms; use particle_args::{Args, JError}; @@ -172,15 +172,8 @@ pub fn host_call(data: &HashMap, args: Args) -> (CallServiceResu } pub fn make_wasm_backend() -> WasmtimeWasmBackend { - let mut wasmtime_config = WasmtimeConfig::default(); - // TODO async-marine: impl proper configuration - wasmtime_config - .debug_info(true) - .wasm_backtrace(true) - .epoch_interruption(true) - .async_wasm_stack(2 * 1024 * 1024) - .max_wasm_stack(2 * 1024 * 1024); - WasmtimeWasmBackend::new(wasmtime_config).expect("Cannot create WasmtimeWasmBackend") + let wasmtime_config = WasmBackendConfig::default(); + WasmtimeWasmBackend::new(wasmtime_config.into()).expect("Cannot create WasmtimeWasmBackend") } pub async fn make_vm(tmp_dir_path: &Path) -> AVMRunner { From 9563c36917c776804c38205eeaf04b278451e1c8 Mon Sep 17 00:00:00 2001 From: Valery Antopol Date: Mon, 15 Apr 2024 15:54:41 +0400 Subject: [PATCH 29/33] update to releaseed marine --- Cargo.lock | 77 +++++++++++++++++++++++++++++++----------------------- Cargo.toml | 8 +++--- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83fe43b565..fbe3491a58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,7 +95,7 @@ dependencies = [ [[package]] name = "air-interpreter-interface" version = "0.19.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" dependencies = [ "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", "air-interpreter-value", @@ -124,7 +124,7 @@ dependencies = [ [[package]] name = "air-interpreter-sede" version = "0.1.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" dependencies = [ "marine-rs-sdk", "rmp-serde", @@ -138,7 +138,7 @@ dependencies = [ [[package]] name = "air-interpreter-value" version = "0.1.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" dependencies = [ "serde", "serde_json", @@ -156,7 +156,7 @@ dependencies = [ [[package]] name = "air-utils" version = "0.3.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" [[package]] name = "allocator-api2" @@ -741,7 +741,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "avm-data-store" version = "0.7.9" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" dependencies = [ "avm-interface", "serde", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "avm-interface" version = "0.32.1" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" dependencies = [ "air-interpreter-interface", "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "avm-server" version = "0.37.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" dependencies = [ "air-interpreter-interface", "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", @@ -2543,8 +2543,9 @@ dependencies = [ [[package]] name = "fluence-app-service" -version = "0.35.2" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e423d621b41b09b24581ff639abe8590da6af5b374b90aa5f6232a67c59a203" dependencies = [ "log", "maplit", @@ -3679,8 +3680,9 @@ dependencies = [ [[package]] name = "it-json-serde" -version = "0.5.1" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9011f4a5b18c9148bbdfac7d364266e34b4cda2fc585230f1dab706c315cf556" dependencies = [ "serde", "serde_derive", @@ -4942,8 +4944,9 @@ dependencies = [ [[package]] name = "marine-core" -version = "0.30.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67d0d9d1ea05ecf84c887afc720d9fb139e5453cb7ffd8102f36b54bd02c2222" dependencies = [ "anyhow", "bytesize", @@ -4971,8 +4974,9 @@ dependencies = [ [[package]] name = "marine-it-generator" -version = "0.17.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8c8aac013e8dc4d828e4a1160e9b8b7224e6847c17fa0b25836aaf6226628" dependencies = [ "it-lilo", "marine-it-parser", @@ -4987,8 +4991,9 @@ dependencies = [ [[package]] name = "marine-it-interfaces" -version = "0.9.1" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34970fe6e4da4fcee6d911e96afb1b99ead0c80e41ba2531a36a1075fbbfb03f" dependencies = [ "multimap 0.8.3", "wasmer-interface-types-fl", @@ -4996,8 +5001,9 @@ dependencies = [ [[package]] name = "marine-it-parser" -version = "0.16.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa3a1f23268aedbe23baed2a3a00ea21bf7b61aa61feb393b70dd0597414cb5e" dependencies = [ "anyhow", "itertools 0.10.5", @@ -5107,7 +5113,8 @@ dependencies = [ [[package]] name = "marine-min-it-version" version = "0.3.2" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147e6e4c9d3dc9afbb06b2e3bc069b63c749733f698d0c364c320a72b133f1d5" dependencies = [ "once_cell", "semver 1.0.20", @@ -5115,8 +5122,9 @@ dependencies = [ [[package]] name = "marine-module-info-parser" -version = "0.15.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0abfe0aae8f0b89e79278e6f09ed094396aed413a5cddfff67e9a95adf6891" dependencies = [ "anyhow", "chrono", @@ -5131,8 +5139,9 @@ dependencies = [ [[package]] name = "marine-module-interface" -version = "0.8.1" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e139be29c46e01a1087175834a95881e6e60b1f3304bc10e098450e5bd2b64" dependencies = [ "anyhow", "itertools 0.10.5", @@ -5200,8 +5209,9 @@ dependencies = [ [[package]] name = "marine-runtime" -version = "0.36.2" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b89585db43f79da40041d5100f84c360ada9e5ac086d95fbbbab118771f2ec" dependencies = [ "bytesize", "it-json-serde", @@ -5252,12 +5262,14 @@ dependencies = [ [[package]] name = "marine-utils" version = "0.5.1" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce56bfabfd0af5326ff81c32c8d2261aa03b10e00ea6c165de4ebf8a3f998e4" [[package]] name = "marine-wasm-backend-traits" -version = "0.6.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e15277ea4420bfd8c3a26aceded5d64c35c416afaedfccc3b21832eb578f6c1d" dependencies = [ "anyhow", "futures", @@ -5271,8 +5283,9 @@ dependencies = [ [[package]] name = "marine-wasmtime-backend" -version = "0.6.0" -source = "git+https://github.com/fluencelabs/marine?branch=feat/async-call#5aec5419ac6a78114d658f1eaeac4e1d84ef8b86" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f8537d3b8d370431746ef24f7fab31cc0e41e39cb14a024e4895325c7e8b27f" dependencies = [ "anyhow", "futures", @@ -6477,7 +6490,7 @@ dependencies = [ [[package]] name = "polyplets" version = "0.7.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#d4a222f4975090dbf37162cb431b158a49c14e0f" +source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" dependencies = [ "marine-call-parameters 0.14.0", "serde", diff --git a/Cargo.toml b/Cargo.toml index f0405f3ca8..241123cfa9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,11 +110,11 @@ fluence-spell-dtos = "=0.7.5" fluence-spell-distro = "=0.7.5" # marine -fluence-app-service = { version = "=0.35.2", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call", features = ["wasmtime"] } +fluence-app-service = { version = "=0.36.0", features = ["wasmtime"] } marine-utils = "0.5.1" -marine-it-parser = { version = "0.16.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } -marine-module-info-parser = { version = "0.15.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } -marine-wasmtime-backend = { version = "0.6.0", git = "https://github.com/fluencelabs/marine", branch = "feat/async-call" } +marine-it-parser = "0.17.0" +marine-module-info-parser = "0.16.0" +marine-wasmtime-backend = "0.7.0" # avm avm-server = { git = "https://github.com/fluencelabs/aquavm", version = "=0.37.0", branch = "feat/use-async-marine" } From da4dbfb0d017d9833b598a5cb1612379df04e0f6 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Mon, 22 Apr 2024 19:34:36 +0300 Subject: [PATCH 30/33] update avm --- Cargo.lock | 83 ++++++++++++++++++++++++++++++++---------------------- Cargo.toml | 4 +-- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbe3491a58..98e105f86d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,13 +95,14 @@ dependencies = [ [[package]] name = "air-interpreter-interface" version = "0.19.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ca7926759c89514cbc1fdffe7477585e71eef42eedcedd695511e518b74cb9" dependencies = [ - "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", + "air-interpreter-sede", "air-interpreter-value", "fluence-it-types", "marine-call-parameters 0.14.0", - "marine-rs-sdk", + "marine-rs-sdk 0.14.0", "serde", "serde_bytes", "serde_json", @@ -113,20 +114,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "433b1ca3538f5f6a6083646b2aa61cd57a08c1558091f6be47b2299fc7b28261" dependencies = [ - "rmp-serde", - "serde", - "serde_bytes", - "serde_json", - "thiserror", - "unsigned-varint 0.8.0", -] - -[[package]] -name = "air-interpreter-sede" -version = "0.1.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" -dependencies = [ - "marine-rs-sdk", + "marine-rs-sdk 0.10.3", "rmp-serde", "serde", "serde_bytes", @@ -138,7 +126,8 @@ dependencies = [ [[package]] name = "air-interpreter-value" version = "0.1.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3158e53f5ca496d825120e111e110a546ed05e3116d37125655a9e20b230529" dependencies = [ "serde", "serde_json", @@ -146,9 +135,9 @@ dependencies = [ [[package]] name = "air-interpreter-wasm" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32424e4abaebf4e085109d917907c5c2898efe55eb88a9f1be866e1bbfc710b0" +checksum = "291be3567af94a8de9e25b3a2e6ac0ba58bb07c5967bead27c20a918846f3c6c" dependencies = [ "built 0.7.1", ] @@ -156,7 +145,8 @@ dependencies = [ [[package]] name = "air-utils" version = "0.3.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3705bf46663ca316391c8c666d96edf4c13f5d1054f4e7487a752e2051b85165" [[package]] name = "allocator-api2" @@ -741,7 +731,8 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "avm-data-store" version = "0.7.9" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2bbb779d135467217968e752b092d2a00d649f452b1015aac332284d9b5aa9" dependencies = [ "avm-interface", "serde", @@ -751,10 +742,11 @@ dependencies = [ [[package]] name = "avm-interface" version = "0.32.1" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1767525a79ab972c3a40c6dc807f6eebcc323932e9846648b3b58f9940a54057" dependencies = [ "air-interpreter-interface", - "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", + "air-interpreter-sede", "air-utils", "log", "maplit", @@ -767,11 +759,12 @@ dependencies = [ [[package]] name = "avm-server" -version = "0.37.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63902333bfcced4ab6d61fc1bbea14c6cec7b7852b7e9967cb66e252f49c581" dependencies = [ "air-interpreter-interface", - "air-interpreter-sede 0.1.0 (git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine)", + "air-interpreter-sede", "air-utils", "avm-data-store", "avm-interface", @@ -2630,7 +2623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3794dff0e7e2851fee56651bf45f8d57c8be3c77c285a5f16fd86d4d6ed1037" dependencies = [ "eyre", - "marine-rs-sdk", + "marine-rs-sdk 0.14.0", "marine-sqlite-connector", "serde", "thiserror", @@ -5154,6 +5147,19 @@ dependencies = [ "wasmer-interface-types-fl", ] +[[package]] +name = "marine-rs-sdk" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034cab8adf708e87db08f093e0c7b8ea49359cc875ed2a778c1bf245b5d9d9f8" +dependencies = [ + "marine-call-parameters 0.10.3", + "marine-macro 0.10.3", + "marine-rs-sdk-main 0.10.3", + "marine-timestamp-macro 0.10.3", + "serde", +] + [[package]] name = "marine-rs-sdk" version = "0.14.0" @@ -5163,7 +5169,7 @@ dependencies = [ "marine-call-parameters 0.14.0", "marine-macro 0.14.0", "marine-rs-sdk-main 0.14.0", - "marine-timestamp-macro", + "marine-timestamp-macro 0.14.0", "serde", ] @@ -5223,7 +5229,7 @@ dependencies = [ "marine-call-parameters 0.13.0", "marine-core", "marine-module-interface", - "marine-rs-sdk", + "marine-rs-sdk 0.14.0", "marine-rs-sdk-main 0.14.0", "marine-utils", "marine-wasm-backend-traits", @@ -5246,7 +5252,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c4d82c7e8c07f59aa526271b810c97ec7f79d14a77725025618a79b0b1d9051" dependencies = [ "bytesize", - "marine-rs-sdk", + "marine-rs-sdk 0.14.0", +] + +[[package]] +name = "marine-timestamp-macro" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f812a03cb13b79ab75e38053a77ecc4b4738a1b485b650d971dec3dbbcb2561" +dependencies = [ + "chrono", + "quote", ] [[package]] @@ -6235,7 +6251,7 @@ dependencies = [ name = "particle-protocol" version = "0.3.0" dependencies = [ - "air-interpreter-sede 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "air-interpreter-sede", "asynchronous-codec 0.7.0", "base64 0.21.7", "derivative", @@ -6490,7 +6506,8 @@ dependencies = [ [[package]] name = "polyplets" version = "0.7.0" -source = "git+https://github.com/fluencelabs/aquavm?branch=feat/use-async-marine#044691d97b26340da340f444b7d492c11093478d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77452f7f8d029801e32bc975404918f45c338183416a2aa2cb3d59c5c922446" dependencies = [ "marine-call-parameters 0.14.0", "serde", diff --git a/Cargo.toml b/Cargo.toml index 241123cfa9..12767540a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,8 +117,8 @@ marine-module-info-parser = "0.16.0" marine-wasmtime-backend = "0.7.0" # avm -avm-server = { git = "https://github.com/fluencelabs/aquavm", version = "=0.37.0", branch = "feat/use-async-marine" } -air-interpreter-wasm = "=0.62.0" +avm-server = "=0.38.0" +air-interpreter-wasm = "=0.63.0" # libp2p libp2p = { version = "0.53.2", features = ["noise", "tcp", "dns", "websocket", "yamux", "tokio", "kad", "ping", "identify", "macros"] } From c8f75ffb5eaad3da3baa247815e32460b1288b5c Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Mon, 22 Apr 2024 19:46:41 +0300 Subject: [PATCH 31/33] fix test --- aquamarine/src/aquamarine.rs | 5 ++--- crates/local-vm/src/local_vm.rs | 2 +- crates/server-config/src/wasm_backend_config.rs | 2 +- nox/tests/http_expected_config.toml | 6 +++--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/aquamarine/src/aquamarine.rs b/aquamarine/src/aquamarine.rs index d14ca3c78f..601a205c30 100644 --- a/aquamarine/src/aquamarine.rs +++ b/aquamarine/src/aquamarine.rs @@ -20,7 +20,7 @@ use std::task::Poll; use std::time::Duration; use futures::StreamExt; -use marine_wasmtime_backend::{WasmtimeWasmBackend}; +use marine_wasmtime_backend::WasmtimeWasmBackend; use tokio::sync::mpsc; use tokio::task::JoinHandle; use tracing::{instrument, Instrument}; @@ -78,8 +78,7 @@ impl AquamarineBackend { data_store_config.particles_anomaly_dir, ); let data_store: Arc = Arc::new(data_store); - let avm_wasm_backend = - WasmtimeWasmBackend::new(avm_wasm_backend_config.into())?; + let avm_wasm_backend = WasmtimeWasmBackend::new(avm_wasm_backend_config.into())?; let vm_pool = VmPool::new( config.pool_size, diff --git a/crates/local-vm/src/local_vm.rs b/crates/local-vm/src/local_vm.rs index 0d360e7411..84d12ee8e5 100644 --- a/crates/local-vm/src/local_vm.rs +++ b/crates/local-vm/src/local_vm.rs @@ -24,7 +24,7 @@ use avm_server::avm_runner::{AVMRunner, RawAVMOutcome}; use avm_server::{CallResults, CallServiceResult}; use fstrings::f; use libp2p::PeerId; -use marine_wasmtime_backend::{WasmtimeWasmBackend}; +use marine_wasmtime_backend::WasmtimeWasmBackend; use serde_json::{json, Value as JValue}; use air_interpreter_fs::{air_interpreter_path, write_default_air_interpreter}; diff --git a/crates/server-config/src/wasm_backend_config.rs b/crates/server-config/src/wasm_backend_config.rs index 34a0d312e0..d19521633e 100644 --- a/crates/server-config/src/wasm_backend_config.rs +++ b/crates/server-config/src/wasm_backend_config.rs @@ -21,7 +21,7 @@ impl Default for WasmBackendConfig { Self { debug_info: true, wasm_backtrace: true, - async_wasm_stack: bytesize::ByteSize::mb(2), + async_wasm_stack: bytesize::ByteSize::mb(4), max_wasm_stack: bytesize::ByteSize::mb(2), epoch_interruption_duration: Some(Duration::from_secs(1)), } diff --git a/nox/tests/http_expected_config.toml b/nox/tests/http_expected_config.toml index 1af8aaafb0..5112f4e856 100644 --- a/nox/tests/http_expected_config.toml +++ b/nox/tests/http_expected_config.toml @@ -5,7 +5,7 @@ persistent_base_dir = "{base_dir}/persistent" avm_base_dir = "{base_dir}/ephemeral/avm" services_ephemeral_dir = "{base_dir}/ephemeral/services" services_persistent_dir = "{base_dir}/persistent/services" -air_interpreter_path = "{base_dir}/persistent/aquamarine_0.62.0.wasm" +air_interpreter_path = "{base_dir}/persistent/aquamarine_0.63.0.wasm" spell_base_dir = "{base_dir}/persistent/spell" keypairs_base_dir = "{base_dir}/persistent/keypairs" workers_base_dir = "{base_dir}/persistent/workers" @@ -66,7 +66,7 @@ hard_limit_enabled = false [node_config.avm_config.wasm_backend] debug_info = true wasm_backtrace = true -async_wasm_stack = "2.0 MB" +async_wasm_stack = "4.0 MB" max_wasm_stack = "2.0 MB" epoch_interruption_duration = "1s" @@ -127,6 +127,6 @@ http_port = 18080 [node_config.services.wasm_backend] debug_info = true wasm_backtrace = true -async_wasm_stack = "2.0 MB" +async_wasm_stack = "4.0 MB" max_wasm_stack = "2.0 MB" epoch_interruption_duration = "1s" From f74187f050da221482101ff97d5df1be6ba362e8 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 23 Apr 2024 13:05:24 +0300 Subject: [PATCH 32/33] fix configs --- aquamarine/src/aquamarine.rs | 3 +- aquamarine/src/config.rs | 40 ------------------- aquamarine/src/lib.rs | 2 +- crates/created-swarm/src/swarm.rs | 10 +---- crates/spell-service-api/src/lib.rs | 4 +- nox/src/main.rs | 28 +------------ nox/src/node.rs | 57 +++++++++++++++++++++++++-- particle-services/src/app_services.rs | 4 +- particle-services/src/config.rs | 45 +++++++++++++++++++++ particle-services/src/lib.rs | 1 + 10 files changed, 109 insertions(+), 85 deletions(-) diff --git a/aquamarine/src/aquamarine.rs b/aquamarine/src/aquamarine.rs index 601a205c30..0e3dd75274 100644 --- a/aquamarine/src/aquamarine.rs +++ b/aquamarine/src/aquamarine.rs @@ -28,13 +28,12 @@ use tracing::{instrument, Instrument}; use health::HealthCheckRegistry; use particle_execution::{ParticleFunctionStatic, ServiceFunction}; use particle_protocol::ExtendedParticle; -use particle_services::PeerScope; +use particle_services::{PeerScope, WasmBackendConfig}; use peer_metrics::{ParticleExecutorMetrics, VmPoolMetrics}; use workers::{Event, KeyStorage, PeerScopes, Receiver, Workers}; use crate::command::Command; use crate::command::Command::{AddService, Ingest, RemoveService}; -use crate::config::WasmBackendConfig; use crate::error::AquamarineApiError; use crate::vm_pool::VmPool; use crate::{ diff --git a/aquamarine/src/config.rs b/aquamarine/src/config.rs index 4019c6e1d4..a35e8ee997 100644 --- a/aquamarine/src/config.rs +++ b/aquamarine/src/config.rs @@ -16,7 +16,6 @@ use fs_utils::to_abs_path; use libp2p::PeerId; -use marine_wasmtime_backend::WasmtimeConfig; use std::path::PathBuf; use std::time::Duration; @@ -37,45 +36,6 @@ pub struct VmConfig { pub hard_limit_enabled: bool, } -#[derive(Debug, Clone)] -pub struct WasmBackendConfig { - /// Configures whether DWARF debug information will be emitted during compilation. - pub debug_info: bool, - /// Configures whether the errors from the VM should collect the wasm backtrace and parse debug info. - pub wasm_backtrace: bool, - /// Configures the size of the stacks used for asynchronous execution. - pub async_wasm_stack: usize, - /// Configures the maximum amount of stack space available for executing WebAssembly code. - pub max_wasm_stack: usize, - /// Enables the epoch interruption mechanism. - pub epoch_interruption_duration: Option, -} - -impl From for WasmtimeConfig { - fn from(value: WasmBackendConfig) -> Self { - let mut config = WasmtimeConfig::default(); - config - .debug_info(value.debug_info) - .wasm_backtrace(value.wasm_backtrace) - .epoch_interruption(true) - .async_wasm_stack(value.async_wasm_stack) - .max_wasm_stack(value.max_wasm_stack); - config - } -} - -impl Default for WasmBackendConfig { - fn default() -> Self { - Self { - debug_info: true, - wasm_backtrace: true, - async_wasm_stack: 2 * 1024 * 1024, - max_wasm_stack: 2 * 1024 * 1024, - epoch_interruption_duration: Some(Duration::from_secs(1)), - } - } -} - #[derive(Debug, Clone)] pub struct VmPoolConfig { /// Number of VMs to create diff --git a/aquamarine/src/lib.rs b/aquamarine/src/lib.rs index dd101eeaa5..e085858e30 100644 --- a/aquamarine/src/lib.rs +++ b/aquamarine/src/lib.rs @@ -51,8 +51,8 @@ pub use crate::aquamarine::{AquamarineApi, AquamarineBackend}; pub use crate::config::{DataStoreConfig, VmConfig, VmPoolConfig}; pub use crate::particle_effects::{InterpretationStats, ParticleEffects, RemoteRoutingEffects}; pub type AVMRunner = avm_server::avm_runner::AVMRunner; -pub use config::WasmBackendConfig; pub use error::AquamarineApiError; pub use marine_wasmtime_backend::WasmtimeWasmBackend; pub use particle_data_store::{DataStoreError, ParticleDataStore}; +pub use particle_services::WasmBackendConfig; pub use plumber::Plumber; diff --git a/crates/created-swarm/src/swarm.rs b/crates/created-swarm/src/swarm.rs index c0549b3aa0..91daa0845f 100644 --- a/crates/created-swarm/src/swarm.rs +++ b/crates/created-swarm/src/swarm.rs @@ -30,7 +30,7 @@ use libp2p::{core::Multiaddr, PeerId}; use serde::Deserialize; use air_interpreter_fs::{air_interpreter_path, write_default_air_interpreter}; -use aquamarine::{AVMRunner, AquamarineApi, VmConfig, WasmBackendConfig}; +use aquamarine::{AVMRunner, AquamarineApi, VmConfig}; use aquamarine::{AquaRuntime, DataStoreConfig}; use base64::{engine::general_purpose::STANDARD as base64, Engine}; use cid_utils::Hash; @@ -442,13 +442,6 @@ pub async fn create_swarm_with_runtime( listen_on: config.listen_on.clone(), manager: management_peer_id, }); - let avm_wasm_backend_config = WasmBackendConfig{ - debug_info: true, - wasm_backtrace: true, - async_wasm_stack: 2*1024*1024, - max_wasm_stack: 2*1024*1024, - epoch_interruption_duration: Some(Duration::from_secs(1)), - }; let data_store_config = DataStoreConfig::new(tmp_dir.clone()); @@ -462,7 +455,6 @@ pub async fn create_swarm_with_runtime( resolved.clone(), core_manager, vm_config, - avm_wasm_backend_config, data_store_config, "some version", "some version", diff --git a/crates/spell-service-api/src/lib.rs b/crates/spell-service-api/src/lib.rs index dd1d0b908f..dea48ed5d3 100644 --- a/crates/spell-service-api/src/lib.rs +++ b/crates/spell-service-api/src/lib.rs @@ -284,7 +284,7 @@ mod tests { use std::sync::Arc; use particle_services::{ - ParticleAppServices, ParticleAppServicesConfig, PeerScope, ServiceType, + ParticleAppServices, ParticleAppServicesConfig, PeerScope, ServiceType, WasmBackendConfig, }; use fluence_libp2p::PeerId; @@ -347,6 +347,7 @@ mod tests { let workers = Arc::new(workers); let service_memory_limit = server_config::default_service_memory_limit(); + let wasm_backend_config = WasmBackendConfig::default(); let config = ParticleAppServicesConfig::new( root_key_pair.get_peer_id(), persistent_dir, @@ -359,6 +360,7 @@ mod tests { Default::default(), Default::default(), true, + wasm_backend_config, ) .unwrap(); diff --git a/nox/src/main.rs b/nox/src/main.rs index 1bb3abe489..150d6adef0 100644 --- a/nox/src/main.rs +++ b/nox/src/main.rs @@ -38,7 +38,7 @@ use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use air_interpreter_fs::write_default_air_interpreter; -use aquamarine::{AVMRunner, DataStoreConfig, VmConfig, WasmBackendConfig}; +use aquamarine::{AVMRunner, DataStoreConfig, VmConfig}; use config_utils::to_peer_id; use core_manager::{CoreManager, CoreManagerFunctions, DevCoreManager, StrictCoreManager}; use fs_utils::to_abs_path; @@ -201,7 +201,6 @@ async fn start_fluence( let listen_addrs = config.listen_multiaddrs(); let vm_config = vm_config(&config); - let avm_wasm_backend_config = avm_wasm_backend_config(&config); let data_store_config = DataStoreConfig::new(config.dir_config.avm_base_dir.clone()); @@ -214,7 +213,6 @@ async fn start_fluence( config, core_manager, vm_config, - avm_wasm_backend_config, data_store_config, VERSION, air_interpreter_wasm::VERSION, @@ -274,27 +272,3 @@ fn vm_config(config: &ResolvedConfig) -> VmConfig { config.node_config.avm_config.hard_limit_enabled, ) } - -fn avm_wasm_backend_config(config: &ResolvedConfig) -> WasmBackendConfig { - WasmBackendConfig { - debug_info: config.node_config.services.wasm_backend.debug_info, - wasm_backtrace: config.node_config.services.wasm_backend.wasm_backtrace, - async_wasm_stack: config - .node_config - .services - .wasm_backend - .async_wasm_stack - .as_u64() as usize, - max_wasm_stack: config - .node_config - .services - .wasm_backend - .max_wasm_stack - .as_u64() as usize, - epoch_interruption_duration: config - .node_config - .services - .wasm_backend - .epoch_interruption_duration, - } -} diff --git a/nox/src/node.rs b/nox/src/node.rs index 263a74d54b..24235d9101 100644 --- a/nox/src/node.rs +++ b/nox/src/node.rs @@ -162,7 +162,6 @@ impl Node { config: ResolvedConfig, core_manager: Arc, vm_config: RT::Config, - avm_wasm_backend_config: WasmBackendConfig, data_store_config: DataStoreConfig, node_version: &'static str, air_version: &'static str, @@ -202,6 +201,8 @@ impl Node { let workers = Arc::new(workers); + let wasm_backend_config = services_wasm_backend_config(&config); + let services_config = ParticleAppServicesConfig::new( scopes.get_host_peer_id(), config.dir_config.services_persistent_dir.clone(), @@ -220,6 +221,7 @@ impl Node { .into_iter() .collect(), config.node_config.dev_mode_config.enable, + wasm_backend_config, ) .expect("create services config"); @@ -318,6 +320,7 @@ impl Node { let pool_config = VmPoolConfig::new(config.aquavm_pool_size, config.particle_execution_timeout); + let avm_wasm_backend_config = avm_wasm_backend_config(&config); let (aquamarine_backend, aquamarine_api) = AquamarineBackend::new( pool_config, vm_config, @@ -739,6 +742,54 @@ impl Node { } } +fn avm_wasm_backend_config(config: &ResolvedConfig) -> WasmBackendConfig { + WasmBackendConfig { + debug_info: config.node_config.avm_config.wasm_backend.debug_info, + wasm_backtrace: config.node_config.avm_config.wasm_backend.wasm_backtrace, + async_wasm_stack: config + .node_config + .avm_config + .wasm_backend + .async_wasm_stack + .as_u64() as usize, + max_wasm_stack: config + .node_config + .avm_config + .wasm_backend + .max_wasm_stack + .as_u64() as usize, + epoch_interruption_duration: config + .node_config + .avm_config + .wasm_backend + .epoch_interruption_duration, + } +} + +fn services_wasm_backend_config(config: &ResolvedConfig) -> WasmBackendConfig { + WasmBackendConfig { + debug_info: config.node_config.services.wasm_backend.debug_info, + wasm_backtrace: config.node_config.services.wasm_backend.wasm_backtrace, + async_wasm_stack: config + .node_config + .services + .wasm_backend + .async_wasm_stack + .as_u64() as usize, + max_wasm_stack: config + .node_config + .services + .wasm_backend + .max_wasm_stack + .as_u64() as usize, + epoch_interruption_duration: config + .node_config + .services + .wasm_backend + .epoch_interruption_duration, + } +} + #[cfg(test)] mod tests { use std::path::PathBuf; @@ -751,7 +802,7 @@ mod tests { use serde_json::json; use air_interpreter_fs::{air_interpreter_path, write_default_air_interpreter}; - use aquamarine::{AVMRunner, DataStoreConfig, VmConfig, WasmBackendConfig}; + use aquamarine::{AVMRunner, DataStoreConfig, VmConfig}; use config_utils::to_peer_id; use connected_client::ConnectedClient; use core_manager::DummyCoreManager; @@ -788,7 +839,6 @@ mod tests { None, false, ); - let avm_wasm_backend_config = WasmBackendConfig::default(); let data_store_config = DataStoreConfig::new(config.dir_config.avm_base_dir.clone()); @@ -802,7 +852,6 @@ mod tests { config, core_manager, vm_config, - avm_wasm_backend_config, data_store_config, "some version", "some version", diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index 080aee6b1a..47717bab0c 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -1258,7 +1258,7 @@ mod tests { use crate::app_services::{ServiceAlias, ServiceType}; use crate::persistence::load_persisted_services; - use crate::{ParticleAppServices, ParticleAppServicesConfig, ServiceError}; + use crate::{ParticleAppServices, ParticleAppServicesConfig, ServiceError, WasmBackendConfig}; fn create_pid() -> PeerId { let keypair = Keypair::generate_ed25519(); @@ -1300,6 +1300,7 @@ mod tests { .expect("Could not load worker registry"); let workers = Arc::new(workers); + let wasm_backend_config = WasmBackendConfig::default(); let config = ParticleAppServicesConfig::new( PeerId::from(root_keypair.public()), @@ -1313,6 +1314,7 @@ mod tests { Default::default(), Default::default(), true, + wasm_backend_config, ) .unwrap(); diff --git a/particle-services/src/config.rs b/particle-services/src/config.rs index 269a15dd93..20435aa3ee 100644 --- a/particle-services/src/config.rs +++ b/particle-services/src/config.rs @@ -18,9 +18,11 @@ use fs_utils::{create_dirs, set_write_only, to_abs_path}; use bytesize::ByteSize; use cid_utils::Hash; +use fluence_app_service::WasmtimeConfig; use libp2p_identity::PeerId; use std::collections::HashMap; use std::path::{Path, PathBuf}; +use std::time::Duration; #[derive(Debug, Clone)] pub struct ParticleAppServicesConfig { @@ -54,6 +56,8 @@ pub struct ParticleAppServicesConfig { pub mounted_binaries_mapping: HashMap, /// Is in the developer mode pub is_dev_mode: bool, + /// config for the wasmtime backend + pub wasm_backend_config: WasmBackendConfig, } impl ParticleAppServicesConfig { @@ -70,6 +74,7 @@ impl ParticleAppServicesConfig { allowed_effectors: HashMap>, mounted_binaries_mapping: HashMap, is_dev_mode: bool, + wasm_backend_config: WasmBackendConfig, ) -> Result { let persistent_dir = to_abs_path(persistent_dir); let ephemeral_dir = to_abs_path(ephemeral_dir); @@ -129,6 +134,7 @@ impl ParticleAppServicesConfig { allowed_effectors, mounted_binaries_mapping, is_dev_mode, + wasm_backend_config, }; create_dirs(&[ @@ -145,3 +151,42 @@ impl ParticleAppServicesConfig { Ok(this) } } + +#[derive(Debug, Clone)] +pub struct WasmBackendConfig { + /// Configures whether DWARF debug information will be emitted during compilation. + pub debug_info: bool, + /// Configures whether the errors from the VM should collect the wasm backtrace and parse debug info. + pub wasm_backtrace: bool, + /// Configures the size of the stacks used for asynchronous execution. + pub async_wasm_stack: usize, + /// Configures the maximum amount of stack space available for executing WebAssembly code. + pub max_wasm_stack: usize, + /// Enables the epoch interruption mechanism. + pub epoch_interruption_duration: Option, +} + +impl From for WasmtimeConfig { + fn from(value: WasmBackendConfig) -> Self { + let mut config = WasmtimeConfig::default(); + config + .debug_info(value.debug_info) + .wasm_backtrace(value.wasm_backtrace) + .epoch_interruption(true) + .async_wasm_stack(value.async_wasm_stack) + .max_wasm_stack(value.max_wasm_stack); + config + } +} + +impl Default for WasmBackendConfig { + fn default() -> Self { + Self { + debug_info: true, + wasm_backtrace: true, + async_wasm_stack: 4 * 1024 * 1024, + max_wasm_stack: 2 * 1024 * 1024, + epoch_interruption_duration: Some(Duration::from_secs(1)), + } + } +} diff --git a/particle-services/src/lib.rs b/particle-services/src/lib.rs index 4363096003..278f1f3fd7 100644 --- a/particle-services/src/lib.rs +++ b/particle-services/src/lib.rs @@ -43,4 +43,5 @@ mod config; pub use app_services::ServiceInfo; pub use config::ParticleAppServicesConfig; +pub use config::WasmBackendConfig; pub use types::peer_scope::PeerScope; From bc1880a3ec0fdfaffdd162971fc3b3776adbbf10 Mon Sep 17 00:00:00 2001 From: Nick Pavlov Date: Tue, 23 Apr 2024 13:17:37 +0300 Subject: [PATCH 33/33] fix configs --- aquamarine/src/plumber.rs | 12 +++--------- particle-services/src/app_services.rs | 10 +--------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/aquamarine/src/plumber.rs b/aquamarine/src/plumber.rs index 0fcd71c2ce..fe570f1768 100644 --- a/aquamarine/src/plumber.rs +++ b/aquamarine/src/plumber.rs @@ -675,7 +675,7 @@ mod tests { use async_trait::async_trait; use avm_server::avm_runner::RawAVMOutcome; use marine_wasmtime_backend::{WasmtimeConfig, WasmtimeWasmBackend}; - use particle_services::PeerScope; + use particle_services::{PeerScope, WasmBackendConfig}; use tracing::Span; struct MockF; @@ -756,15 +756,9 @@ mod tests { } async fn plumber() -> Plumber> { - let mut wasmtime_config = WasmtimeConfig::default(); - wasmtime_config - .debug_info(true) - .wasm_backtrace(true) - .epoch_interruption(true) - .async_wasm_stack(2 * 1024 * 1024) - .max_wasm_stack(2 * 1024 * 1024); + let avm_wasm_config: WasmtimeConfig = WasmBackendConfig::default().into(); let avm_wasm_backend = - WasmtimeWasmBackend::new(wasmtime_config).expect("Could not create wasm backend"); + WasmtimeWasmBackend::new(avm_wasm_config).expect("Could not create wasm backend"); // Pool is of size 1 so it's easier to control tests let vm_pool = VmPool::new(1, (), None, None, avm_wasm_backend.clone()); let builtin_mock = Arc::new(MockF); diff --git a/particle-services/src/app_services.rs b/particle-services/src/app_services.rs index 47717bab0c..0e301c6d78 100644 --- a/particle-services/src/app_services.rs +++ b/particle-services/src/app_services.rs @@ -236,15 +236,7 @@ impl ParticleAppServices { persisted_services }); - let mut wasmtime_config = WasmtimeConfig::default(); - // TODO async-marine: impl proper configuration - // TODO async-marine: move to the right place - wasmtime_config - .debug_info(true) - .wasm_backtrace(true) - .epoch_interruption(true) - .async_wasm_stack(2 * 1024 * 1024) - .max_wasm_stack(2 * 1024 * 1024); + let wasmtime_config: WasmtimeConfig = config.wasm_backend_config.clone().into(); let (app_service_factory, epoch_ticker) = AppServiceFactory::new(wasmtime_config).map_err(ServiceError::Engine)?;