From 8b1896382510a724b9c9eb18ef4eafe107217c56 Mon Sep 17 00:00:00 2001 From: Ryan Daum Date: Fri, 6 Dec 2024 19:30:32 -0500 Subject: [PATCH] =?UTF-8?q?Restructure=20the=20source=20tree=20a=20bit?= =?UTF-8?q?=C8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * values -> common rpc-* -> rpc/rpc-* moot & model-checker -> testing/moot, testing/load-tools * Move common RPC CLI arguments up into rpc-common * Rename main.rs to tx-list-append in new load tools to make room for more tools --- Cargo.lock | 2 + Cargo.toml | 27 +- crates/README.md | 13 +- crates/{values => common}/Cargo.toml | 0 crates/{values => common}/src/encode.rs | 2 +- crates/{values => common}/src/lib.rs | 0 .../src/matching/command_parse.rs | 0 .../src/matching/match_env.rs | 0 .../src/matching/mock_matching_env.rs | 0 crates/{values => common}/src/matching/mod.rs | 0 .../src/matching/ws_match_env.rs | 0 crates/{values => common}/src/model/defset.rs | 0 crates/{values => common}/src/model/match.rs | 0 crates/{values => common}/src/model/mod.rs | 0 .../{values => common}/src/model/objects.rs | 0 crates/{values => common}/src/model/objset.rs | 0 .../src/model/permissions.rs | 0 .../{values => common}/src/model/propdef.rs | 0 crates/{values => common}/src/model/props.rs | 0 .../{values => common}/src/model/verbdef.rs | 0 crates/{values => common}/src/model/verbs.rs | 0 .../src/model/world_state.rs | 0 crates/{values => common}/src/tasks/errors.rs | 0 crates/{values => common}/src/tasks/events.rs | 0 crates/{values => common}/src/tasks/mod.rs | 0 .../{values => common}/src/util/bitarray.rs | 0 crates/{values => common}/src/util/bitenum.rs | 2 +- crates/{values => common}/src/util/bitset.rs | 0 crates/{values => common}/src/util/mod.rs | 0 crates/{values => common}/src/var/error.rs | 0 crates/{values => common}/src/var/list.rs | 0 crates/{values => common}/src/var/map.rs | 2 +- crates/{values => common}/src/var/mod.rs | 8 +- crates/{values => common}/src/var/obj.rs | 0 crates/{values => common}/src/var/scalar.rs | 0 crates/{values => common}/src/var/string.rs | 0 crates/{values => common}/src/var/symbol.rs | 0 crates/{values => common}/src/var/var.rs | 0 crates/{values => common}/src/var/variant.rs | 0 crates/compiler/Cargo.toml | 2 +- crates/compiler/src/codegen.rs | 2 +- crates/compiler/src/unparse.rs | 2 +- crates/daemon/Cargo.toml | 4 +- crates/daemon/src/main.rs | 8 +- crates/db/Cargo.toml | 2 +- crates/db/src/db_loader_client.rs | 4 +- crates/db/src/db_transaction.rs | 4 +- crates/db/src/loader.rs | 2 +- crates/db/src/tx/global_cache.rs | 2 +- crates/db/src/tx/tx_table.rs | 6 +- crates/db/src/worldstate_transaction.rs | 2 +- crates/kernel/Cargo.toml | 4 +- crates/kernel/src/builtins/bf_server.rs | 4 +- crates/kernel/src/config.rs | 4 +- crates/kernel/src/tasks/vm_host.rs | 2 +- crates/kernel/src/textdump/load_db.rs | 4 +- crates/kernel/src/vm/moo_execute.rs | 2 +- crates/kernel/src/vm/moo_frame.rs | 2 +- crates/kernel/src/vm/vm_unwind.rs | 2 +- crates/{ => rpc}/rpc-async-client/Cargo.toml | 2 +- crates/{ => rpc}/rpc-async-client/src/lib.rs | 0 .../rpc-async-client/src/listeners.rs | 0 .../rpc-async-client/src/pubsub_client.rs | 0 .../rpc-async-client/src/rpc_client.rs | 0 crates/{ => rpc}/rpc-common/Cargo.toml | 4 +- crates/rpc/rpc-common/src/client_args.rs | 52 ++ crates/{ => rpc}/rpc-common/src/lib.rs | 4 +- crates/{ => rpc}/rpc-sync-client/Cargo.toml | 0 crates/{ => rpc}/rpc-sync-client/src/lib.rs | 0 .../rpc-sync-client/src/pubsub_client.rs | 0 .../rpc-sync-client/src/rpc_client.rs | 0 crates/telnet-host/Cargo.toml | 8 +- crates/telnet-host/src/main.rs | 45 +- .../load-tools}/Cargo.toml | 12 +- crates/testing/load-tools/src/setup.rs | 326 ++++++++++++ .../load-tools/src/tx-list-append.rs} | 500 ++++-------------- crates/{ => testing}/moot/Cargo.toml | 2 +- crates/{ => testing}/moot/README.md | 0 crates/{ => testing}/moot/Test.db | 0 crates/{ => testing}/moot/Test.db.md | 0 crates/{ => testing}/moot/src/lib.rs | 2 +- crates/{ => testing}/moot/tests/moot_lmoo.rs | 0 crates/web-host/Cargo.toml | 6 +- crates/web-host/src/client/rpc.js | 6 +- crates/web-host/src/client/var.js | 6 +- crates/web-host/src/host/mod.rs | 4 +- crates/web-host/src/main.rs | 45 +- 87 files changed, 585 insertions(+), 559 deletions(-) rename crates/{values => common}/Cargo.toml (100%) rename crates/{values => common}/src/encode.rs (98%) rename crates/{values => common}/src/lib.rs (100%) rename crates/{values => common}/src/matching/command_parse.rs (100%) rename crates/{values => common}/src/matching/match_env.rs (100%) rename crates/{values => common}/src/matching/mock_matching_env.rs (100%) rename crates/{values => common}/src/matching/mod.rs (100%) rename crates/{values => common}/src/matching/ws_match_env.rs (100%) rename crates/{values => common}/src/model/defset.rs (100%) rename crates/{values => common}/src/model/match.rs (100%) rename crates/{values => common}/src/model/mod.rs (100%) rename crates/{values => common}/src/model/objects.rs (100%) rename crates/{values => common}/src/model/objset.rs (100%) rename crates/{values => common}/src/model/permissions.rs (100%) rename crates/{values => common}/src/model/propdef.rs (100%) rename crates/{values => common}/src/model/props.rs (100%) rename crates/{values => common}/src/model/verbdef.rs (100%) rename crates/{values => common}/src/model/verbs.rs (100%) rename crates/{values => common}/src/model/world_state.rs (100%) rename crates/{values => common}/src/tasks/errors.rs (100%) rename crates/{values => common}/src/tasks/events.rs (100%) rename crates/{values => common}/src/tasks/mod.rs (100%) rename crates/{values => common}/src/util/bitarray.rs (100%) rename crates/{values => common}/src/util/bitenum.rs (98%) rename crates/{values => common}/src/util/bitset.rs (100%) rename crates/{values => common}/src/util/mod.rs (100%) rename crates/{values => common}/src/var/error.rs (100%) rename crates/{values => common}/src/var/list.rs (100%) rename crates/{values => common}/src/var/map.rs (99%) rename crates/{values => common}/src/var/mod.rs (96%) rename crates/{values => common}/src/var/obj.rs (100%) rename crates/{values => common}/src/var/scalar.rs (100%) rename crates/{values => common}/src/var/string.rs (100%) rename crates/{values => common}/src/var/symbol.rs (100%) rename crates/{values => common}/src/var/var.rs (100%) rename crates/{values => common}/src/var/variant.rs (100%) rename crates/{ => rpc}/rpc-async-client/Cargo.toml (93%) rename crates/{ => rpc}/rpc-async-client/src/lib.rs (100%) rename crates/{ => rpc}/rpc-async-client/src/listeners.rs (100%) rename crates/{ => rpc}/rpc-async-client/src/pubsub_client.rs (100%) rename crates/{ => rpc}/rpc-async-client/src/rpc_client.rs (100%) rename crates/{ => rpc}/rpc-common/Cargo.toml (84%) create mode 100644 crates/rpc/rpc-common/src/client_args.rs rename crates/{ => rpc}/rpc-common/src/lib.rs (99%) rename crates/{ => rpc}/rpc-sync-client/Cargo.toml (100%) rename crates/{ => rpc}/rpc-sync-client/src/lib.rs (100%) rename crates/{ => rpc}/rpc-sync-client/src/pubsub_client.rs (100%) rename crates/{ => rpc}/rpc-sync-client/src/rpc_client.rs (100%) rename crates/{model-checker => testing/load-tools}/Cargo.toml (70%) create mode 100644 crates/testing/load-tools/src/setup.rs rename crates/{model-checker/src/main.rs => testing/load-tools/src/tx-list-append.rs} (65%) rename crates/{ => testing}/moot/Cargo.toml (92%) rename crates/{ => testing}/moot/README.md (100%) rename crates/{ => testing}/moot/Test.db (100%) rename crates/{ => testing}/moot/Test.db.md (100%) rename crates/{ => testing}/moot/src/lib.rs (99%) rename crates/{ => testing}/moot/tests/moot_lmoo.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index ad96419b..a3a8a4ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2346,6 +2346,8 @@ name = "rpc-common" version = "0.1.0" dependencies = [ "bincode", + "clap", + "clap_derive", "moor-values", "pem", "rusty_paseto", diff --git a/Cargo.toml b/Cargo.toml index 2717fd94..ceb4ba98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,31 +2,32 @@ resolver = "2" members = [ + "crates/common", "crates/compiler", "crates/daemon", "crates/db", "crates/kernel", - "crates/model-checker", - "crates/moot", - "crates/rpc-async-client", - "crates/rpc-common", - "crates/rpc-sync-client", + "crates/rpc/rpc-async-client", + "crates/rpc/rpc-common", + "crates/rpc/rpc-sync-client", "crates/telnet-host", - "crates/values", + "crates/testing/load-tools", + "crates/testing/moot", "crates/web-host", ] default-members = [ - "crates/values", + "crates/common", "crates/compiler", "crates/kernel", "crates/db", - "crates/rpc-common", - "crates/rpc-sync-client", - "crates/rpc-async-client", + "crates/rpc/rpc-common", + "crates/rpc/rpc-sync-client", + "crates/rpc/rpc-async-client", "crates/daemon", "crates/telnet-host", "crates/web-host", - "crates/moot", + "crates/testing/moot", + "crates/testing/load-tools", ] [workspace.package] @@ -119,7 +120,7 @@ thiserror = "2.0" ## For macro-ing paste = "1.0" -# For the DB & values layer. +# For the DB & common layer. fjall = { version = "2.4", default-features = false, features = ["ssi_tx", "bytes"] } libc = "0.2" text_io = "0.1" # Used for reading text dumps. @@ -144,5 +145,5 @@ signal-hook = "0.3" # For the telnet host termimad = "0.31" -# For the consistency checker in `model-checker` +# For the consistency checker in `load-tools` edn-format = "3.3.0" diff --git a/crates/README.md b/crates/README.md index 1f7a8919..b2ec3631 100644 --- a/crates/README.md +++ b/crates/README.md @@ -10,9 +10,10 @@ Binaries: network `host`s - `web-host` - like the above, but hosts an HTTP server which provides a websocket interface to the system. as well as various web APIs. -- `model-checker` - a tool for using the `elle` tool from Jepsen for verifying transactional properties of the\ - database -- `moot` - a comprensive test suite for verifying the correctness of the MOO implementation, including a battery of +- `testing/load-tools` - tools for inducing load for transactional consistency test (via jepsen's `elle` tool), or for + performance testing. +- `testing/moot` - a comprensive test suite for verifying the correctness of the MOO implementation, including a battery + of tests ported from ToastStunt. Libraries: @@ -23,6 +24,6 @@ Libraries: - `compiler` - the MOO language grammar, parser, AST, and codegen, as well as the decompiler & unparser - `kernel` - the kernel of the MOO driver: virtual machine, task scheduler, implementations of all builtin\ functions -- `rpc-common` - provides types & functions used by both `daemon` and each host binary, for the RPC interface -- `rpc-async-client` - provides an async RPC client for the `daemon`'s RPC interface -- `rpc-sync-client` - provides a synchronous RPC client for the `daemon`'s RPC interface +- `rpc/rpc-common` - provides types & functions used by both `daemon` and each host binary, for the RPC interface +- `rpc/rpc-async-client` - provides an async RPC client for the `daemon`'s RPC interface +- `rpc/rpc-sync-client` - provides a synchronous RPC client for the `daemon`'s RPC interface diff --git a/crates/values/Cargo.toml b/crates/common/Cargo.toml similarity index 100% rename from crates/values/Cargo.toml rename to crates/common/Cargo.toml diff --git a/crates/values/src/encode.rs b/crates/common/src/encode.rs similarity index 98% rename from crates/values/src/encode.rs rename to crates/common/src/encode.rs index 9d5d5c99..eecfc6ef 100644 --- a/crates/values/src/encode.rs +++ b/crates/common/src/encode.rs @@ -44,7 +44,7 @@ pub enum DecodingError { InvalidErrorValue(u8), } -/// A trait for all values that can be stored in the database. (e.g. all of them). +/// A trait for all common that can be stored in the database. (e.g. all of them). /// To abstract away from the underlying serialization format, we use this trait. pub trait AsByteBuffer { /// Returns the size of this value in bytes. diff --git a/crates/values/src/lib.rs b/crates/common/src/lib.rs similarity index 100% rename from crates/values/src/lib.rs rename to crates/common/src/lib.rs diff --git a/crates/values/src/matching/command_parse.rs b/crates/common/src/matching/command_parse.rs similarity index 100% rename from crates/values/src/matching/command_parse.rs rename to crates/common/src/matching/command_parse.rs diff --git a/crates/values/src/matching/match_env.rs b/crates/common/src/matching/match_env.rs similarity index 100% rename from crates/values/src/matching/match_env.rs rename to crates/common/src/matching/match_env.rs diff --git a/crates/values/src/matching/mock_matching_env.rs b/crates/common/src/matching/mock_matching_env.rs similarity index 100% rename from crates/values/src/matching/mock_matching_env.rs rename to crates/common/src/matching/mock_matching_env.rs diff --git a/crates/values/src/matching/mod.rs b/crates/common/src/matching/mod.rs similarity index 100% rename from crates/values/src/matching/mod.rs rename to crates/common/src/matching/mod.rs diff --git a/crates/values/src/matching/ws_match_env.rs b/crates/common/src/matching/ws_match_env.rs similarity index 100% rename from crates/values/src/matching/ws_match_env.rs rename to crates/common/src/matching/ws_match_env.rs diff --git a/crates/values/src/model/defset.rs b/crates/common/src/model/defset.rs similarity index 100% rename from crates/values/src/model/defset.rs rename to crates/common/src/model/defset.rs diff --git a/crates/values/src/model/match.rs b/crates/common/src/model/match.rs similarity index 100% rename from crates/values/src/model/match.rs rename to crates/common/src/model/match.rs diff --git a/crates/values/src/model/mod.rs b/crates/common/src/model/mod.rs similarity index 100% rename from crates/values/src/model/mod.rs rename to crates/common/src/model/mod.rs diff --git a/crates/values/src/model/objects.rs b/crates/common/src/model/objects.rs similarity index 100% rename from crates/values/src/model/objects.rs rename to crates/common/src/model/objects.rs diff --git a/crates/values/src/model/objset.rs b/crates/common/src/model/objset.rs similarity index 100% rename from crates/values/src/model/objset.rs rename to crates/common/src/model/objset.rs diff --git a/crates/values/src/model/permissions.rs b/crates/common/src/model/permissions.rs similarity index 100% rename from crates/values/src/model/permissions.rs rename to crates/common/src/model/permissions.rs diff --git a/crates/values/src/model/propdef.rs b/crates/common/src/model/propdef.rs similarity index 100% rename from crates/values/src/model/propdef.rs rename to crates/common/src/model/propdef.rs diff --git a/crates/values/src/model/props.rs b/crates/common/src/model/props.rs similarity index 100% rename from crates/values/src/model/props.rs rename to crates/common/src/model/props.rs diff --git a/crates/values/src/model/verbdef.rs b/crates/common/src/model/verbdef.rs similarity index 100% rename from crates/values/src/model/verbdef.rs rename to crates/common/src/model/verbdef.rs diff --git a/crates/values/src/model/verbs.rs b/crates/common/src/model/verbs.rs similarity index 100% rename from crates/values/src/model/verbs.rs rename to crates/common/src/model/verbs.rs diff --git a/crates/values/src/model/world_state.rs b/crates/common/src/model/world_state.rs similarity index 100% rename from crates/values/src/model/world_state.rs rename to crates/common/src/model/world_state.rs diff --git a/crates/values/src/tasks/errors.rs b/crates/common/src/tasks/errors.rs similarity index 100% rename from crates/values/src/tasks/errors.rs rename to crates/common/src/tasks/errors.rs diff --git a/crates/values/src/tasks/events.rs b/crates/common/src/tasks/events.rs similarity index 100% rename from crates/values/src/tasks/events.rs rename to crates/common/src/tasks/events.rs diff --git a/crates/values/src/tasks/mod.rs b/crates/common/src/tasks/mod.rs similarity index 100% rename from crates/values/src/tasks/mod.rs rename to crates/common/src/tasks/mod.rs diff --git a/crates/values/src/util/bitarray.rs b/crates/common/src/util/bitarray.rs similarity index 100% rename from crates/values/src/util/bitarray.rs rename to crates/common/src/util/bitarray.rs diff --git a/crates/values/src/util/bitenum.rs b/crates/common/src/util/bitenum.rs similarity index 98% rename from crates/values/src/util/bitenum.rs rename to crates/common/src/util/bitenum.rs index 1de6d77e..c66fa469 100644 --- a/crates/values/src/util/bitenum.rs +++ b/crates/common/src/util/bitenum.rs @@ -97,7 +97,7 @@ impl BitEnum { } pub fn contains_all(&self, values: BitEnum) -> bool { - // Verify that all bits from values are in self.value + // Verify that all bits from common are in self.value values.value & self.value == values.value } } diff --git a/crates/values/src/util/bitset.rs b/crates/common/src/util/bitset.rs similarity index 100% rename from crates/values/src/util/bitset.rs rename to crates/common/src/util/bitset.rs diff --git a/crates/values/src/util/mod.rs b/crates/common/src/util/mod.rs similarity index 100% rename from crates/values/src/util/mod.rs rename to crates/common/src/util/mod.rs diff --git a/crates/values/src/var/error.rs b/crates/common/src/var/error.rs similarity index 100% rename from crates/values/src/var/error.rs rename to crates/common/src/var/error.rs diff --git a/crates/values/src/var/list.rs b/crates/common/src/var/list.rs similarity index 100% rename from crates/values/src/var/list.rs rename to crates/common/src/var/list.rs diff --git a/crates/values/src/var/map.rs b/crates/common/src/var/map.rs similarity index 99% rename from crates/values/src/var/map.rs rename to crates/common/src/var/map.rs index 978ee3bb..4e0e20ac 100644 --- a/crates/values/src/var/map.rs +++ b/crates/common/src/var/map.rs @@ -92,7 +92,7 @@ impl Associative for Map { } fn index_in(&self, key: &Var, case_sensitive: bool) -> Result, Error> { - // Check the values in the key-value pairs and return the index of the first match. + // Check the common in the key-value pairs and return the index of the first match. // Linear O(N) operation. let pos = self.iter().position(|(_, v)| { if case_sensitive { diff --git a/crates/values/src/var/mod.rs b/crates/common/src/var/mod.rs similarity index 96% rename from crates/values/src/var/mod.rs rename to crates/common/src/var/mod.rs index 77470b5c..a98739ef 100644 --- a/crates/values/src/var/mod.rs +++ b/crates/common/src/var/mod.rs @@ -37,7 +37,7 @@ pub use var::{ }; pub use variant::Variant; -/// Integer encoding of values as represented in a `LambdaMOO` textdump, and by `bf_typeof` +/// Integer encoding of common as represented in a `LambdaMOO` textdump, and by `bf_typeof` #[repr(u8)] #[derive(Clone, Copy, Debug, Eq, PartialEq, FromRepr)] #[allow(non_camel_case_types)] @@ -134,7 +134,7 @@ pub trait Sequence { /// Return a sequence which is a subset of this sequence where the indices lay between `from` /// and `to`, inclusive. fn range(&self, from: isize, to: isize) -> Result; - /// Assign new values to the sequence where the indices lay between `from` and `to`, inclusive. + /// Assign new common to the sequence where the indices lay between `from` and `to`, inclusive. fn range_set(&self, from: isize, to: isize, with: &Var) -> Result; /// Append the given sequence to this sequence. fn append(&self, other: &Var) -> Result; @@ -158,11 +158,11 @@ pub trait Associative { fn index_set(&self, key: &Var, value: &Var) -> Result; /// Return the key-value pairs in the associative container between the given `from` and `to` fn range(&self, from: &Var, to: &Var) -> Result; - /// Assign new values to the key-value pairs in the associative container between the given `from` and `to` + /// Assign new common to the key-value pairs in the associative container between the given `from` and `to` fn range_set(&self, from: &Var, to: &Var, with: &Var) -> Result; /// Return the keys in the associative container. fn keys(&self) -> Vec; - /// Return the values in the associative container. + /// Return the common in the associative container. fn values(&self) -> Vec; /// Check if the associative container contains the key, returning true if it does. fn contains_key(&self, key: &Var, case_sensitive: bool) -> Result; diff --git a/crates/values/src/var/obj.rs b/crates/common/src/var/obj.rs similarity index 100% rename from crates/values/src/var/obj.rs rename to crates/common/src/var/obj.rs diff --git a/crates/values/src/var/scalar.rs b/crates/common/src/var/scalar.rs similarity index 100% rename from crates/values/src/var/scalar.rs rename to crates/common/src/var/scalar.rs diff --git a/crates/values/src/var/string.rs b/crates/common/src/var/string.rs similarity index 100% rename from crates/values/src/var/string.rs rename to crates/common/src/var/string.rs diff --git a/crates/values/src/var/symbol.rs b/crates/common/src/var/symbol.rs similarity index 100% rename from crates/values/src/var/symbol.rs rename to crates/common/src/var/symbol.rs diff --git a/crates/values/src/var/var.rs b/crates/common/src/var/var.rs similarity index 100% rename from crates/values/src/var/var.rs rename to crates/common/src/var/var.rs diff --git a/crates/values/src/var/variant.rs b/crates/common/src/var/variant.rs similarity index 100% rename from crates/values/src/var/variant.rs rename to crates/common/src/var/variant.rs diff --git a/crates/compiler/Cargo.toml b/crates/compiler/Cargo.toml index 453a3fec..0664e473 100644 --- a/crates/compiler/Cargo.toml +++ b/crates/compiler/Cargo.toml @@ -18,7 +18,7 @@ unindent.workspace = true [dependencies] ## Own -moor-values = { path = "../values" } +moor-values = { path = "../common" } ## General usefulness bincode.workspace = true diff --git a/crates/compiler/src/codegen.rs b/crates/compiler/src/codegen.rs index 00875ed5..51f970b6 100644 --- a/crates/compiler/src/codegen.rs +++ b/crates/compiler/src/codegen.rs @@ -818,7 +818,7 @@ impl CodegenState { } fn generate_arg_list(&mut self, args: &Vec) -> Result<(), CompileError> { - // TODO: Check recursion down to see if all literal values, and if so reduce to a Imm value with the full list, + // TODO: Check recursion down to see if all literal common, and if so reduce to a Imm value with the full list, // instead of concatenation with MkSingletonList. if args.is_empty() { self.emit(Op::ImmEmptyList); diff --git a/crates/compiler/src/unparse.rs b/crates/compiler/src/unparse.rs index 1d2941bc..c35274f7 100644 --- a/crates/compiler/src/unparse.rs +++ b/crates/compiler/src/unparse.rs @@ -728,7 +728,7 @@ pub fn annotate_line_numbers(start_line_no: usize, tree: &mut [Stmt]) -> usize { } /// Utility function to produce a MOO literal from a Var/Variant. -/// This is kept in `compiler` and not in `values` because it's specific to the MOO language, and +/// This is kept in `compiler` and not in `common` because it's specific to the MOO language, and /// other languages could have different representations. pub fn to_literal(v: &Var) -> String { match v.variant() { diff --git a/crates/daemon/Cargo.toml b/crates/daemon/Cargo.toml index d0eb014a..088716f4 100644 --- a/crates/daemon/Cargo.toml +++ b/crates/daemon/Cargo.toml @@ -14,8 +14,8 @@ description = "The actual moor binary that runs as an RPC-accessible daemon that [dependencies] moor-db = { path = "../db" } moor-kernel = { path = "../kernel" } -moor-values = { path = "../values" } -rpc-common = { path = "../rpc-common" } +moor-values = { path = "../common" } +rpc-common = { path = "../rpc/rpc-common" } ## Command line arguments parsing. clap.workspace = true diff --git a/crates/daemon/src/main.rs b/crates/daemon/src/main.rs index c7858dd9..b43a9929 100644 --- a/crates/daemon/src/main.rs +++ b/crates/daemon/src/main.rs @@ -163,13 +163,13 @@ struct Args { #[arg(long, help = "Enable debug logging", default_value = "false")] debug: bool, - /// Whether to allow notify() to send arbitrary MOO values to players. The interpretation of - /// the values varies depending on host/client. + /// Whether to allow notify() to send arbitrary MOO common to players. The interpretation of + /// the common varies depending on host/client. /// If this is false, only strings are allowed, as in LambdaMOO. #[arg( long, - help = "Enable rich_notify, allowing notify() to send arbitrary MOO values to players. \ - The interpretation of the values varies depending on host/client. \ + help = "Enable rich_notify, allowing notify() to send arbitrary MOO common to players. \ + The interpretation of the common varies depending on host/client. \ If this is false, only strings are allowed, as in LambdaMOO.", default_value = "true" )] diff --git a/crates/db/Cargo.toml b/crates/db/Cargo.toml index f04caf99..32129150 100644 --- a/crates/db/Cargo.toml +++ b/crates/db/Cargo.toml @@ -16,7 +16,7 @@ tempfile.workspace = true [dependencies] ## Own -moor-values = { path = "../values" } +moor-values = { path = "../common" } ## Error declaration/ handling bytes.workspace = true diff --git a/crates/db/src/db_loader_client.rs b/crates/db/src/db_loader_client.rs index 79b2048a..e527416d 100644 --- a/crates/db/src/db_loader_client.rs +++ b/crates/db/src/db_loader_client.rs @@ -169,9 +169,9 @@ impl LoaderInterface for DbTxWorldState { // First get the entire inheritance hierarchy. let hierarchy = self.get_tx().ancestors(this)?; - // Now get the property values for each of those objects, but only for the props which + // Now get the property common for each of those objects, but only for the props which // are defined by that object. - // At the same time, get the values. + // At the same time, get the common. let mut properties = vec![]; for obj in hierarchy.iter() { let obj_propdefs = self.get_tx().get_properties(&obj)?; diff --git a/crates/db/src/db_transaction.rs b/crates/db/src/db_transaction.rs index fecbd913..6f882036 100644 --- a/crates/db/src/db_transaction.rs +++ b/crates/db/src/db_transaction.rs @@ -348,7 +348,7 @@ impl WorldStateTransaction for DbTransaction { let mut descendant_props = HashMap::new(); for c in descendants.iter() { let mut inherited_props = vec![]; - // Remove the set values. + // Remove the set common. let old_props = self.get_properties(o)?; if !old_props.is_empty() { for p in old_props.iter() { @@ -458,7 +458,7 @@ impl WorldStateTransaction for DbTransaction { } fn get_object_size_bytes(&self, obj: &Obj) -> Result { - // Means retrieving the values for all of the objects attributes, and then summing their sizes. + // Means retrieving the common for all of the objects attributes, and then summing their sizes. // This is remarkably inefficient. let flags = self.get_object_flags(obj)?; diff --git a/crates/db/src/loader.rs b/crates/db/src/loader.rs index d705c7f8..8cc17413 100644 --- a/crates/db/src/loader.rs +++ b/crates/db/src/loader.rs @@ -95,7 +95,7 @@ pub trait LoaderInterface: Send { uuid: Uuid, ) -> Result<(Option, PropPerms), WorldStateError>; - /// Returns all the property values from the root of the inheritance hierarchy down to the + /// Returns all the property common from the root of the inheritance hierarchy down to the /// bottom, for the given object. #[allow(clippy::type_complexity)] fn get_all_property_values( diff --git a/crates/db/src/tx/global_cache.rs b/crates/db/src/tx/global_cache.rs index 3bf9967a..5750eab5 100644 --- a/crates/db/src/tx/global_cache.rs +++ b/crates/db/src/tx/global_cache.rs @@ -49,7 +49,7 @@ where Domain: Hash + PartialEq + Eq + Clone, Codomain: Clone + PartialEq + Eq, { - /// A series of values that local caches should be pre-seeded with. + /// A series of common that local caches should be pre-seeded with. preseed: HashSet, index: Mutex>, diff --git a/crates/db/src/tx/tx_table.rs b/crates/db/src/tx/tx_table.rs index 3e5ae2a7..d697d232 100644 --- a/crates/db/src/tx/tx_table.rs +++ b/crates/db/src/tx/tx_table.rs @@ -370,7 +370,7 @@ where let mut index = self.index.borrow_mut(); // This is basically like going a `get` on each entry, we're filling our cache with - // all the upstream values. + // all the upstream common. for (ts, d, c) in upstream { let entry = index.get_mut(&d); match entry { @@ -594,7 +594,7 @@ mod tests { Entry::NotPresent(Timestamp(1)) ); - // Inserting brand new values... + // Inserting brand new common... let result = cache.insert(6, 6); assert_eq!(result, Ok(())); assert_eq!( @@ -609,7 +609,7 @@ mod tests { }) ); - // Upsert should work for new values and old... + // Upsert should work for new common and old... // Not present local or upstream. let old_value = cache.upsert(7, 7).unwrap(); diff --git a/crates/db/src/worldstate_transaction.rs b/crates/db/src/worldstate_transaction.rs index 34aa23e2..05611c7a 100644 --- a/crates/db/src/worldstate_transaction.rs +++ b/crates/db/src/worldstate_transaction.rs @@ -28,7 +28,7 @@ use moor_values::Obj; use moor_values::Symbol; use moor_values::Var; -/// A trait defining a generic interface to a database for storing the per-attribute values +/// A trait defining a generic interface to a database for storing the per-attribute common /// of our objects and their properties and verbs. Used by DbTxWorldState. /// One instance per transaction. pub trait WorldStateTransaction: Send { diff --git a/crates/kernel/Cargo.toml b/crates/kernel/Cargo.toml index 4d50aeaa..d019899e 100644 --- a/crates/kernel/Cargo.toml +++ b/crates/kernel/Cargo.toml @@ -39,8 +39,8 @@ harness = false ## Own moor-compiler = { path = "../compiler" } moor-db = { path = "../db" } -moor-moot = { path = "../moot" } -moor-values = { path = "../values" } +moor-moot = { path = "../testing/moot" } +moor-values = { path = "../common" } ## General usefulness bytes.workspace = true diff --git a/crates/kernel/src/builtins/bf_server.rs b/crates/kernel/src/builtins/bf_server.rs index c906fac1..5be5bcad 100644 --- a/crates/kernel/src/builtins/bf_server.rs +++ b/crates/kernel/src/builtins/bf_server.rs @@ -729,7 +729,7 @@ bf_declare!(function_info, bf_function_info); /// `object` is the object to call when a connection is established, in lieux of #0 (the system object) /// if `print-messages` is true, then the server will print messages like ** Connected ** etc to the connection when it establishes /// if `host-type` is provided, it should be a string, and it will be used to determine the type of host that will be expected to listen. -/// this defaults to "tcp", but other values can include "websocket" +/// this defaults to "tcp", but other common can include "websocket" fn bf_listen(bf_args: &mut BfCallState<'_>) -> Result { // Requires wizard permissions. bf_args @@ -1000,7 +1000,7 @@ bf_declare!(db_disk_size, db_disk_size); /* Function: none load_server_options () - This causes the server to consult the current values of properties on $server_options, updating + This causes the server to consult the current common of properties on $server_options, updating the corresponding server option settings (see section Server Options Set in the Database) accordingly. If the programmer is not a wizard, then E_PERM is raised. */ diff --git a/crates/kernel/src/config.rs b/crates/kernel/src/config.rs index b0656562..e040d7f2 100644 --- a/crates/kernel/src/config.rs +++ b/crates/kernel/src/config.rs @@ -21,8 +21,8 @@ use std::path::PathBuf; #[derive(Clone, Debug)] pub struct Config { - /// Whether to allow notify() to send arbitrary MOO values to players. The interpretation of - /// the values varies depending on host/client. + /// Whether to allow notify() to send arbitrary MOO common to players. The interpretation of + /// the common varies depending on host/client. /// If this is false, only strings are allowed, as in LambdaMOO. pub rich_notify: bool, /// Where to write periodic textdumps of the database. diff --git a/crates/kernel/src/tasks/vm_host.rs b/crates/kernel/src/tasks/vm_host.rs index 2f9eda88..95f59815 100644 --- a/crates/kernel/src/tasks/vm_host.rs +++ b/crates/kernel/src/tasks/vm_host.rs @@ -50,7 +50,7 @@ use crate::vm::{FinallyReason, VMExecState}; use crate::PhantomUnsync; use moor_values::matching::command_parse::ParsedCommand; -/// Return values from exec_interpreter back to the Task scheduler loop +/// Return common from exec_interpreter back to the Task scheduler loop pub enum VMHostResponse { /// Tell the task to just keep on letting us do what we're doing. ContinueOk, diff --git a/crates/kernel/src/textdump/load_db.rs b/crates/kernel/src/textdump/load_db.rs index 9af6d8bc..90b8410c 100644 --- a/crates/kernel/src/textdump/load_db.rs +++ b/crates/kernel/src/textdump/load_db.rs @@ -145,7 +145,7 @@ pub fn read_textdump( // Define props. This means going through and just adding at the very root, which will create // initially-clear state in all the descendants. A second pass will then go through and update - // flags and values for the children. + // flags and common for the children. for (objid, o) in &td.objects { for (pnum, _p) in o.propvals.iter().enumerate() { let resolved = resolve_prop(&td.objects, pnum, o).unwrap(); @@ -167,7 +167,7 @@ pub fn read_textdump( } } - info!("Setting property values & info"); + info!("Setting property common & info"); for (objid, o) in &td.objects { for (pnum, p) in o.propvals.iter().enumerate() { let resolved = resolve_prop(&td.objects, pnum, o).unwrap(); diff --git a/crates/kernel/src/vm/moo_execute.rs b/crates/kernel/src/vm/moo_execute.rs index c31071f3..efd79099 100644 --- a/crates/kernel/src/vm/moo_execute.rs +++ b/crates/kernel/src/vm/moo_execute.rs @@ -216,7 +216,7 @@ pub fn moo_frame_execute( // TODO: Handling for MAXINT/MAXOBJ in various opcodes // Given we're 64-bit this is highly unlikely to ever be a concern for us, but - // we also don't want to *crash* on obscene values, so impl that here. + // we also don't want to *crash* on obscene common, so impl that here. let next_val = match (to.variant(), from.variant()) { (Variant::Int(to_i), Variant::Int(from_i)) => { diff --git a/crates/kernel/src/vm/moo_frame.rs b/crates/kernel/src/vm/moo_frame.rs index b980e66f..2e3e165d 100644 --- a/crates/kernel/src/vm/moo_frame.rs +++ b/crates/kernel/src/vm/moo_frame.rs @@ -31,7 +31,7 @@ pub(crate) struct MooStackFrame { pub(crate) program: Program, /// The program counter. pub(crate) pc: usize, - /// The values of the variables currently in scope, by their offset. + /// The common of the variables currently in scope, by their offset. pub(crate) environment: BitArray>, /// The current used scope size, used when entering and exiting local scopes. pub(crate) environment_width: usize, diff --git a/crates/kernel/src/vm/vm_unwind.rs b/crates/kernel/src/vm/vm_unwind.rs index ba1a027e..8bfb721e 100644 --- a/crates/kernel/src/vm/vm_unwind.rs +++ b/crates/kernel/src/vm/vm_unwind.rs @@ -210,7 +210,7 @@ impl VMExecState { /// which makes its way back up to the scheduler. /// Contains all the logic for handling the various reasons for exiting a verb execution: /// * Error raises of various kinds - /// * Return values + /// * Return common pub(crate) fn unwind_stack(&mut self, why: FinallyReason) -> ExecutionResult { // Walk activation stack from bottom to top, tossing frames as we go. while let Some(a) = self.stack.last_mut() { diff --git a/crates/rpc-async-client/Cargo.toml b/crates/rpc/rpc-async-client/Cargo.toml similarity index 93% rename from crates/rpc-async-client/Cargo.toml rename to crates/rpc/rpc-async-client/Cargo.toml index 863abdcf..19af6d08 100644 --- a/crates/rpc-async-client/Cargo.toml +++ b/crates/rpc/rpc-async-client/Cargo.toml @@ -13,7 +13,7 @@ description = "Utilities for connection to the 0MQ RPC server via tokio/async ca [dependencies] # Own -moor-values = { path = "../values" } +moor-values = { path = "../../common" } rpc-common = { path = "../rpc-common" } bincode.workspace = true diff --git a/crates/rpc-async-client/src/lib.rs b/crates/rpc/rpc-async-client/src/lib.rs similarity index 100% rename from crates/rpc-async-client/src/lib.rs rename to crates/rpc/rpc-async-client/src/lib.rs diff --git a/crates/rpc-async-client/src/listeners.rs b/crates/rpc/rpc-async-client/src/listeners.rs similarity index 100% rename from crates/rpc-async-client/src/listeners.rs rename to crates/rpc/rpc-async-client/src/listeners.rs diff --git a/crates/rpc-async-client/src/pubsub_client.rs b/crates/rpc/rpc-async-client/src/pubsub_client.rs similarity index 100% rename from crates/rpc-async-client/src/pubsub_client.rs rename to crates/rpc/rpc-async-client/src/pubsub_client.rs diff --git a/crates/rpc-async-client/src/rpc_client.rs b/crates/rpc/rpc-async-client/src/rpc_client.rs similarity index 100% rename from crates/rpc-async-client/src/rpc_client.rs rename to crates/rpc/rpc-async-client/src/rpc_client.rs diff --git a/crates/rpc-common/Cargo.toml b/crates/rpc/rpc-common/Cargo.toml similarity index 84% rename from crates/rpc-common/Cargo.toml rename to crates/rpc/rpc-common/Cargo.toml index 749ba010..62eadb93 100644 --- a/crates/rpc-common/Cargo.toml +++ b/crates/rpc/rpc-common/Cargo.toml @@ -13,9 +13,11 @@ description = "Common entities used for 0MQ based RPC communication with the dae [dependencies] # Own -moor-values = { path = "../values" } +moor-values = { path = "../../common" } bincode.workspace = true +clap.workspace = true +clap_derive.workspace = true thiserror.workspace = true # Auth/Auth diff --git a/crates/rpc/rpc-common/src/client_args.rs b/crates/rpc/rpc-common/src/client_args.rs new file mode 100644 index 00000000..c58e67a6 --- /dev/null +++ b/crates/rpc/rpc-common/src/client_args.rs @@ -0,0 +1,52 @@ +// Copyright (C) 2024 Ryan Daum +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, version 3. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +// + +use clap_derive::Parser; +use std::path::PathBuf; + +/// Common command line arguments for hosts / clients +#[derive(Parser, Debug)] // requires `derive` feature +pub struct RpcClientArgs { + #[arg( + long, + value_name = "rpc-address", + help = "RPC ZMQ req-reply socket address", + default_value = "ipc:///tmp/moor_rpc.sock" + )] + pub rpc_address: String, + + #[arg( + long, + value_name = "events-address", + help = "Events ZMQ pub-sub address", + default_value = "ipc:///tmp/moor_events.sock" + )] + pub events_address: String, + + #[arg( + long, + value_name = "public_key", + help = "file containing the pkcs8 ed25519 public key (shared with the daemon), used for authenticating client & host connections", + default_value = "public_key.pem" + )] + pub public_key: PathBuf, + + #[arg( + long, + value_name = "private_key", + help = "file containing a pkcs8 ed25519 private key (shared with the daemon), used for authenticating client & host connections", + default_value = "private_key.pem" + )] + pub private_key: PathBuf, +} diff --git a/crates/rpc-common/src/lib.rs b/crates/rpc/rpc-common/src/lib.rs similarity index 99% rename from crates/rpc-common/src/lib.rs rename to crates/rpc/rpc-common/src/lib.rs index 3bf160e0..013d8c17 100644 --- a/crates/rpc-common/src/lib.rs +++ b/crates/rpc/rpc-common/src/lib.rs @@ -23,6 +23,8 @@ use std::path::Path; use std::time::SystemTime; use thiserror::Error; +pub mod client_args; + /// A ZMQ topic for broadcasting to all clients of all hosts. pub const CLIENT_BROADCAST_TOPIC: &[u8; 9] = b"broadcast"; @@ -266,7 +268,7 @@ pub enum ClientEvent { Disconnect(), /// Task errors that should be sent to the client. TaskError(usize, SchedulerError), - /// Task return values on success that the client can get. + /// Task return common on success that the client can get. TaskSuccess(usize, Var), } diff --git a/crates/rpc-sync-client/Cargo.toml b/crates/rpc/rpc-sync-client/Cargo.toml similarity index 100% rename from crates/rpc-sync-client/Cargo.toml rename to crates/rpc/rpc-sync-client/Cargo.toml diff --git a/crates/rpc-sync-client/src/lib.rs b/crates/rpc/rpc-sync-client/src/lib.rs similarity index 100% rename from crates/rpc-sync-client/src/lib.rs rename to crates/rpc/rpc-sync-client/src/lib.rs diff --git a/crates/rpc-sync-client/src/pubsub_client.rs b/crates/rpc/rpc-sync-client/src/pubsub_client.rs similarity index 100% rename from crates/rpc-sync-client/src/pubsub_client.rs rename to crates/rpc/rpc-sync-client/src/pubsub_client.rs diff --git a/crates/rpc-sync-client/src/rpc_client.rs b/crates/rpc/rpc-sync-client/src/rpc_client.rs similarity index 100% rename from crates/rpc-sync-client/src/rpc_client.rs rename to crates/rpc/rpc-sync-client/src/rpc_client.rs diff --git a/crates/telnet-host/Cargo.toml b/crates/telnet-host/Cargo.toml index 27dc032a..ae396143 100644 --- a/crates/telnet-host/Cargo.toml +++ b/crates/telnet-host/Cargo.toml @@ -13,10 +13,10 @@ description = "A server which presents a classic LambdaMOO-style line-based TCP [dependencies] moor-compiler = { path = "../compiler" } -moor-moot = { path = "../moot" } -moor-values = { path = "../values" } -rpc-async-client = { path = "../rpc-async-client" } -rpc-common = { path = "../rpc-common" } +moor-moot = { path = "../testing/moot" } +moor-values = { path = "../common" } +rpc-async-client = { path = "../rpc/rpc-async-client" } +rpc-common = { path = "../rpc/rpc-common" } ## Command line arguments parsing. clap.workspace = true diff --git a/crates/telnet-host/src/main.rs b/crates/telnet-host/src/main.rs index 6e467284..e3b56a5d 100644 --- a/crates/telnet-host/src/main.rs +++ b/crates/telnet-host/src/main.rs @@ -19,9 +19,9 @@ use clap::Parser; use clap_derive::Parser; use moor_values::SYSTEM_OBJECT; use rpc_async_client::{make_host_token, proces_hosts_events, start_host_session}; +use rpc_common::client_args::RpcClientArgs; use rpc_common::{load_keypair, HostType}; use std::net::SocketAddr; -use std::path::PathBuf; use std::sync::atomic::AtomicBool; use std::sync::Arc; use tokio::select; @@ -49,38 +49,6 @@ struct Args { )] telnet_port: u16, - #[arg( - long, - value_name = "rpc-address", - help = "RPC ZMQ req-reply socket address", - default_value = "ipc:///tmp/moor_rpc.sock" - )] - rpc_address: String, - - #[arg( - long, - value_name = "events-address", - help = "Events ZMQ pub-sub address", - default_value = "ipc:///tmp/moor_events.sock" - )] - events_address: String, - - #[arg( - long, - value_name = "public_key", - help = "file containing the pkcs8 ed25519 public key (shared with the daemon), used for authenticating client & host connections", - default_value = "public_key.pem" - )] - public_key: PathBuf, - - #[arg( - long, - value_name = "private_key", - help = "file containing a pkcs8 ed25519 private key (shared with the daemon), used for authenticating client & host connections", - default_value = "private_key.pem" - )] - private_key: PathBuf, - #[arg(long, help = "Enable debug logging", default_value = "false")] debug: bool, } @@ -89,6 +57,7 @@ struct Args { async fn main() -> Result<(), eyre::Error> { color_eyre::install()?; let args: Args = Args::parse(); + let client_args: RpcClientArgs = RpcClientArgs::parse(); let main_subscriber = tracing_subscriber::fmt() .compact() @@ -120,8 +89,8 @@ async fn main() -> Result<(), eyre::Error> { let (mut listeners_server, listeners_channel, listeners) = Listeners::new( zmq_ctx.clone(), - args.rpc_address.clone(), - args.events_address.clone(), + client_args.rpc_address.clone(), + client_args.events_address.clone(), kill_switch.clone(), ); let listeners_thread = tokio::spawn(async move { @@ -133,14 +102,14 @@ async fn main() -> Result<(), eyre::Error> { .await .expect("Unable to start default listener"); - let keypair = load_keypair(&args.public_key, &args.private_key) + let keypair = load_keypair(&client_args.public_key, &client_args.private_key) .expect("Unable to load keypair from public and private key files"); let host_token = make_host_token(&keypair, HostType::TCP); let rpc_client = start_host_session( host_token.clone(), zmq_ctx.clone(), - args.rpc_address.clone(), + client_args.rpc_address.clone(), kill_switch.clone(), listeners.clone(), ) @@ -151,7 +120,7 @@ async fn main() -> Result<(), eyre::Error> { rpc_client, host_token, zmq_ctx.clone(), - args.events_address.clone(), + client_args.events_address.clone(), args.telnet_address.clone(), kill_switch.clone(), listeners.clone(), diff --git a/crates/model-checker/Cargo.toml b/crates/testing/load-tools/Cargo.toml similarity index 70% rename from crates/model-checker/Cargo.toml rename to crates/testing/load-tools/Cargo.toml index 0061f6e5..d48ab660 100644 --- a/crates/model-checker/Cargo.toml +++ b/crates/testing/load-tools/Cargo.toml @@ -9,12 +9,16 @@ license.workspace = true readme.workspace = true repository.workspace = true rust-version.workspace = true -description = "Checks transactional consistency of the moor runtime" +description = "Load testing and transaction model checking" + +[[bin]] +name = "moor-model-checker" +path = "src/tx-list-append.rs" [dependencies] -moor-values = { path = "../values" } -rpc-async-client = { path = "../rpc-async-client" } -rpc-common = { path = "../rpc-common" } +moor-values = { path = "../../common" } +rpc-async-client = { path = "../../rpc/rpc-async-client" } +rpc-common = { path = "../../rpc/rpc-common" } clap.workspace = true clap_derive.workspace = true diff --git a/crates/testing/load-tools/src/setup.rs b/crates/testing/load-tools/src/setup.rs new file mode 100644 index 00000000..6be70189 --- /dev/null +++ b/crates/testing/load-tools/src/setup.rs @@ -0,0 +1,326 @@ +// Copyright (C) 2024 Ryan Daum +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, version 3. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +// + +use eyre::bail; +use moor_values::model::ObjectRef; +use moor_values::tasks::VerbProgramError; +use moor_values::{Obj, Symbol, SYSTEM_OBJECT}; +use rpc_async_client::pubsub_client::broadcast_recv; +use rpc_async_client::rpc_client::RpcSendClient; +use rpc_async_client::{ListenersClient, ListenersMessage}; +use rpc_common::HostClientToDaemonMessage::ConnectionEstablish; +use rpc_common::{ + AuthToken, ClientToken, ClientsBroadcastEvent, DaemonToClientReply, HostClientToDaemonMessage, + HostType, ReplyResult, VerbProgramResponse, CLIENT_BROADCAST_TOPIC, +}; +use std::net::{Ipv4Addr, SocketAddr}; +use std::sync::atomic::AtomicBool; +use std::sync::Arc; +use std::time::SystemTime; +use tmq::subscribe::Subscribe; +use tmq::{request, subscribe}; +use tokio::task::JoinHandle; +use tracing::{debug, error, info}; +use uuid::Uuid; + +pub async fn noop_listeners_loop() -> (ListenersClient, JoinHandle<()>) { + let (tx, mut rx) = tokio::sync::mpsc::channel(1); + let t = tokio::spawn(async move { + while let Some(msg) = rx.recv().await { + match msg { + ListenersMessage::AddListener(_, _) => {} + ListenersMessage::RemoveListener(_) => {} + ListenersMessage::GetListeners(r) => { + let _ = r.send(vec![]); + } + } + } + }); + + (ListenersClient::new(tx), t) +} + +pub async fn broadcast_handle( + zmq_ctx: tmq::Context, + rpc_address: String, + mut broadcast_sub: Subscribe, + client_id: Uuid, + client_token: ClientToken, + connection_oid: Obj, + kill_switch: Arc, +) { + let rpc_request_sock = request(&zmq_ctx) + .set_rcvtimeo(100) + .set_sndtimeo(100) + .connect(rpc_address.as_str()) + .expect("Unable to bind RPC server for connection"); + + let mut rpc_client = RpcSendClient::new(rpc_request_sock); + // Process ping-pongs on the broadcast topic. + tokio::spawn(async move { + loop { + if kill_switch.load(std::sync::atomic::Ordering::Relaxed) { + break; + } + if let Ok(event) = broadcast_recv(&mut broadcast_sub).await { + match event { + ClientsBroadcastEvent::PingPong(_) => { + let _ = rpc_client + .make_client_rpc_call( + client_id, + HostClientToDaemonMessage::ClientPong( + client_token.clone(), + SystemTime::now(), + connection_oid.clone(), + HostType::TCP, + SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0), + ), + ) + .await; + } + } + } + } + }); +} + +pub async fn create_user_session( + zmq_ctx: tmq::Context, + rpc_address: String, + events_address: String, +) -> Result< + ( + Obj, + AuthToken, + ClientToken, + Uuid, + RpcSendClient, + Subscribe, + Subscribe, + ), + eyre::Error, +> { + let rpc_request_sock = request(&zmq_ctx) + .set_rcvtimeo(100) + .set_sndtimeo(100) + .connect(rpc_address.as_str()) + .expect("Unable to bind RPC server for connection"); + + // And let the RPC server know we're here, and it should start sending events on the + // narrative subscription. + debug!(rpc_address, "Contacting RPC server to establish connection"); + let mut rpc_client = RpcSendClient::new(rpc_request_sock); + let client_id = uuid::Uuid::new_v4(); + let peer_addr = format!("{}.test", Uuid::new_v4()); + let (client_token, connection_oid) = match rpc_client + .make_client_rpc_call(client_id, ConnectionEstablish(peer_addr.to_string())) + .await + { + Ok(ReplyResult::ClientSuccess(DaemonToClientReply::NewConnection(token, objid))) => { + (token, objid) + } + Ok(ReplyResult::Failure(f)) => { + bail!("RPC failure in connection establishment: {}", f); + } + Ok(_) => { + bail!("Unexpected response from RPC server"); + } + Err(e) => { + bail!("Unable to establish connection: {}", e); + } + }; + debug!(client_id = ?client_id, connection = ?connection_oid, "Connection established"); + + let events_sub = subscribe(&zmq_ctx) + .connect(events_address.as_str()) + .expect("Unable to connect narrative subscriber "); + let events_sub = events_sub + .subscribe(&client_id.as_bytes()[..]) + .expect("Unable to subscribe to narrative messages for client connection"); + let broadcast_sub = subscribe(&zmq_ctx) + .connect(events_address.as_str()) + .expect("Unable to connect broadcast subscriber "); + let broadcast_sub = broadcast_sub + .subscribe(CLIENT_BROADCAST_TOPIC) + .expect("Unable to subscribe to broadcast messages for client connection"); + + info!( + "Subscribed on pubsub events socket for {:?}, socket addr {}", + client_id, events_address + ); + + // Now "connect wizard" + let response = rpc_client + .make_client_rpc_call( + client_id, + HostClientToDaemonMessage::LoginCommand( + client_token.clone(), + SYSTEM_OBJECT, + vec!["connect".to_string(), "wizard".to_string()], + false, + ), + ) + .await + .expect("Unable to send login request to RPC server"); + let (connection_oid, auth_token) = if let ReplyResult::ClientSuccess( + DaemonToClientReply::LoginResult(Some((auth_token, _connect_type, player))), + ) = response + { + (player.clone(), auth_token.clone()) + } else { + panic!("Unexpected response from RPC server"); + }; + + Ok(( + connection_oid, + auth_token, + client_token, + client_id, + rpc_client, + events_sub, + broadcast_sub, + )) +} + +pub async fn compile( + rpc_client: &mut RpcSendClient, + client_id: Uuid, + oid: Obj, + auth_token: AuthToken, + client_token: ClientToken, + verb_name: Symbol, + verb_contents: Vec, +) { + let response = rpc_client + .make_client_rpc_call( + client_id, + HostClientToDaemonMessage::Verbs( + client_token.clone(), + auth_token.clone(), + ObjectRef::Id(oid.clone()), + ), + ) + .await + .expect("Unable to send verbs request to RPC server"); + match response { + ReplyResult::ClientSuccess(DaemonToClientReply::Verbs(verbs)) => { + info!("Got verbs: {:?}", verbs); + } + _ => { + panic!("RPC failure in verbs"); + } + } + + let response = rpc_client + .make_client_rpc_call( + client_id, + HostClientToDaemonMessage::Program( + client_token.clone(), + auth_token.clone(), + ObjectRef::Id(oid.clone()), + verb_name, + verb_contents, + ), + ) + .await + .expect("Unable to send program request to RPC server"); + + match response { + ReplyResult::ClientSuccess(DaemonToClientReply::ProgramResponse( + VerbProgramResponse::Success(_, _), + )) => { + info!("Programmed {}:{} successfully", oid, verb_name); + } + ReplyResult::ClientSuccess(DaemonToClientReply::ProgramResponse( + VerbProgramResponse::Failure(e), + )) => match e { + VerbProgramError::NoVerbToProgram => { + panic!("No verb to program"); + } + VerbProgramError::CompilationError(e) => { + error!("Compilation error in {}:{}", oid, verb_name); + for e in e { + error!("{}", e); + } + panic!("Compilation error"); + } + VerbProgramError::DatabaseError => { + panic!("Database error"); + } + }, + _ => { + panic!("RPC failure in program"); + } + } +} + +pub async fn initialization_session( + connection_oid: Obj, + auth_token: AuthToken, + client_token: ClientToken, + client_id: Uuid, + mut rpc_client: RpcSendClient, + initialization_script: &str, + verbs: &[(Symbol, String)], +) -> Result<(), eyre::Error> { + let response = rpc_client + .make_client_rpc_call( + client_id, + HostClientToDaemonMessage::Eval( + client_token.clone(), + auth_token.clone(), + initialization_script.to_string(), + ), + ) + .await + .expect("Unable to send eval request to RPC server"); + + match response { + ReplyResult::HostSuccess(hs) => { + info!("Evaluated successfully: {:?}", hs); + } + ReplyResult::ClientSuccess(cs) => { + info!("Evaluated successfully: {:?}", cs); + } + ReplyResult::Failure(f) => { + panic!("RPC failure in eval: {}", f); + } + } + + info!("Initialization script executed successfully"); + + for (verb_name, verb_code) in verbs { + compile( + &mut rpc_client, + client_id, + connection_oid.clone(), + auth_token.clone(), + client_token.clone(), + verb_name.clone(), + verb_code.split('\n').map(|s| s.to_string()).collect(), + ) + .await; + + info!("Compiled {} verb", verb_name); + } + + info!("Initialization session complete"); + + Ok(()) +} + +pub struct ExecutionContext { + pub(crate) zmq_ctx: tmq::Context, + pub(crate) kill_switch: Arc, +} diff --git a/crates/model-checker/src/main.rs b/crates/testing/load-tools/src/tx-list-append.rs similarity index 65% rename from crates/model-checker/src/main.rs rename to crates/testing/load-tools/src/tx-list-append.rs index 5ffc4c7a..09c2e648 100644 --- a/crates/model-checker/src/main.rs +++ b/crates/testing/load-tools/src/tx-list-append.rs @@ -18,35 +18,35 @@ //! The results are written to a file in the EDN format that `elle-cli` can consume. //! See: https://github.com/ligurio/elle-cli +mod setup; + +use crate::setup::{broadcast_handle, create_user_session, initialization_session}; use clap::Parser; use clap_derive::Parser; use edn_format::{Keyword, Value}; -use eyre::{anyhow, bail}; +use eyre::anyhow; use futures::stream::FuturesUnordered; use futures::StreamExt; use moor_values::model::ObjectRef; -use moor_values::tasks::VerbProgramError; -use moor_values::{v_int, v_list, List, Obj, Sequence, Symbol, Var, Variant, SYSTEM_OBJECT}; -use rpc_async_client::pubsub_client::{broadcast_recv, events_recv}; +use moor_values::{v_int, v_list, List, Obj, Sequence, Symbol, Var, Variant}; +use rpc_async_client::pubsub_client::events_recv; use rpc_async_client::rpc_client::RpcSendClient; -use rpc_async_client::{make_host_token, start_host_session, ListenersClient, ListenersMessage}; +use rpc_async_client::{make_host_token, start_host_session}; +use rpc_common::client_args::RpcClientArgs; use rpc_common::DaemonToClientReply::TaskSubmitted; -use rpc_common::HostClientToDaemonMessage::ConnectionEstablish; use rpc_common::{ - load_keypair, AuthToken, ClientEvent, ClientToken, ClientsBroadcastEvent, DaemonToClientReply, - HostClientToDaemonMessage, HostType, ReplyResult, VerbProgramResponse, CLIENT_BROADCAST_TOPIC, + load_keypair, AuthToken, ClientEvent, ClientToken, HostClientToDaemonMessage, HostType, + ReplyResult, }; +use setup::ExecutionContext; use std::collections::{BTreeMap, HashMap}; -use std::net::{Ipv4Addr, SocketAddr}; use std::path::PathBuf; use std::sync::atomic::AtomicBool; use std::sync::Arc; -use std::time::{Instant, SystemTime}; -use tmq::subscribe::Subscribe; -use tmq::{request, subscribe}; +use std::time::Instant; +use tmq::request; use tokio::sync::Mutex; -use tokio::task::JoinHandle; -use tracing::{debug, error, info}; +use tracing::{debug, info}; use uuid::Uuid; #[derive(Clone, Parser, Debug)] @@ -59,38 +59,6 @@ struct Args { )] num_users: usize, - #[arg( - long, - value_name = "rpc-address", - help = "RPC ZMQ req-reply socket address", - default_value = "ipc:///tmp/moor_rpc.sock" - )] - rpc_address: String, - - #[arg( - long, - value_name = "events-address", - help = "Events ZMQ pub-sub address", - default_value = "ipc:///tmp/moor_events.sock" - )] - events_address: String, - - #[arg( - long, - value_name = "public_key", - help = "file containing the pkcs8 ed25519 public key (shared with the daemon), used for authenticating client & host connections", - default_value = "public_key.pem" - )] - public_key: PathBuf, - - #[arg( - long, - value_name = "private_key", - help = "file containing a pkcs8 ed25519 private key (shared with the daemon), used for authenticating client & host connections", - default_value = "private_key.pem" - )] - private_key: PathBuf, - #[arg(long, help = "Enable debug logging", default_value = "false")] debug: bool, @@ -127,166 +95,8 @@ struct Args { output_file: PathBuf, } -async fn noop_listeners_loop() -> (ListenersClient, JoinHandle<()>) { - let (tx, mut rx) = tokio::sync::mpsc::channel(1); - let t = tokio::spawn(async move { - while let Some(msg) = rx.recv().await { - match msg { - ListenersMessage::AddListener(_, _) => {} - ListenersMessage::RemoveListener(_) => {} - ListenersMessage::GetListeners(r) => { - let _ = r.send(vec![]); - } - } - } - }); - - (ListenersClient::new(tx), t) -} - -async fn broadcast_handle( - zmq_ctx: tmq::Context, - rpc_address: String, - mut broadcast_sub: Subscribe, - client_id: Uuid, - client_token: ClientToken, - connection_oid: Obj, - kill_switch: Arc, -) { - let rpc_request_sock = request(&zmq_ctx) - .set_rcvtimeo(100) - .set_sndtimeo(100) - .connect(rpc_address.as_str()) - .expect("Unable to bind RPC server for connection"); - - let mut rpc_client = RpcSendClient::new(rpc_request_sock); - // Process ping-pongs on the broadcast topic. - tokio::spawn(async move { - loop { - if kill_switch.load(std::sync::atomic::Ordering::Relaxed) { - break; - } - if let Ok(event) = broadcast_recv(&mut broadcast_sub).await { - match event { - ClientsBroadcastEvent::PingPong(_) => { - let _ = rpc_client - .make_client_rpc_call( - client_id, - HostClientToDaemonMessage::ClientPong( - client_token.clone(), - SystemTime::now(), - connection_oid.clone(), - HostType::TCP, - SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0), - ), - ) - .await; - } - } - } - } - }); -} -async fn create_user_session( - zmq_ctx: tmq::Context, - rpc_address: String, - events_address: String, -) -> Result< - ( - Obj, - AuthToken, - ClientToken, - Uuid, - RpcSendClient, - Subscribe, - Subscribe, - ), - eyre::Error, -> { - let rpc_request_sock = request(&zmq_ctx) - .set_rcvtimeo(100) - .set_sndtimeo(100) - .connect(rpc_address.as_str()) - .expect("Unable to bind RPC server for connection"); - - // And let the RPC server know we're here, and it should start sending events on the - // narrative subscription. - debug!(rpc_address, "Contacting RPC server to establish connection"); - let mut rpc_client = RpcSendClient::new(rpc_request_sock); - let client_id = uuid::Uuid::new_v4(); - let peer_addr = format!("{}.test", Uuid::new_v4()); - let (client_token, connection_oid) = match rpc_client - .make_client_rpc_call(client_id, ConnectionEstablish(peer_addr.to_string())) - .await - { - Ok(ReplyResult::ClientSuccess(DaemonToClientReply::NewConnection(token, objid))) => { - (token, objid) - } - Ok(ReplyResult::Failure(f)) => { - bail!("RPC failure in connection establishment: {}", f); - } - Ok(_) => { - bail!("Unexpected response from RPC server"); - } - Err(e) => { - bail!("Unable to establish connection: {}", e); - } - }; - debug!(client_id = ?client_id, connection = ?connection_oid, "Connection established"); - - let events_sub = subscribe(&zmq_ctx) - .connect(events_address.as_str()) - .expect("Unable to connect narrative subscriber "); - let events_sub = events_sub - .subscribe(&client_id.as_bytes()[..]) - .expect("Unable to subscribe to narrative messages for client connection"); - let broadcast_sub = subscribe(&zmq_ctx) - .connect(events_address.as_str()) - .expect("Unable to connect broadcast subscriber "); - let broadcast_sub = broadcast_sub - .subscribe(CLIENT_BROADCAST_TOPIC) - .expect("Unable to subscribe to broadcast messages for client connection"); - - info!( - "Subscribed on pubsub events socket for {:?}, socket addr {}", - client_id, events_address - ); - - // Now "connect wizard" - let response = rpc_client - .make_client_rpc_call( - client_id, - HostClientToDaemonMessage::LoginCommand( - client_token.clone(), - SYSTEM_OBJECT, - vec!["connect".to_string(), "wizard".to_string()], - false, - ), - ) - .await - .expect("Unable to send login request to RPC server"); - let (connection_oid, auth_token) = if let ReplyResult::ClientSuccess( - DaemonToClientReply::LoginResult(Some((auth_token, _connect_type, player))), - ) = response - { - (player.clone(), auth_token.clone()) - } else { - panic!("Unexpected response from RPC server"); - }; - - Ok(( - connection_oid, - auth_token, - client_token, - client_id, - rpc_client, - events_sub, - broadcast_sub, - )) -} - // Script for creating the set of properties we want to use -const ADD_PROPS_SCRIPT: &str = r#" +const LIST_APPEND_INITIALIZATION_SCRIPT: &str = r#" for i in [1..num_props] let prop = "prop_" + tostr(i); try @@ -306,8 +116,8 @@ suspend(1); return 1; "#; -/// Verb code for writing to the properties. Returns the pre-write values and the written values -const WRITE_WORKLOAD_VERB: &str = r#" +/// Verb code for writing to the properties. Returns the pre-write common and the written common +const LIST_APPEND_WRITE_WORKLOAD_VERB: &str = r#" append_props = args[1]; let read_log = {}; let write_log = {}; @@ -332,8 +142,8 @@ endfor return {read_log, write_log}; "#; -/// Verb code for a read workload. Just reads from random properties and returns the values -const READ_WORKLOAD_VERB: &str = r#" +/// Verb code for a read workload. Just reads from random properties and returns the common +const LIST_APPEND_READ_WORKLOAD_VERB: &str = r#" read_props = args[1]; let read_log = {}; for i in [1..length(read_props)] @@ -345,149 +155,6 @@ endfor return {read_log}; "#; -async fn compile( - rpc_client: &mut RpcSendClient, - client_id: Uuid, - oid: Obj, - auth_token: AuthToken, - client_token: ClientToken, - verb_name: Symbol, - verb_contents: Vec, -) { - let response = rpc_client - .make_client_rpc_call( - client_id, - HostClientToDaemonMessage::Verbs( - client_token.clone(), - auth_token.clone(), - ObjectRef::Id(oid.clone()), - ), - ) - .await - .expect("Unable to send verbs request to RPC server"); - match response { - ReplyResult::ClientSuccess(DaemonToClientReply::Verbs(verbs)) => { - info!("Got verbs: {:?}", verbs); - } - _ => { - panic!("RPC failure in verbs"); - } - } - - let response = rpc_client - .make_client_rpc_call( - client_id, - HostClientToDaemonMessage::Program( - client_token.clone(), - auth_token.clone(), - ObjectRef::Id(oid.clone()), - verb_name, - verb_contents, - ), - ) - .await - .expect("Unable to send program request to RPC server"); - - match response { - ReplyResult::ClientSuccess(DaemonToClientReply::ProgramResponse( - VerbProgramResponse::Success(_, _), - )) => { - info!("Programmed {}:{} successfully", oid, verb_name); - } - ReplyResult::ClientSuccess(DaemonToClientReply::ProgramResponse( - VerbProgramResponse::Failure(e), - )) => match e { - VerbProgramError::NoVerbToProgram => { - panic!("No verb to program"); - } - VerbProgramError::CompilationError(e) => { - error!("Compilation error in {}:{}", oid, verb_name); - for e in e { - error!("{}", e); - } - panic!("Compilation error"); - } - VerbProgramError::DatabaseError => { - panic!("Database error"); - } - }, - _ => { - panic!("RPC failure in program"); - } - } -} - -async fn initialization_session( - args: &Args, - connection_oid: Obj, - auth_token: AuthToken, - client_token: ClientToken, - client_id: Uuid, - mut rpc_client: RpcSendClient, -) -> Result<(), eyre::Error> { - let num_props_script = format!("let num_props = {};{}", args.num_props, ADD_PROPS_SCRIPT); - let response = rpc_client - .make_client_rpc_call( - client_id, - HostClientToDaemonMessage::Eval( - client_token.clone(), - auth_token.clone(), - num_props_script, - ), - ) - .await - .expect("Unable to send eval request to RPC server"); - - match response { - ReplyResult::HostSuccess(hs) => { - info!("Evaluated successfully: {:?}", hs); - } - ReplyResult::ClientSuccess(cs) => { - info!("Evaluated successfully: {:?}", cs); - } - ReplyResult::Failure(f) => { - panic!("RPC failure in eval: {}", f); - } - } - - info!( - "Created/cleared {} properties & workload verbs", - args.num_props - ); - - compile( - &mut rpc_client, - client_id, - connection_oid.clone(), - auth_token.clone(), - client_token.clone(), - Symbol::mk("write_workload"), - WRITE_WORKLOAD_VERB - .split('\n') - .map(|s| s.to_string()) - .collect(), - ) - .await; - - info!("Compiled write_workload verb"); - compile( - &mut rpc_client, - client_id, - connection_oid.clone(), - auth_token.clone(), - client_token.clone(), - Symbol::mk("read_workload"), - READ_WORKLOAD_VERB - .split('\n') - .map(|s| s.to_string()) - .collect(), - ) - .await; - info!("Compiled read_workload verb"); - - Ok(()) -} - #[derive(Debug, Clone)] enum WorkItem { Append(usize, Vec<(usize, Vec)>), @@ -512,7 +179,7 @@ fn process_reads(read_log: &List) -> Vec<(usize, Vec)> { let Variant::List(values) = prop_entry[1].variant() else { panic!( - "Unexpected prop values for prop_num {}: {:?}", + "Unexpected prop common for prop_num {}: {:?}", prop_num, prop_entry[1] ); }; @@ -538,7 +205,7 @@ fn process_writes(write_log: &List) -> Vec<(usize, Vec)> { panic!("Unexpected write log entry: {:?}", prop_entry); }; let prop_entry: Vec<_> = l.iter().collect(); - // first item should be the prop num, second should be the written values + // first item should be the prop num, second should be the written common let (prop, values) = { let Variant::Int(prop_num) = prop_entry[0].variant() else { panic!("Unexpected prop num value: {:?}", prop_entry[0]); @@ -546,7 +213,7 @@ fn process_writes(write_log: &List) -> Vec<(usize, Vec)> { let Variant::List(values) = prop_entry[1].variant() else { panic!( - "Unexpected prop values for prop_num {}: {:?}", + "Unexpected prop common for prop_num {}: {:?}", prop_num, prop_entry[1] ); }; @@ -685,47 +352,14 @@ async fn workload( Ok(workload) } -#[tokio::main(flavor = "multi_thread")] -async fn main() -> Result<(), eyre::Error> { - color_eyre::install().expect("Unable to install color_eyre"); - let args: Args = Args::parse(); - - let main_subscriber = tracing_subscriber::fmt() - .compact() - .with_ansi(true) - .with_file(true) - .with_line_number(true) - .with_thread_names(true) - .with_max_level(if args.debug { - tracing::Level::DEBUG - } else { - tracing::Level::INFO - }) - .finish(); - tracing::subscriber::set_global_default(main_subscriber) - .expect("Unable to set configure logging"); - - let zmq_ctx = tmq::Context::new(); - let kill_switch = Arc::new(AtomicBool::new(false)); - - let keypair = load_keypair(&args.public_key, &args.private_key) - .expect("Unable to load keypair from public and private key files"); - let host_token = make_host_token(&keypair, HostType::TCP); - - let (listeners, _ljh) = noop_listeners_loop().await; - - let _rpc_client = start_host_session( - host_token.clone(), - zmq_ctx.clone(), - args.rpc_address.clone(), - kill_switch.clone(), - listeners.clone(), - ) - .await - .expect("Unable to establish initial host session"); - - // Create the initialization user session - // which will be used to make sure the properties we want to use are set up +async fn list_append_workload( + args: Args, + client_args: RpcClientArgs, + ExecutionContext { + zmq_ctx, + kill_switch, + }: ExecutionContext, +) -> Result<(), eyre::Error> { let ( connection_oid, auth_token, @@ -736,15 +370,15 @@ async fn main() -> Result<(), eyre::Error> { broadcast_sub, ) = create_user_session( zmq_ctx.clone(), - args.rpc_address.clone(), - args.events_address.clone(), + client_args.rpc_address.clone(), + client_args.events_address.clone(), ) .await?; { let kill_switch = kill_switch.clone(); let zmq_ctx = zmq_ctx.clone(); - let rpc_address = args.rpc_address.clone(); + let rpc_address = client_args.rpc_address.clone(); let client_id = client_id.clone(); let client_token = client_token.clone(); let connection_oid = connection_oid.clone(); @@ -763,13 +397,28 @@ async fn main() -> Result<(), eyre::Error> { } info!("Initializing workload session (creating properties & verbs)"); + let num_props_script = format!( + "let num_props = {};{}", + args.num_props, LIST_APPEND_INITIALIZATION_SCRIPT + ); + initialization_session( - &args, connection_oid.clone(), auth_token.clone(), client_token.clone(), client_id, rpc_client, + &num_props_script, + &[ + ( + Symbol::mk("write_workload"), + LIST_APPEND_WRITE_WORKLOAD_VERB.to_string(), + ), + ( + Symbol::mk("read_workload"), + LIST_APPEND_READ_WORKLOAD_VERB.to_string(), + ), + ], ) .await?; @@ -818,7 +467,7 @@ async fn main() -> Result<(), eyre::Error> { let connection_oid = connection_oid.clone(); let auth_token = auth_token.clone(); let client_token = client_token.clone(); - let rpc_address = args.rpc_address.clone(); + let rpc_address = client_args.rpc_address.clone(); let args = args.clone(); let task_results = task_results.clone(); workload_futures.push(workload( @@ -984,6 +633,55 @@ async fn main() -> Result<(), eyre::Error> { std::fs::write(&args.output_file, output_document)?; info!("Workload written to {}", args.output_file.display()); + Ok(()) +} + +#[tokio::main(flavor = "multi_thread")] +async fn main() -> Result<(), eyre::Error> { + color_eyre::install().expect("Unable to install color_eyre"); + let args: Args = Args::parse(); + let client_args: RpcClientArgs = RpcClientArgs::parse(); + + let main_subscriber = tracing_subscriber::fmt() + .compact() + .with_ansi(true) + .with_file(true) + .with_line_number(true) + .with_thread_names(true) + .with_max_level(if args.debug { + tracing::Level::DEBUG + } else { + tracing::Level::INFO + }) + .finish(); + tracing::subscriber::set_global_default(main_subscriber) + .expect("Unable to set configure logging"); + + let zmq_ctx = tmq::Context::new(); + let kill_switch = Arc::new(AtomicBool::new(false)); + + let keypair = load_keypair(&client_args.public_key, &client_args.private_key) + .expect("Unable to load keypair from public and private key files"); + let host_token = make_host_token(&keypair, HostType::TCP); + + let (listeners, _ljh) = setup::noop_listeners_loop().await; + + let _rpc_client = start_host_session( + host_token.clone(), + zmq_ctx.clone(), + client_args.rpc_address.clone(), + kill_switch.clone(), + listeners.clone(), + ) + .await + .expect("Unable to establish initial host session"); + + let exec_context = ExecutionContext { + zmq_ctx, + kill_switch: kill_switch.clone(), + }; + list_append_workload(args, client_args, exec_context).await?; + kill_switch.store(true, std::sync::atomic::Ordering::Relaxed); Ok(()) } diff --git a/crates/moot/Cargo.toml b/crates/testing/moot/Cargo.toml similarity index 92% rename from crates/moot/Cargo.toml rename to crates/testing/moot/Cargo.toml index 490064b6..5d3a1832 100644 --- a/crates/moot/Cargo.toml +++ b/crates/testing/moot/Cargo.toml @@ -17,4 +17,4 @@ pretty_assertions.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -moor-values = { path = "../values" } +moor-values = { path = "../../common" } diff --git a/crates/moot/README.md b/crates/testing/moot/README.md similarity index 100% rename from crates/moot/README.md rename to crates/testing/moot/README.md diff --git a/crates/moot/Test.db b/crates/testing/moot/Test.db similarity index 100% rename from crates/moot/Test.db rename to crates/testing/moot/Test.db diff --git a/crates/moot/Test.db.md b/crates/testing/moot/Test.db.md similarity index 100% rename from crates/moot/Test.db.md rename to crates/testing/moot/Test.db.md diff --git a/crates/moot/src/lib.rs b/crates/testing/moot/src/lib.rs similarity index 99% rename from crates/moot/src/lib.rs rename to crates/testing/moot/src/lib.rs index 180f5bfb..ebb65de6 100644 --- a/crates/moot/src/lib.rs +++ b/crates/testing/moot/src/lib.rs @@ -281,7 +281,7 @@ impl MootState { runner.none() }; - // Send the values through the debug formatter, because MOO string comparison + // Send the common through the debug formatter, because MOO string comparison // is case-insensitive, but we want case-sensitive comparison in tests. assert_eq!( format!("{actual:?}"), diff --git a/crates/moot/tests/moot_lmoo.rs b/crates/testing/moot/tests/moot_lmoo.rs similarity index 100% rename from crates/moot/tests/moot_lmoo.rs rename to crates/testing/moot/tests/moot_lmoo.rs diff --git a/crates/web-host/Cargo.toml b/crates/web-host/Cargo.toml index 029430ef..61df3f95 100644 --- a/crates/web-host/Cargo.toml +++ b/crates/web-host/Cargo.toml @@ -12,9 +12,9 @@ rust-version.workspace = true description = "A RESTful web front end for interacting with the moor system" [dependencies] -moor-values = { path = "../values" } -rpc-async-client = { path = "../rpc-async-client" } -rpc-common = { path = "../rpc-common" } +moor-values = { path = "../common" } +rpc-async-client = { path = "../rpc/rpc-async-client" } +rpc-common = { path = "../rpc/rpc-common" } ## Command line arguments parsing. clap.workspace = true diff --git a/crates/web-host/src/client/rpc.js b/crates/web-host/src/client/rpc.js index 850dde44..4f4da0ae 100644 --- a/crates/web-host/src/client/rpc.js +++ b/crates/web-host/src/client/rpc.js @@ -15,7 +15,7 @@ // import {ObjectRef} from "./var"; // Converts a JSON representation of a MOO value into a MOO expression string -// JSON values look like: +// JSON common look like: // number -> number // "string" -> "string" // { error_code: number, error_name: string (e.g. E_PROPNF), error_message: string } -> E_ @@ -51,8 +51,8 @@ function json_to_moo(json) { } } -// Turn a list of arguments containing JSON values into a string which is a list of MOO -// values. +// Turn a list of arguments containing JSON common into a string which is a list of MOO +// common. function transform_args(args) { let result = []; for (let i = 0; i < args.length; i++) { diff --git a/crates/web-host/src/client/var.js b/crates/web-host/src/client/var.js index 513fd89b..9adbd84a 100644 --- a/crates/web-host/src/client/var.js +++ b/crates/web-host/src/client/var.js @@ -13,7 +13,7 @@ // // Parse a JSON document representing a MOO 'Var'. -// Moor JSON values are a bit special because we have a number of types that are not a direct map. +// Moor JSON common are a bit special because we have a number of types that are not a direct map. // Represents a MOO 'map' which is a list of key-value pairs in sorted order and binary search for keys. // (We cannot use a JavaScript object because the keys are potentially-not strings.) @@ -110,7 +110,7 @@ export class Map { this.pairs = pairs; } - // Insert a key-value pair into the map, replacing the value if the key already exists, values are kept in sorted + // Insert a key-value pair into the map, replacing the value if the key already exists, common are kept in sorted // order. // As in MOO, we are CoW friendly, so we return a new map with the new pair inserted. insert(key, value) { @@ -156,7 +156,7 @@ export class Map { return this.pairs.map(pair => pair[0]); } - // Return the values in the map + // Return the common in the map values() { return this.pairs.map(pair => pair[1]); } diff --git a/crates/web-host/src/host/mod.rs b/crates/web-host/src/host/mod.rs index 6aa03609..0597f52e 100644 --- a/crates/web-host/src/host/mod.rs +++ b/crates/web-host/src/host/mod.rs @@ -47,8 +47,8 @@ struct Error { } /// Construct a JSON representation of a Var. -/// This is not a straight-ahead representation because moo values have some semantic differences -/// from JSON values, in particular: +/// This is not a straight-ahead representation because moo common have some semantic differences +/// from JSON common, in particular: /// - Maps are not supported in JSON serialization, so we have to encode them as a list of pairs, /// with a tag to indicate that it's a map. /// - Object references are encoded as a JSON object with a tag to indicate the type of reference. diff --git a/crates/web-host/src/main.rs b/crates/web-host/src/main.rs index 89465042..d2465080 100644 --- a/crates/web-host/src/main.rs +++ b/crates/web-host/src/main.rs @@ -28,9 +28,9 @@ use moor_values::{Obj, SYSTEM_OBJECT}; use rpc_async_client::{ make_host_token, proces_hosts_events, start_host_session, ListenersClient, ListenersMessage, }; +use rpc_common::client_args::RpcClientArgs; use rpc_common::{load_keypair, HostType}; use std::net::SocketAddr; -use std::path::PathBuf; use std::sync::atomic::AtomicBool; use std::sync::Arc; use tokio::net::TcpListener; @@ -47,38 +47,6 @@ struct Args { default_value = "0.0.0.0:8080" )] listen_address: String, - - #[arg( - long, - value_name = "rpc-address", - help = "RPC server address", - default_value = "ipc:///tmp/moor_rpc.sock" - )] - rpc_address: String, - - #[arg( - long, - value_name = "events-address", - help = "Events server address", - default_value = "ipc:///tmp/moor_events.sock" - )] - events_address: String, - - #[arg( - long, - value_name = "public_key", - help = "file containing the pkcs8 ed25519 public key (shared with the daemon), used for authenticating client & host connections", - default_value = "public_key.pem" - )] - public_key: PathBuf, - - #[arg( - long, - value_name = "private_key", - help = "file containing a pkcs8 ed25519 private key (shared with the daemon), used for authenticating client & host connections", - default_value = "private_key.pem" - )] - private_key: PathBuf, } struct Listeners { @@ -251,6 +219,7 @@ fn mk_routes(web_host: WebHost) -> eyre::Result { async fn main() -> Result<(), eyre::Error> { color_eyre::install()?; let args: Args = Args::parse(); + let client_args: RpcClientArgs = RpcClientArgs::parse(); let main_subscriber = tracing_subscriber::fmt() .compact() @@ -270,7 +239,7 @@ async fn main() -> Result<(), eyre::Error> { let kill_switch = Arc::new(AtomicBool::new(false)); - let keypair = load_keypair(&args.public_key, &args.private_key) + let keypair = load_keypair(&client_args.public_key, &client_args.private_key) .expect("Unable to load keypair from public and private key files"); let host_token = make_host_token(&keypair, HostType::TCP); @@ -278,8 +247,8 @@ async fn main() -> Result<(), eyre::Error> { let (mut listeners_server, listeners_channel, listeners) = Listeners::new( zmq_ctx.clone(), - args.rpc_address.clone(), - args.events_address.clone(), + client_args.rpc_address.clone(), + client_args.events_address.clone(), kill_switch.clone(), ); let listeners_thread = tokio::spawn(async move { @@ -289,7 +258,7 @@ async fn main() -> Result<(), eyre::Error> { let rpc_client = start_host_session( host_token.clone(), zmq_ctx.clone(), - args.rpc_address.clone(), + client_args.rpc_address.clone(), kill_switch.clone(), listeners.clone(), ) @@ -305,7 +274,7 @@ async fn main() -> Result<(), eyre::Error> { rpc_client, host_token, zmq_ctx.clone(), - args.events_address.clone(), + client_args.events_address.clone(), args.listen_address.clone(), kill_switch.clone(), listeners.clone(),