From fa8491bcd40462162593f7643c0d26ae2e131f0e Mon Sep 17 00:00:00 2001 From: ActivePeter <1020401660@qq.com> Date: Wed, 21 Feb 2024 00:22:03 -0800 Subject: [PATCH] feat(kv,wasm): kv persist and http arg 1. Persist kv on master 2. Support multi fn http handler(second level path) 3. Suited panote app --- Cargo.lock | 77 ++ Cargo.toml | 3 + apps/_wasm_serverless_lib/Cargo.toml | 1 + apps/_wasm_serverless_lib/src/lib.rs | 23 +- apps/fn2/Cargo.lock | 3 + apps/longchain/Cargo.lock | 3 + apps/panote_auth/Cargo.lock | 568 +++++++++++ apps/panote_auth/Cargo.toml | 21 + apps/panote_auth/app.yaml | 11 + apps/panote_auth/files/authority_config.json | 5 + apps/panote_auth/src/impl.rs | 37 + apps/panote_auth/src/impl/authority.rs | 132 +++ apps/panote_auth/src/lib.rs | 46 + apps/panote_auth/src/struct.rs | 12 + apps/panote_content/Cargo.lock | 213 ++++ apps/panote_content/Cargo.toml | 19 + apps/panote_content/app.yaml | 76 ++ apps/panote_content/src/impl.rs | 927 ++++++++++++++++++ apps/panote_content/src/lib.rs | 163 +++ apps/panote_content/src/struct.rs | 64 ++ apps/panote_list/Cargo.lock | 213 ++++ apps/panote_list/Cargo.toml | 19 + apps/panote_list/app.yaml | 16 + apps/panote_list/src/impl.rs | 80 ++ apps/panote_list/src/lib.rs | 43 + apps/panote_list/src/struct.rs | 16 + apps/word_count/Cargo.lock | 3 + apps/word_count/src/lib.rs | 2 +- scripts/build/_ans_build_demo_apps_each.yml | 19 +- scripts/build/ans_build_demo_apps.yml | 3 + .../test_dir/files/node_config.yaml | 4 +- scripts/http_test.py | 6 +- src/general/{fs => m_fs}/mod.rs | 54 +- src/general/m_kv_store_engine.rs | 138 +++ ...ric_publisher.rs => m_metric_publisher.rs} | 13 +- src/general/mod.rs | 5 +- src/general/network/http_handler.rs | 49 +- src/general/network/{p2p.rs => m_p2p.rs} | 9 +- .../network/{p2p_quic.rs => m_p2p_quic.rs} | 27 +- src/general/network/mod.rs | 4 +- src/general/network/msg_pack.rs | 2 +- src/main.rs | 2 +- .../{http_handler.rs => m_http_handler.rs} | 43 +- src/master/{master.rs => m_master.rs} | 12 +- src/master/{master_kv.rs => m_master_kv.rs} | 82 +- ...etric_observor.rs => m_metric_observor.rs} | 12 +- src/master/mod.rs | 8 +- src/sys.rs | 103 +- src/worker/app_meta.rs | 8 + src/worker/kv_storage.rs | 4 - src/worker/{executor.rs => m_executor.rs} | 153 ++- .../{http_handler.rs => m_http_handler.rs} | 38 +- ...tance_manager.rs => m_instance_manager.rs} | 17 +- ...{kv_user_client.rs => m_kv_user_client.rs} | 23 +- src/worker/{worker.rs => m_worker.rs} | 10 +- src/worker/mod.rs | 11 +- src/worker/wasm_host_funcs/fs.rs | 29 +- src/worker/wasm_host_funcs/kv.rs | 5 +- src/worker/wasm_host_funcs/mod.rs | 60 +- src/worker/wasm_host_funcs/result.rs | 30 + 60 files changed, 3487 insertions(+), 292 deletions(-) create mode 100644 apps/panote_auth/Cargo.lock create mode 100644 apps/panote_auth/Cargo.toml create mode 100644 apps/panote_auth/app.yaml create mode 100644 apps/panote_auth/files/authority_config.json create mode 100644 apps/panote_auth/src/impl.rs create mode 100644 apps/panote_auth/src/impl/authority.rs create mode 100644 apps/panote_auth/src/lib.rs create mode 100644 apps/panote_auth/src/struct.rs create mode 100644 apps/panote_content/Cargo.lock create mode 100644 apps/panote_content/Cargo.toml create mode 100644 apps/panote_content/app.yaml create mode 100644 apps/panote_content/src/impl.rs create mode 100644 apps/panote_content/src/lib.rs create mode 100644 apps/panote_content/src/struct.rs create mode 100644 apps/panote_list/Cargo.lock create mode 100644 apps/panote_list/Cargo.toml create mode 100644 apps/panote_list/app.yaml create mode 100644 apps/panote_list/src/impl.rs create mode 100644 apps/panote_list/src/lib.rs create mode 100644 apps/panote_list/src/struct.rs rename src/general/{fs => m_fs}/mod.rs (56%) create mode 100644 src/general/m_kv_store_engine.rs rename src/general/{metric_publisher.rs => m_metric_publisher.rs} (85%) rename src/general/network/{p2p.rs => m_p2p.rs} (98%) rename src/general/network/{p2p_quic.rs => m_p2p_quic.rs} (94%) rename src/master/{http_handler.rs => m_http_handler.rs} (72%) rename src/master/{master.rs => m_master.rs} (90%) rename src/master/{master_kv.rs => m_master_kv.rs} (74%) rename src/master/{metric_observor.rs => m_metric_observor.rs} (92%) delete mode 100644 src/worker/kv_storage.rs rename src/worker/{executor.rs => m_executor.rs} (67%) rename src/worker/{http_handler.rs => m_http_handler.rs} (57%) rename src/worker/{instance_manager.rs => m_instance_manager.rs} (93%) rename src/worker/{kv_user_client.rs => m_kv_user_client.rs} (85%) rename src/worker/{worker.rs => m_worker.rs} (77%) create mode 100644 src/worker/wasm_host_funcs/result.rs diff --git a/Cargo.lock b/Cargo.lock index 8ad0e2e..33debcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,6 +234,12 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.5.0" @@ -387,6 +393,15 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -619,6 +634,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "futures" version = "0.3.29" @@ -708,6 +733,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -806,6 +840,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + [[package]] name = "httparse" version = "1.8.0" @@ -2044,6 +2084,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + [[package]] name = "slog" version = "2.7.0" @@ -2356,6 +2412,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +dependencies = [ + "bitflags 2.4.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.2" @@ -2640,6 +2714,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", + "sled", "slog", "slog-async", "slog-term", @@ -2648,6 +2723,8 @@ dependencies = [ "sysinfo", "thiserror", "tokio", + "tower", + "tower-http", "tracing", "tracing-subscriber", "wasmedge-sdk", diff --git a/Cargo.toml b/Cargo.toml index 1106ecb..5709972 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,9 @@ moka = { version = "0.12.1", features = ["sync"] } rand = "0.8.5" slotmap = { version = "1.0" } prometheus-client = "0.22.1" +tower-http = {version="0.4.0", features=["cors"]} +tower= "0.4.0" +sled = "0.34.7" # slog-envlogger = { version = "2.1.0", optional = true } diff --git a/apps/_wasm_serverless_lib/Cargo.toml b/apps/_wasm_serverless_lib/Cargo.toml index 3698b3e..9126f81 100644 --- a/apps/_wasm_serverless_lib/Cargo.toml +++ b/apps/_wasm_serverless_lib/Cargo.toml @@ -8,3 +8,4 @@ edition = "2021" crate-type = ["lib"] [dependencies] +wasmedge-bindgen = "0.4.1" \ No newline at end of file diff --git a/apps/_wasm_serverless_lib/src/lib.rs b/apps/_wasm_serverless_lib/src/lib.rs index ab3d529..6f0c8ae 100644 --- a/apps/_wasm_serverless_lib/src/lib.rs +++ b/apps/_wasm_serverless_lib/src/lib.rs @@ -1,6 +1,6 @@ use std::mem::ManuallyDrop; use std::vec::Vec; - +pub use wasmedge_bindgen::*; // use externref::externref; // #[allow(unused_imports)] // use wasmedge_bindgen::*; @@ -14,6 +14,26 @@ extern "C" { fn kv_batch_res(ope_id: i32, args_ptr: *const i32, args_len: i32); fn open_file(fname: *const u8, fnamelen: i32, fd: &mut i32); fn read_file_at(fd: i32, buf: *const u8, buflen: i32, offset: i32, readlen: &mut i32); + pub fn write_result(res_ptr: *const u8, res_len: i32); +} + +pub trait KvResTrans { + fn res_str(&self) -> Option<&str>; +} + +impl KvResTrans for Vec { + fn res_str(&self) -> Option<&str> { + if let KvResult::Get(Some(s)) = &self[0] { + return std::str::from_utf8(s).map_or_else( + |err| { + println!("err when get kv res str:{}", err); + None + }, + |v| Some(v), + ); + } + None + } } // pub enum KvOpe { @@ -191,6 +211,7 @@ impl HostFile { Self { fd } } + // data will be append to `buf` until the file is read to the end or `buf` is full to capacity pub fn read_at(&self, offset: usize, buf: &mut Vec) -> usize { let mut readlen = 0; let buf_old_len = buf.len(); diff --git a/apps/fn2/Cargo.lock b/apps/fn2/Cargo.lock index 168a3d3..5dfae95 100644 --- a/apps/fn2/Cargo.lock +++ b/apps/fn2/Cargo.lock @@ -139,6 +139,9 @@ checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasm_serverless_lib" version = "0.1.0" +dependencies = [ + "wasmedge-bindgen", +] [[package]] name = "wasmedge-bindgen" diff --git a/apps/longchain/Cargo.lock b/apps/longchain/Cargo.lock index 08d410c..9f06687 100644 --- a/apps/longchain/Cargo.lock +++ b/apps/longchain/Cargo.lock @@ -140,6 +140,9 @@ checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasm_serverless_lib" version = "0.1.0" +dependencies = [ + "wasmedge-bindgen", +] [[package]] name = "wasmedge-bindgen" diff --git a/apps/panote_auth/Cargo.lock b/apps/panote_auth/Cargo.lock new file mode 100644 index 0000000..67a15d8 --- /dev/null +++ b/apps/panote_auth/Cargo.lock @@ -0,0 +1,568 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bumpalo" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonwebtoken" +version = "9.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" +dependencies = [ + "base64", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "panote_auth" +version = "0.1.0" +dependencies = [ + "chrono", + "jsonwebtoken", + "serde", + "serde_json", + "wasm-bindgen", + "wasm_serverless_lib", + "wasmedge-bindgen", + "wasmedge-bindgen-macro", + "wasmedge-wasi-helper", +] + +[[package]] +name = "pem" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +dependencies = [ + "base64", + "serde", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "serde_json" +version = "1.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.49", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + +[[package]] +name = "wasm_serverless_lib" +version = "0.1.0" +dependencies = [ + "wasmedge-bindgen", +] + +[[package]] +name = "wasmedge-bindgen" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "363e00c6f7c2fd162c36a97b3f352dd0ed690cde5c0d0a6d50524ef9c0fa7acd" + +[[package]] +name = "wasmedge-bindgen-macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fe812750bd02aac1b3b32f90f70442b58e802cb2b09454726619af359fdf33" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wasmedge-wasi-helper" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd351a86b66f511cbeab0cb848cc9dbd06b4165689c2f992a74500fb809b19dd" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/apps/panote_auth/Cargo.toml b/apps/panote_auth/Cargo.toml new file mode 100644 index 0000000..86f633c --- /dev/null +++ b/apps/panote_auth/Cargo.toml @@ -0,0 +1,21 @@ + + [package] + name = "panote_auth" + version = "0.1.0" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasmedge-bindgen = "0.4.1" + wasmedge-bindgen-macro = "0.4.1" + wasm-bindgen = "0.2.74" + wasm_serverless_lib = { path = "../_wasm_serverless_lib" } + wasmedge-wasi-helper = "=0.2.0" + serde = { version = "1.0", features = ["derive"] } + serde_json = "1.0" + chrono = "0.4.19" + jsonwebtoken = "9.2.0" + \ No newline at end of file diff --git a/apps/panote_auth/app.yaml b/apps/panote_auth/app.yaml new file mode 100644 index 0000000..f6c4d06 --- /dev/null +++ b/apps/panote_auth/app.yaml @@ -0,0 +1,11 @@ +fns: + login: + args: + - http_text: null + event: + - http_fn: null + verify_token: + args: + - http_text: null + event: + - http_fn: null diff --git a/apps/panote_auth/files/authority_config.json b/apps/panote_auth/files/authority_config.json new file mode 100644 index 0000000..88c4265 --- /dev/null +++ b/apps/panote_auth/files/authority_config.json @@ -0,0 +1,5 @@ +{ + "id":"test_id", + "pw":"test_pw", + "token_secret": "hello world" +} \ No newline at end of file diff --git a/apps/panote_auth/src/impl.rs b/apps/panote_auth/src/impl.rs new file mode 100644 index 0000000..68c8296 --- /dev/null +++ b/apps/panote_auth/src/impl.rs @@ -0,0 +1,37 @@ +use crate::r#struct::*; +use crate::*; + +use self::authority::AuthorityMan; + +mod authority; + +impl AuthApi for Impl { + fn login(&self, req: LoginReq) -> LoginResp { + let auth_man = AuthorityMan::new(); + if let Ok(_) = auth_man.check_id_and_pw(&*(req.id), &*(req.pw)) { + LoginResp { + if_success: 1, + token: auth_man.gen_token(), + } + } else { + LoginResp { + if_success: 0, + token: "".to_string(), + } + } + } + fn verify_token(&self, req: VerifyTokenReq) -> VerifyTokenResp { + let auth_man = AuthorityMan::new(); + if auth_man.check_token(req.token).is_ok() { + VerifyTokenResp { + if_success: 1, + new_token: auth_man.gen_token(), + } + } else { + VerifyTokenResp { + if_success: 0, + new_token: "".to_string(), + } + } + } +} diff --git a/apps/panote_auth/src/impl/authority.rs b/apps/panote_auth/src/impl/authority.rs new file mode 100644 index 0000000..b852789 --- /dev/null +++ b/apps/panote_auth/src/impl/authority.rs @@ -0,0 +1,132 @@ +use self::token::CheckTokenRes; +use serde::{Deserialize, Serialize}; +use wasm_serverless_lib::{HostFile, KvBatch, KvResult}; + +#[derive(Serialize, Deserialize, Default)] +pub struct AuthorityConfig { + pub id: String, + pub pw: String, + pub token_secret: String, +} + +mod token { + use chrono; + use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; + use serde::{Deserialize, Serialize}; + + use super::AuthorityMan; + + // Our claims struct, it needs to derive `Serialize` and/or `Deserialize` + #[derive(Debug, Serialize, Deserialize)] + struct Claims { + // connid:i32, + exp: u64, + } + + // lazy_static! { + // pub static ref TOKEN_SECRET: RwLock =RwLock::new( String::new()); + // // pub static ref TEST:Test=Test::new(); + // } + const EXPIRE_SEC: u64 = 60 * 60 * 24 * 15; //15 day + + //需要保证uid有效 + pub fn maketoken(auth_man: &AuthorityMan) -> String { + let secret = &auth_man.0.token_secret; + // 用于设置过期时间 + let second = chrono::Local::now().timestamp(); + + // 生成JWT,主要用于保存uid + // 用于加密的key是服务器配置的 + // todo : 安全性思考 + encode( + &Header::default(), + &Claims { + exp: second as u64 + EXPIRE_SEC, + }, + &EncodingKey::from_secret(secret.as_bytes()), + ) + .unwrap() + } + + pub enum CheckTokenRes { + FailParse, + Valid, + Expire, + } + + // 解析token + pub fn checktoken(token: String, secret: &str) -> CheckTokenRes { + // 解析用于验证的token + let token = decode::( + &token, + &DecodingKey::from_secret(secret.as_bytes()), + &Validation::default(), + ); + match token { + Ok(data) => { + let second = chrono::Local::now().timestamp() as u64; + + println!( + "{} {}", + serde_json::to_string(&data.claims).unwrap(), + second + ); + // 过期 + if second > data.claims.exp { + return CheckTokenRes::Expire; + } + CheckTokenRes::Valid + // Ch + } + Err(e) => { + // log::debug!("{}", e); + print!("error:{}", e); + + CheckTokenRes::FailParse + } + } + } +} + +const CONFIG_FILE_PATH: &'static str = "authority_config.json"; + +pub struct AuthorityMan(AuthorityConfig); +impl AuthorityMan { + pub fn new() -> Self { + // let res = KvBatch::new() + // .then_get("authority_config".as_bytes()) + // .finally_call(); + // let res = if let KvResult::Get(Some(res)) = &res[0] { + // serde_json::from_slice(&res).unwrap() + // } else + { + let mut vec = Vec::with_capacity(300); + HostFile::open(CONFIG_FILE_PATH).read_at(0, &mut vec); + let res = serde_json::from_slice(&vec).unwrap(); + // KvBatch::new() + // .then_set("authority_config".as_bytes(), &vec) + // .finally_call(); + + Self(res) + } + } + fn config(&self) -> &AuthorityConfig { + &self.0 + } + pub fn check_id_and_pw(&self, id: &str, pw: &str) -> Result<(), ()> { + let config = self.config(); + if config.pw == pw && config.id == id { + return Ok(()); + } + Err(()) + } + pub fn gen_token(&self) -> String { + token::maketoken(self) + } + pub fn check_token(&self, token: String) -> Result<(), ()> { + match token::checktoken(token, &self.0.token_secret) { + CheckTokenRes::Valid => Result::Ok(()), + _ => Result::Err(()), + } + } +} diff --git a/apps/panote_auth/src/lib.rs b/apps/panote_auth/src/lib.rs new file mode 100644 index 0000000..9157f64 --- /dev/null +++ b/apps/panote_auth/src/lib.rs @@ -0,0 +1,46 @@ +use serde_json; +use serde_json::Value; +use std::mem::ManuallyDrop; +use wasm_serverless_lib::*; +mod r#impl; +mod r#struct; +use r#struct::*; + +trait AuthApi { + fn login(&self, req: LoginReq) -> LoginResp; + fn verify_token(&self, req: VerifyTokenReq) -> VerifyTokenResp; +} + +pub struct Impl; + +#[no_mangle] +fn login(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { + String::from_raw_parts( + http_json_ptr as *mut u8, + http_json_len as usize, + http_json_len as usize, + ) + }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.login(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn verify_token(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { + String::from_raw_parts( + http_json_ptr as *mut u8, + http_json_len as usize, + http_json_len as usize, + ) + }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.verify_token(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } + println!("verify_token done"); +} diff --git a/apps/panote_auth/src/struct.rs b/apps/panote_auth/src/struct.rs new file mode 100644 index 0000000..c05ca89 --- /dev/null +++ b/apps/panote_auth/src/struct.rs @@ -0,0 +1,12 @@ +use serde::{Serialize, Deserialize}; +// Requests +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct LoginReq { pub id: String, pub pw: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct VerifyTokenReq { pub token: String } + +// Responses +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct LoginResp { pub if_success: i32, pub token: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct VerifyTokenResp { pub if_success: i32, pub new_token: String } diff --git a/apps/panote_content/Cargo.lock b/apps/panote_content/Cargo.lock new file mode 100644 index 0000000..747fef3 --- /dev/null +++ b/apps/panote_content/Cargo.lock @@ -0,0 +1,213 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bumpalo" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "panote_content" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", + "wasm-bindgen", + "wasm_serverless_lib", + "wasmedge-bindgen", + "wasmedge-bindgen-macro", + "wasmedge-wasi-helper", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "serde_json" +version = "1.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.49", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + +[[package]] +name = "wasm_serverless_lib" +version = "0.1.0" +dependencies = [ + "wasmedge-bindgen", +] + +[[package]] +name = "wasmedge-bindgen" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "363e00c6f7c2fd162c36a97b3f352dd0ed690cde5c0d0a6d50524ef9c0fa7acd" + +[[package]] +name = "wasmedge-bindgen-macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fe812750bd02aac1b3b32f90f70442b58e802cb2b09454726619af359fdf33" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wasmedge-wasi-helper" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd351a86b66f511cbeab0cb848cc9dbd06b4165689c2f992a74500fb809b19dd" diff --git a/apps/panote_content/Cargo.toml b/apps/panote_content/Cargo.toml new file mode 100644 index 0000000..bbbeb81 --- /dev/null +++ b/apps/panote_content/Cargo.toml @@ -0,0 +1,19 @@ + + [package] + name = "panote_content" + version = "0.1.0" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasmedge-bindgen = "0.4.1" + wasmedge-bindgen-macro = "0.4.1" + wasm-bindgen = "0.2.74" + wasm_serverless_lib = { path = "../_wasm_serverless_lib" } + wasmedge-wasi-helper = "=0.2.0" + serde = { version = "1.0", features = ["derive"] } + serde_json = "1.0" + \ No newline at end of file diff --git a/apps/panote_content/app.yaml b/apps/panote_content/app.yaml new file mode 100644 index 0000000..f9690c4 --- /dev/null +++ b/apps/panote_content/app.yaml @@ -0,0 +1,76 @@ +fns: + add_path: + args: + - http_text: null + event: + - http_fn: null + article_binder: + args: + - http_text: null + event: + - http_fn: null + article_list: + args: + - http_text: null + event: + - http_fn: null + create_new_bar: + args: + - http_text: null + event: + - http_fn: null + delete_bar: + args: + - http_text: null + event: + - http_fn: null + fetch_all_note_bars_epoch: + args: + - http_text: null + event: + - http_fn: null + get_chunk_note_ids: + args: + - http_text: null + event: + - http_fn: null + get_note_bar_info: + args: + - http_text: null + event: + - http_fn: null + get_note_mata: + args: + - http_text: null + event: + - http_fn: null + get_path_info: + args: + - http_text: null + event: + - http_fn: null + redo: + args: + - http_text: null + event: + - http_fn: null + remove_path: + args: + - http_text: null + event: + - http_fn: null + set_path_info: + args: + - http_text: null + event: + - http_fn: null + update_bar_content: + args: + - http_text: null + event: + - http_fn: null + update_bar_transform: + args: + - http_text: null + event: + - http_fn: null diff --git a/apps/panote_content/src/impl.rs b/apps/panote_content/src/impl.rs new file mode 100644 index 0000000..1ba2176 --- /dev/null +++ b/apps/panote_content/src/impl.rs @@ -0,0 +1,927 @@ +use crate::r#struct::*; +use crate::*; +use serde::{Deserialize, Serialize}; +use serde_json::Number; +use std::time::{SystemTime, UNIX_EPOCH}; + +#[derive(Serialize, Deserialize)] +struct ArticleListNode { + pub barid: String, + pub artname: String, +} +#[derive(Serialize, Deserialize, Default)] +struct ArticleList { + pub list: Vec, +} +impl ArticleList { + pub fn bind(&mut self, arg: ArticleBinderReq) -> bool { + for a in &self.list { + if a.barid == arg.barid { + //文章已绑定 + self.rename(arg); + return true; + } + } + self.list.push(ArticleListNode { + barid: arg.barid, + artname: arg.article_name, + }); + true + } + pub fn unbind(&mut self, arg: ArticleBinderReq) -> bool { + let oldsz = self.list.len(); + self.list.retain(|v| v.barid != arg.article_name); + oldsz != self.list.len() + } + pub fn rename(&mut self, mut arg: ArticleBinderReq) -> bool { + for a in &mut self.list { + if a.barid == arg.barid { + std::mem::swap(&mut a.artname, &mut arg.article_name); + return true; + } + } + return false; + } +} + +#[derive(Serialize, Deserialize)] +struct PathInfo { + pathtype: i32, +} + +#[derive(Serialize, Deserialize)] +pub struct NoteBarInfo { + pub x: f32, + pub y: f32, + pub w: f32, + pub h: f32, + pub text: String, + pub formatted: String, + pub connected: Vec, + pub edit_time: Option, + pub create_time: Option, + pub epoch: Option, +} +impl NoteBarInfo { + pub fn epoch_i32(&self) -> i32 { + self.epoch.unwrap() as i32 + } + pub fn epoch_addup(&mut self) { + if self.epoch.unwrap() == i32::MAX as u64 { + self.epoch.replace(0); + } else { + let old = self.epoch.unwrap(); + self.epoch.replace(old + 1); + } + } + pub fn fix_old(&mut self) { + if self.epoch.is_none() { + self.epoch = Some(0); + } + } + pub fn update_edit_time(&mut self) { + self.edit_time = Some(time_stamp_ms_u64()); + } + pub fn to_reply(self) -> GetNoteBarInfoResp { + GetNoteBarInfoResp { + x: self.x, + y: self.y, + w: self.w, + h: self.h, + text: self.text, + formatted: self.formatted, + connected: self.connected, + epoch: self.epoch.unwrap() as i32, + } + } + pub fn remove_path(&mut self, pathid: &str) { + self.connected.retain(|s| s.as_str().unwrap() != pathid) + } +} + +const CHUNK_W: i32 = 300; +const CHUNK_H: i32 = 400; + +pub fn time_stamp_ms_u64() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64 +} + +fn chunkpos_to_chunkid(x: i32, y: i32) -> String { + format!("{}_{}", x, y) +} + +fn note_pos_to_chunkpos(x: f32, y: f32) -> (i32, i32) { + ( + if x > 0.0 { + x as i32 / CHUNK_W + } else { + x as i32 / CHUNK_W - 1 + }, + if y > 0.0 { + y as i32 / CHUNK_H + } else { + y as i32 / CHUNK_H - 1 + }, + ) +} + +fn fitup_chunk_range_in_notemeta_for_newck( + ckx: i32, + cky: i32, + meta_: &mut GetNoteMataResp, +) -> bool { + let mut changed = false; + if meta_.max_chunkx < ckx { + meta_.max_chunkx = ckx; + changed = true; + } else if meta_.min_chunkx > ckx { + meta_.min_chunkx = ckx; + changed = true; + } + if meta_.max_chunky < cky { + meta_.max_chunky = cky; + changed = true; + } else if meta_.min_chunky > cky { + meta_.min_chunky = cky; + changed = true; + } + + changed +} + +struct NoteMan {} +impl NoteMan { + fn new() -> Self { + Self {} + } + + pub fn fitdown_chunk_range_in_notemeta_if_ck_is_on_edge( + &self, + noteid: &str, + ckx: i32, + cky: i32, + meta_: &mut GetNoteMataResp, + ) -> bool { + fn y_empty(man: &NoteMan, x: i32, meta_: &GetNoteMataResp, noteid: &str) -> bool { + let mut line_empty = true; + for y in meta_.min_chunky..meta_.max_chunky + 1 { + if man + .get_note_chunk_ids(GetChunkNoteIdsReq { + noteid: noteid.to_string(), + chunkx: x, + chunky: y, + }) + .noteids + .len() + != 0 + { + //如果有非空的chunk + line_empty = false; + break; + } + } + line_empty + }; + fn x_empty(man: &NoteMan, y: i32, meta_: &GetNoteMataResp, noteid: &str) -> bool { + let mut line_empty = true; + for x in meta_.min_chunkx..meta_.max_chunkx + 1 { + if man + .get_note_chunk_ids(GetChunkNoteIdsReq { + noteid: noteid.to_string(), + chunkx: x, + chunky: y, + }) + .noteids + .len() + != 0 + { + //如果有非空的chunk + line_empty = false; + break; + } + } + line_empty + }; + let mut changed = false; + if ckx == meta_.max_chunkx { + let mut new_max_chunkx = meta_.max_chunkx; + //从大到小压缩 + for x in (1..meta_.max_chunkx + 1).rev() { + if y_empty(self, x, meta_, noteid) { + new_max_chunkx = x - 1; + } else { + break; + } + } + if meta_.max_chunkx != new_max_chunkx { + changed = true; + } + meta_.max_chunkx = new_max_chunkx; + } else if ckx == meta_.min_chunkx { + let mut new_min_chunkx = meta_.min_chunkx; + //从xiao到大压缩 + for x in meta_.min_chunkx..0 { + if y_empty(self, x, meta_, noteid) { + new_min_chunkx = x + 1; + } else { + break; + } + } + if meta_.min_chunkx != new_min_chunkx { + changed = true + } + meta_.min_chunkx = new_min_chunkx; + } + if cky == meta_.max_chunky { + let mut new_max_chunky = meta_.max_chunky; + //从大到小压缩 + for y in (1..meta_.max_chunky + 1).rev() { + if x_empty(self, y, meta_, noteid) { + new_max_chunky = y - 1; + } else { + break; + } + } + if meta_.max_chunky != new_max_chunky { + changed = true; + } + meta_.max_chunky = new_max_chunky; + } else if cky == meta_.min_chunky { + let mut new_min_chunky = meta_.min_chunky; + //从xiao到大压缩 + for y in meta_.min_chunky..0 { + if x_empty(self, y, meta_, noteid) { + new_min_chunky = y + 1; + } else { + break; + } + } + if meta_.min_chunky != new_min_chunky { + changed = true; + } + meta_.min_chunky = new_min_chunky; + } + changed + } + + pub fn set_note_meta(&self, noteid: &str, meta: &GetNoteMataResp) { + // self.kernel.set( + // format!("{}|meta", noteid), + // serde_json::to_string(meta).unwrap(), + // ); + KvBatch::new() + .then_set( + format!("{}|meta", noteid).as_bytes(), + serde_json::to_string(meta).unwrap().as_bytes(), + ) + .finally_call(); + } + fn get_note_meta(&self, noteid: &str) -> GetNoteMataResp { + let s = KvBatch::new() + .then_get(format!("{}|meta", noteid).as_bytes()) + .finally_call(); + let s = s.res_str(); + match s { + None => { + let ret = GetNoteMataResp { + next_noteid: 0, + max_chunkx: 0, + max_chunky: 0, + min_chunkx: 0, + min_chunky: 0, + }; + KvBatch::new() + .then_set( + format!("{}|meta", noteid).as_bytes(), + serde_json::to_string(&ret).unwrap().as_bytes(), + ) + .finally_call(); + ret + } + Some(s) => serde_json::from_str::(&s).unwrap(), + } + } + + fn get_note_chunk_ids(&self, arg: GetChunkNoteIdsReq) -> GetChunkNoteIdsResp { + // let chunkid = chunkpos_to_chunkid(arg.chunkx, arg.chunky); + // {//try read from mem + // let mut hold = self.locked_data.write(); + // let noteinfo = hold.get_note_info(connid, &*arg.noteid); + // if let Some(v) = noteinfo.get_chunk_noteids(&*chunkid) { + // return GetChunkNoteIdsReply { + // noteids: v.collect_vec_value() + // }; + // } + // } + + //mem no, load from kv + let key = format!("{}|chunk|{}|{}", arg.noteid, arg.chunkx, arg.chunky); + let s = KvBatch::new().then_get(key.as_bytes()).finally_call(); + let s = s.res_str(); + let kvres = match s { + None => { + let ret = GetChunkNoteIdsResp { + noteids: Vec::new(), + }; + // self.kernel.set(key, serde_json::to_string(&ret).unwrap()); + KvBatch::new() + .then_set( + key.as_bytes(), + serde_json::to_string(&ret).unwrap().as_bytes(), + ) + .finally_call(); + ret + } + Some(s) => serde_json::from_str::(&s).unwrap(), + }; + // //save to mem store + // { + // let mut hold = self.locked_data.write(); + // let noteinfo = hold.get_note_info(connid, &*arg.noteid); + // noteinfo.set_chunk_noteids(&*chunkid, kvres.noteids.clone()); + // } + return kvres; + } + pub fn set_note_chunk_ids( + &self, + // connid: i32, + noteid: &str, + cx: i32, + cy: i32, + ids: &GetChunkNoteIdsResp, + ) { + let chunkid = chunkpos_to_chunkid(cx, cy); + // { + // //mem + // let mut hold = self.locked_data.write(); + // let noteinfo = hold.get_note_info(connid, noteid); + // noteinfo.set_chunk_noteids(&*chunkid, ids.noteids.clone()); + // } + //kv + let key = format!("{}|chunk|{}|{}", noteid, cx, cy); + // self.kernel.set(key, serde_json::to_string(ids).unwrap()); + KvBatch::new() + .then_set( + key.as_bytes(), + serde_json::to_string(ids).unwrap().as_bytes(), + ) + .finally_call(); + } + //变化完后需要检查是否发生收缩, + // return 区块范围 + pub fn change_notebar_chunk( + &self, + noteid: &str, + barid: &str, + ck1: (i32, i32), + ck2: (i32, i32), + ) -> GetNoteMataResp { + //改变两个chunk中的noteids + //chunk1中移除 + let mut ck1data = self.get_note_chunk_ids(GetChunkNoteIdsReq { + noteid: noteid.to_string(), + chunkx: ck1.0, + chunky: ck1.1, + }); + let mut found = ck1data.noteids.len(); + for i in 0..ck1data.noteids.len() { + if ck1data.noteids[i] == barid { + found = i + } + } + ck1data.noteids.remove(found); + + //chunk2中放入 + let mut ck2data = self.get_note_chunk_ids(GetChunkNoteIdsReq { + noteid: noteid.to_string(), + chunkx: ck2.0, + chunky: ck2.1, + }); + ck2data + .noteids + .push(serde_json::Value::String(barid.to_string())); + self.set_note_chunk_ids(noteid, ck1.0, ck1.1, &ck1data); + self.set_note_chunk_ids(noteid, ck2.0, ck2.1, &ck2data); + + let mut meta = self.get_note_meta(noteid); + let mut range_changed = fitup_chunk_range_in_notemeta_for_newck(ck2.0, ck2.1, &mut meta); + range_changed = self + .fitdown_chunk_range_in_notemeta_if_ck_is_on_edge(noteid, ck1.0, ck1.1, &mut meta) + || range_changed; + if range_changed { + self.set_note_meta(noteid, &meta); + } + meta + } + pub fn set_notebar_info(&self, noteid: &str, barid: &str, newinfo: &NoteBarInfo) { + let key = format!("{}|bar|{}", noteid, barid); + // println!("get_notebar_info {}",key); + KvBatch::new() + .then_set( + key.as_bytes(), + serde_json::to_string(newinfo).unwrap().as_bytes(), + ) + .finally_call(); + } + pub fn get_notebar_info(&self, noteid: String, barid: String) -> Option { + let key = format!("{}|bar|{}", noteid, barid); + println!("get_notebar_info {}", key); + let s = KvBatch::new().then_get(key.as_bytes()).finally_call(); + let s = s.res_str(); + //create if not exist + match s { + None => None, + Some(s) => { + let mut fix = serde_json::from_str::(&s).unwrap(); + fix.fix_old(); + Some(fix) + } + } + } + pub fn create_notebar( + &self, + x: f32, + y: f32, + noteid: String, + ) -> (GetNoteBarInfoResp, (i32, i32)) { + //1.读取元数据 + let mut meta = self.get_note_meta(&*noteid); + let next = meta.next_noteid; + meta.next_noteid += 1; + let ret = { + //notebar 信息 + let time = time_stamp_ms_u64(); + let ret = NoteBarInfo { + x, + y, + w: 150.0, + h: 150.0, + text: "".to_string(), + formatted: "".to_string(), + connected: vec![], + edit_time: Some(time), + create_time: Some(time), + epoch: Some(0), + }; //保存笔记信息 + let key = format!("{}|bar|{}", noteid, next); + KvBatch::new() + .then_set( + key.as_bytes(), + serde_json::to_string(&ret).unwrap().as_bytes(), + ) + .finally_call(); + ret.to_reply() + }; + + let (cx, cy) = note_pos_to_chunkpos(x, y); + { + // chunk ids 信息 + let mut chunk_noteids = self.get_note_chunk_ids(GetChunkNoteIdsReq { + noteid: noteid.clone(), + chunkx: cx, + chunky: cy, + }); + chunk_noteids.noteids.push(Value::String(next.to_string())); + self.set_note_chunk_ids(¬eid, cx, cy, &chunk_noteids); + } + + //meta fit 一下chunk + fitup_chunk_range_in_notemeta_for_newck(cx, cy, &mut meta); + self.set_note_meta(&*noteid, &meta); + + (ret, (cx, cy)) + } + pub fn delete_bar(&self, noteid: &str, ebid: &str) -> GetNoteMataResp { + let mut meta = self.get_note_meta(noteid); + if let Some(mut n1) = self.get_notebar_info(noteid.to_string(), ebid.to_string()) { + let (cx, cy) = note_pos_to_chunkpos(n1.x, n1.y); + let mut ck = self.get_note_chunk_ids(GetChunkNoteIdsReq { + noteid: noteid.to_string(), + chunkx: cx, + chunky: cy, + }); + //1.chunk 移除 bar + ck.noteids.retain(|v| v.as_str().unwrap() != ebid); + self.set_note_chunk_ids(noteid, cx, cy, &ck); + //2.相连bar 移除 + for v in &n1.connected { + let mut sp = v.as_str().unwrap().split("_"); + let mut a = sp.next().unwrap().to_string(); + let mut b = sp.next().unwrap().to_string(); + if b == ebid { + std::mem::swap(&mut a, &mut b); + } + let mut notebar = self + .get_notebar_info(noteid.to_string(), b.clone()) + .unwrap(); + notebar + .connected + .retain(|v1| v1.as_str().unwrap() != v.as_str().unwrap()); + self.set_notebar_info(noteid, &*b, ¬ebar); + self.remove_note_path_info(noteid, v.as_str().unwrap()); + } + + if self.fitdown_chunk_range_in_notemeta_if_ck_is_on_edge(noteid, cx, cy, &mut meta) { + self.set_note_meta(noteid, &meta); + } + } else { + eprintln!("error, delete bar ebid not found") + } + + meta + } + pub fn add_path(&self, noteid: &str, ebid1: &str, ebid2: &str) -> Option<(i32, i32)> { + if let (Some(mut n1), Some(mut n2)) = ( + self.get_notebar_info(noteid.to_string(), ebid1.to_string()), + self.get_notebar_info(noteid.to_string(), ebid2.to_string()), + ) { + // todo + // 检查是否已经有path + n1.connected + .push(Value::String(format!("{}_{}", ebid1, ebid2))); + n2.connected + .push(Value::String(format!("{}_{}", ebid1, ebid2))); + n1.epoch_addup(); + n2.epoch_addup(); + self.set_notebar_info(noteid, ebid1, &n1); + self.set_notebar_info(noteid, ebid2, &n2); + let ret = Some((n1.epoch_i32(), n2.epoch_i32())); + self.set_note_path_info( + noteid, + &*format!("{}_{}", ebid1, ebid2), + &PathInfo { pathtype: 0 }, + ); + // let v1=Value::String() + // n1.connected.binary_search(&) + ret + } else { + eprintln!("error, add path ebid not found"); + None + } + } + fn get_note_path_info(&self, noteid: &str, pathid: &str) -> Option { + let key = format!("{}|path|{}", noteid, pathid); + let s = KvBatch::new().then_get(key.as_bytes()).finally_call(); + let s = s.res_str(); + match s { + None => None, + Some(s) => Some(serde_json::from_str(&*s).unwrap()), + } + } + fn set_note_path_info(&self, noteid: &str, pathid: &str, info: &PathInfo) { + let key = format!("{}|path|{}", noteid, pathid); + // self.kernel.set(key, serde_json::to_string(info).unwrap()); + KvBatch::new() + .then_set( + key.as_bytes(), + serde_json::to_string(info).unwrap().as_bytes(), + ) + .finally_call(); + } + pub fn remove_note_path_info(&self, noteid: &str, pathid: &str) { + let key = format!("{}|path|{}", noteid, pathid); + // self.kernel.del(key); + KvBatch::new().then_delete(key.as_bytes()).finally_call(); + } + + fn get_article_list(&self, noteid: &str) -> ArticleList { + let key = format!("{}|articlelist", noteid); + match KvBatch::new() + .then_get(key.as_bytes()) + .finally_call() + .res_str() + { + // match self.kernel.get(key.clone()) { + None => { + // let store=ArticleList::default() + println!("no article list stored"); + // self.kernel.set(key, "{\"list\":[]}".to_string()); + KvBatch::new() + .then_set(key.as_bytes(), "{\"list\":[]}".as_bytes()) + .finally_call(); + ArticleList::default() + } + Some(serial) => { + println!("get_article_list {}", serial); + match serde_json::from_str::(&*serial) { + Ok(v) => v, + Err(e) => { + // self.kernel.set(key, "{\"list\":[]}".to_string()); + KvBatch::new() + .then_set(key.as_bytes(), "{\"list\":[]}".as_bytes()) + .finally_call(); + panic!("unserial article list failed {}", serial); + } + } + } + } + } + fn set_article_list(&self, noteid: &str, article_list: &ArticleList) { + let key = format!("{}|articlelist", noteid); + // self.kernel + // .set(key.clone(), serde_json::to_string(article_list).unwrap()); + // println!("set article list {}", self.kernel.get(key).unwrap()); + } + pub fn article_binder(&self, mut arg: ArticleBinderReq) -> ArticleBinderResp { + let mut task_type = String::new(); + let mut noteid = String::new(); + std::mem::swap(&mut noteid, &mut arg.noteid); + std::mem::swap(&mut task_type, &mut arg.bind_unbind_rename); + let mut al = self.get_article_list(&*noteid); + match &*task_type { + "bind" => { + let ret = ArticleBinderResp { + if_success: if al.bind(arg) { 1 } else { 0 }, + }; + self.set_article_list(&*noteid, &al); + ret + } + "unbind" => { + let ret = ArticleBinderResp { + if_success: if al.unbind(arg) { 1 } else { 0 }, + }; + self.set_article_list(¬eid, &al); + ret + } + "rename" => { + let ret = ArticleBinderResp { + if_success: if al.rename(arg) { 1 } else { 0 }, + }; + self.set_article_list(¬eid, &al); + ret + } + _ => { + eprintln!("unreachable task type {}", task_type); + unreachable!() + } + } + } +} + +impl ContentApi for Impl { + fn get_note_mata(&self, req: GetNoteMataReq) -> GetNoteMataResp { + NoteMan::new().get_note_meta(&req.noteid) + } + fn get_chunk_note_ids(&self, req: GetChunkNoteIdsReq) -> GetChunkNoteIdsResp { + NoteMan::new().get_note_chunk_ids(req) + } + fn get_note_bar_info(&self, req: GetNoteBarInfoReq) -> GetNoteBarInfoResp { + let info = NoteMan::new().get_notebar_info(req.noteid, req.notebarid); + if let Some(info) = info { + info.to_reply() + } else { + GetNoteBarInfoResp { + w: -1.0, + h: -1.0, + ..GetNoteBarInfoResp::default() + } + } + } + fn create_new_bar(&self, arg: CreateNewBarReq) -> CreateNewBarResp { + let note_man = NoteMan::new(); + let (_created, (cx, cy)) = note_man.create_notebar(arg.x, arg.y, arg.noteid.clone()); + let ck_noteids = note_man.get_note_chunk_ids(GetChunkNoteIdsReq { + noteid: arg.noteid, + chunkx: cx, + chunky: cy, + }); + CreateNewBarResp { + chunkx: cx, + chunky: cy, + noteids: ck_noteids.noteids, + } + } + fn update_bar_content(&self, arg: UpdateBarContentReq) -> UpdateBarContentResp { + let note_man = NoteMan::new(); + let mut nb = note_man + .get_notebar_info(arg.noteid.clone(), arg.barid.clone()) + .unwrap(); + nb.formatted = arg.formatted; + nb.text = arg.text; + nb.update_edit_time(); + nb.epoch_addup(); + note_man.set_notebar_info(&*(arg.noteid), &*(arg.barid), &nb); + + UpdateBarContentResp { + new_epoch: nb.epoch_i32(), + } + } + fn update_bar_transform(&self, arg: UpdateBarTransformReq) -> UpdateBarTransformResp { + let note_man = NoteMan::new(); + let mut nb = note_man + .get_notebar_info(arg.noteid.clone(), arg.barid.clone()) + .unwrap(); + let (oldcx, oldcy) = note_pos_to_chunkpos(nb.x, nb.y); + let (newcx, newcy) = note_pos_to_chunkpos(arg.x, arg.y); + let (chunk_change, meta) = if oldcx != newcx || oldcy != newcy { + let meta = note_man.change_notebar_chunk( + &*(arg.noteid), + &*(arg.barid), + (oldcx, oldcy), + (newcx, newcy), + ); //变更区块下的信息 + ( + vec![ + Value::String(chunkpos_to_chunkid(oldcx, oldcy)), + Value::String(chunkpos_to_chunkid(newcx, newcy)), + ], + meta, + ) + } else { + (vec![], note_man.get_note_meta(&*arg.noteid)) + }; + nb.x = arg.x; + nb.y = arg.y; + nb.w = arg.w; + nb.h = arg.h; + nb.epoch_addup(); + note_man.set_notebar_info(&*(arg.noteid), &*(arg.barid), &nb); + UpdateBarTransformResp { + new_epoch: nb.epoch_i32(), + chunk_maxx: meta.max_chunkx, + chunk_minx: meta.min_chunkx, + chunk_maxy: meta.max_chunky, + chunk_miny: meta.min_chunky, + chunk_change, + } + } + fn redo(&self, req: RedoReq) -> RedoResp { + RedoResp::default() + } + fn add_path(&self, arg: AddPathReq) -> AddPathResp { + let note_man = NoteMan::new(); + let res = note_man.add_path(&*(arg.noteid), &*(arg.from), &*(arg.to)); + + if let Some((from_epoch, to_epoch)) = res { + AddPathResp { + _1succ_0fail: 1, + new_epoch_from: from_epoch, + new_epoch_to: to_epoch, + } + } else { + AddPathResp { + _1succ_0fail: 0, + new_epoch_from: 0, + new_epoch_to: 0, + } + } + } + fn get_path_info(&self, arg: GetPathInfoReq) -> GetPathInfoResp { + let note_man = NoteMan::new(); + let info = note_man + .get_note_path_info(&*(arg.noteid), &*(arg.pathid_with_line)) + .unwrap(); + GetPathInfoResp { + type_: info.pathtype, + } + } + fn set_path_info(&self, arg: SetPathInfoReq) -> SetPathInfoResp { + let note_man = NoteMan::new(); + note_man.set_note_path_info( + &*(arg.noteid), + &*(arg.pathid_with_line), + &PathInfo { + pathtype: arg.type_, + }, + ); + SetPathInfoResp::default() + } + fn remove_path(&self, arg: RemovePathReq) -> RemovePathResp { + let note_man = NoteMan::new(); + // 对应editor bar 中的信息变更 + let mut split = arg.pathid_with_line.split("_"); + let a = split.next().unwrap().to_string(); + let b = split.next().unwrap().to_string(); + let mut ainfo = note_man + .get_notebar_info(arg.noteid.clone(), a.clone()) + .unwrap(); + ainfo.remove_path(&*(arg.pathid_with_line)); + ainfo.epoch_addup(); + note_man.set_notebar_info(&*(arg.noteid), &*a, &ainfo); + let mut binfo = note_man + .get_notebar_info(arg.noteid.clone(), b.clone()) + .unwrap(); + binfo.remove_path(&*(arg.pathid_with_line)); + binfo.epoch_addup(); + note_man.set_notebar_info(&*(arg.noteid), &*b, &binfo); + // 移除path + note_man.remove_note_path_info(&*(arg.noteid), &*(arg.pathid_with_line)); + + RemovePathResp { + new_epoch_to: binfo.epoch.unwrap() as i32, + new_epoch_from: ainfo.epoch.unwrap() as i32, + } + } + fn delete_bar(&self, arg: DeleteBarReq) -> DeleteBarResp { + let note_man = NoteMan::new(); + let meta = note_man.delete_bar(&*(arg.noteid), &*(arg.barid)); + DeleteBarResp { + chunk_maxx: meta.max_chunkx, + chunk_minx: meta.min_chunkx, + chunk_maxy: meta.max_chunky, + chunk_miny: meta.min_chunky, + } + } + fn article_binder(&self, req: ArticleBinderReq) -> ArticleBinderResp { + NoteMan::new().article_binder(req) + } + fn article_list(&self, mut arg: ArticleListReq) -> ArticleListResp { + let note_man = NoteMan::new(); + + let mut noteid = String::new(); + std::mem::swap(&mut noteid, &mut arg.noteid); + let al = note_man.get_article_list(&*noteid); + let mut collect_noteinfos:Vec//barid-time-article + =Vec::new(); + for a in al.list { + let bar = note_man.get_notebar_info(noteid.clone(), a.barid.clone()); + if let Some(mut bar_info) = bar { + if let Some(time) = bar_info.edit_time { + let mut map = serde_json::Map::new(); + map.insert("barid".to_string(), Value::from(a.barid)); + map.insert("artname".to_string(), Value::from(a.artname)); + map.insert("edittime".to_string(), Value::from(time)); + collect_noteinfos.push(Value::Object(map)); + } else { + // eprintln!("articlelist collecting bar no edit time"); + let time = time_stamp_ms_u64(); + bar_info.edit_time = Some(time); + note_man.set_notebar_info(&*noteid, &*a.barid, &bar_info); + + let mut map = serde_json::Map::new(); + map.insert("barid".to_string(), Value::from(a.barid)); + map.insert("artname".to_string(), Value::from(a.artname)); + map.insert("edittime".to_string(), Value::from(time)); + collect_noteinfos.push(Value::Object(map)); + } + } else { + eprintln!("articlelist collecting bar not found;") + } + } + collect_noteinfos.sort_by(|v2, v1| { + v1.as_object() + .unwrap() + .get("edittime") + .unwrap() + .as_u64() + .unwrap() + .cmp( + &v2.as_object() + .unwrap() + .get("edittime") + .unwrap() + .as_u64() + .unwrap(), + ) + }); + + println!("artile list collected {}", collect_noteinfos.len()); + + ArticleListResp { + if_success: 1, + list: collect_noteinfos, + } + } + fn fetch_all_note_bars_epoch( + &self, + arg: FetchAllNoteBarsEpochReq, + ) -> FetchAllNoteBarsEpochResp { + let note_man = NoteMan::new(); + + let note_meta = note_man.get_note_meta(arg.noteid.as_str()); + let mut res = vec![]; + for x in note_meta.min_chunkx..note_meta.max_chunkx + 1 { + for y in note_meta.min_chunky..note_meta.max_chunky + 1 { + let ids = note_man.get_note_chunk_ids(GetChunkNoteIdsReq { + noteid: arg.noteid.clone(), + chunkx: x, + chunky: y, + }); + fn get_chunk_note_ids_reply_to_noteids_strvec( + mut reply: GetChunkNoteIdsResp, + ) -> Vec { + let mut res = vec![]; + while let Some(noteid) = reply.noteids.pop() { + res.push(noteid.as_str().unwrap().to_owned()); + } + res + } + let mut notes = get_chunk_note_ids_reply_to_noteids_strvec(ids); + while let Some(noteid) = notes.pop() { + let mut onepair = vec![]; + onepair.reserve(2); + let info = note_man.get_notebar_info(arg.noteid.clone(), noteid.clone()); + onepair.push(Value::String(noteid)); + onepair.push(Value::Number(Number::from(info.unwrap().epoch.unwrap()))); + res.push(Value::Array(onepair)); + } + } + } + FetchAllNoteBarsEpochResp { + bars_id_and_epoch: res, + } + } +} diff --git a/apps/panote_content/src/lib.rs b/apps/panote_content/src/lib.rs new file mode 100644 index 0000000..48920a6 --- /dev/null +++ b/apps/panote_content/src/lib.rs @@ -0,0 +1,163 @@ +use serde_json; +use serde_json::Value; +use std::mem::ManuallyDrop; +use wasm_serverless_lib::*; +mod r#struct; +mod r#impl; +use r#struct::*; + +trait ContentApi { +fn get_note_mata(&self,req: GetNoteMataReq) -> GetNoteMataResp; +fn get_chunk_note_ids(&self,req: GetChunkNoteIdsReq) -> GetChunkNoteIdsResp; +fn get_note_bar_info(&self,req: GetNoteBarInfoReq) -> GetNoteBarInfoResp; +fn create_new_bar(&self,req: CreateNewBarReq) -> CreateNewBarResp; +fn update_bar_content(&self,req: UpdateBarContentReq) -> UpdateBarContentResp; +fn update_bar_transform(&self,req: UpdateBarTransformReq) -> UpdateBarTransformResp; +fn redo(&self,req: RedoReq) -> RedoResp; +fn add_path(&self,req: AddPathReq) -> AddPathResp; +fn get_path_info(&self,req: GetPathInfoReq) -> GetPathInfoResp; +fn set_path_info(&self,req: SetPathInfoReq) -> SetPathInfoResp; +fn remove_path(&self,req: RemovePathReq) -> RemovePathResp; +fn delete_bar(&self,req: DeleteBarReq) -> DeleteBarResp; +fn article_binder(&self,req: ArticleBinderReq) -> ArticleBinderResp; +fn article_list(&self,req: ArticleListReq) -> ArticleListResp; +fn fetch_all_note_bars_epoch(&self,req: FetchAllNoteBarsEpochReq) -> FetchAllNoteBarsEpochResp; +} + +pub struct Impl; + +#[no_mangle] +fn get_note_mata(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.get_note_mata(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn get_chunk_note_ids(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.get_chunk_note_ids(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn get_note_bar_info(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.get_note_bar_info(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn create_new_bar(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.create_new_bar(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn update_bar_content(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.update_bar_content(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn update_bar_transform(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.update_bar_transform(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn redo(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.redo(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn add_path(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.add_path(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn get_path_info(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.get_path_info(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn set_path_info(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.set_path_info(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn remove_path(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.remove_path(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn delete_bar(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.delete_bar(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn article_binder(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.article_binder(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn article_list(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.article_list(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn fetch_all_note_bars_epoch(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.fetch_all_note_bars_epoch(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} diff --git a/apps/panote_content/src/struct.rs b/apps/panote_content/src/struct.rs new file mode 100644 index 0000000..82311f9 --- /dev/null +++ b/apps/panote_content/src/struct.rs @@ -0,0 +1,64 @@ +use serde::{Serialize, Deserialize}; +// Requests +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetNoteMataReq { pub noteid: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetChunkNoteIdsReq { pub noteid: String, pub chunkx: i32, pub chunky: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetNoteBarInfoReq { pub noteid: String, pub notebarid: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct CreateNewBarReq { pub noteid: String, pub x: f32, pub y: f32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct UpdateBarContentReq { pub noteid: String, pub barid: String, pub text: String, pub formatted: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct UpdateBarTransformReq { pub noteid: String, pub barid: String, pub x: f32, pub y: f32, pub w: f32, pub h: f32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct RedoReq { pub noteid: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct AddPathReq { pub noteid: String, pub from: String, pub to: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetPathInfoReq { pub noteid: String, pub pathid_with_line: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct SetPathInfoReq { pub noteid: String, pub pathid_with_line: String, pub type_: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct RemovePathReq { pub noteid: String, pub pathid_with_line: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct DeleteBarReq { pub noteid: String, pub barid: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct ArticleBinderReq { pub bind_unbind_rename: String, pub article_name: String, pub barid: String, pub noteid: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct ArticleListReq { pub noteid: String } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct FetchAllNoteBarsEpochReq { pub noteid: String } + +// Responses +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetNoteMataResp { pub next_noteid: i32, pub max_chunkx: i32, pub max_chunky: i32, pub min_chunkx: i32, pub min_chunky: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetChunkNoteIdsResp { pub noteids: Vec } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetNoteBarInfoResp { pub x: f32, pub y: f32, pub w: f32, pub h: f32, pub text: String, pub formatted: String, pub connected: Vec, pub epoch: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct CreateNewBarResp { pub chunkx: i32, pub chunky: i32, pub noteids: Vec } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct UpdateBarContentResp { pub new_epoch: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct UpdateBarTransformResp { pub new_epoch: i32, pub chunk_maxx: i32, pub chunk_minx: i32, pub chunk_maxy: i32, pub chunk_miny: i32, pub chunk_change: Vec } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct RedoResp { pub redotype: String, pub redovalue: serde_json::Value } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct AddPathResp { pub _1succ_0fail: i32, pub new_epoch_from: i32, pub new_epoch_to: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetPathInfoResp { pub type_: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct SetPathInfoResp { } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct RemovePathResp { pub new_epoch_from: i32, pub new_epoch_to: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct DeleteBarResp { pub chunk_maxx: i32, pub chunk_minx: i32, pub chunk_maxy: i32, pub chunk_miny: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct ArticleBinderResp { pub if_success: i32 } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct ArticleListResp { pub if_success: i32, pub list: Vec } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct FetchAllNoteBarsEpochResp { pub bars_id_and_epoch: Vec } diff --git a/apps/panote_list/Cargo.lock b/apps/panote_list/Cargo.lock new file mode 100644 index 0000000..f12ff49 --- /dev/null +++ b/apps/panote_list/Cargo.lock @@ -0,0 +1,213 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bumpalo" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "panote_list" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", + "wasm-bindgen", + "wasm_serverless_lib", + "wasmedge-bindgen", + "wasmedge-bindgen-macro", + "wasmedge-wasi-helper", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "serde_json" +version = "1.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.49", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + +[[package]] +name = "wasm_serverless_lib" +version = "0.1.0" +dependencies = [ + "wasmedge-bindgen", +] + +[[package]] +name = "wasmedge-bindgen" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "363e00c6f7c2fd162c36a97b3f352dd0ed690cde5c0d0a6d50524ef9c0fa7acd" + +[[package]] +name = "wasmedge-bindgen-macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fe812750bd02aac1b3b32f90f70442b58e802cb2b09454726619af359fdf33" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wasmedge-wasi-helper" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd351a86b66f511cbeab0cb848cc9dbd06b4165689c2f992a74500fb809b19dd" diff --git a/apps/panote_list/Cargo.toml b/apps/panote_list/Cargo.toml new file mode 100644 index 0000000..b487194 --- /dev/null +++ b/apps/panote_list/Cargo.toml @@ -0,0 +1,19 @@ + + [package] + name = "panote_list" + version = "0.1.0" + edition = "2021" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasmedge-bindgen = "0.4.1" + wasmedge-bindgen-macro = "0.4.1" + wasm-bindgen = "0.2.74" + wasm_serverless_lib = { path = "../_wasm_serverless_lib" } + wasmedge-wasi-helper = "=0.2.0" + serde = { version = "1.0", features = ["derive"] } + serde_json = "1.0" + \ No newline at end of file diff --git a/apps/panote_list/app.yaml b/apps/panote_list/app.yaml new file mode 100644 index 0000000..3e006b4 --- /dev/null +++ b/apps/panote_list/app.yaml @@ -0,0 +1,16 @@ +fns: + create_new_note: + args: + - http_text: null + event: + - http_fn: null + get_notes_mata: + args: + - http_text: null + event: + - http_fn: null + rename_note: + args: + - http_text: null + event: + - http_fn: null diff --git a/apps/panote_list/src/impl.rs b/apps/panote_list/src/impl.rs new file mode 100644 index 0000000..4f81078 --- /dev/null +++ b/apps/panote_list/src/impl.rs @@ -0,0 +1,80 @@ +use crate::r#struct::*; +use crate::*; +use wasm_serverless_lib::*; + +struct NotesMan {} +impl NotesMan { + pub fn new() -> Self { + Self {} + } + pub fn set_notelist(&self, list: Vec) { + // self.kernel.set("notes_meta".to_string(),serde_json::to_string(&list).unwrap()); + KvBatch::new() + .then_set( + "notes_meta".as_bytes(), + serde_json::to_string(&list).unwrap().as_bytes(), + ) + .finally_call(); + } + pub fn get_note_list(&self) -> Vec { + // let s = self.kernel.get("notes_meta".to_string()); + let s = KvBatch::new() + .then_get("notes_meta".as_bytes()) + .finally_call(); + let s = s.res_str(); + let mut node_id_name_list: Vec = Vec::new(); + if s.is_none() { + KvBatch::new() + .then_set( + "notes_meta".as_bytes(), + serde_json::to_string(&node_id_name_list) + .unwrap() + .as_bytes(), + ) + .finally_call(); + // self.kernel.set( + // "notes_meta".to_string(), + // serde_json::to_string(&node_id_name_list).unwrap(), + // ); + } else if let Some(s) = s { + // println!("saved data {}",s); + node_id_name_list = serde_json::from_str(&*s).unwrap(); + } + node_id_name_list + } +} + +impl ListApi for Impl { + fn get_notes_mata(&self, req: GetNotesMataReq) -> GetNotesMataResp { + let node_id_name_list = NotesMan::new().get_note_list(); + GetNotesMataResp { node_id_name_list } + } + + fn create_new_note(&self, req: CreateNewNoteReq) -> CreateNewNoteResp { + let man = NotesMan::new(); + let mut nl = man.get_note_list(); + let mut one_id_to_name = Vec::new(); + one_id_to_name.reserve(2); + one_id_to_name.push(Value::String(nl.len().to_string())); + one_id_to_name.push(Value::String("新的笔记".to_string())); + nl.push(Value::Array(one_id_to_name)); + man.set_notelist(nl); + CreateNewNoteResp {} + } + + fn rename_note(&self, arg: RenameNoteReq) -> RenameNoteResp { + let man = NotesMan::new(); + + let mut notelist = man.get_note_list(); + for id_name in &mut notelist { + let id_name = id_name.as_array_mut().unwrap(); + if id_name[0].as_str().unwrap() == arg.noteid { + id_name[1] = Value::String(arg.name); + break; + } + } + man.set_notelist(notelist); + + RenameNoteResp {} + } +} diff --git a/apps/panote_list/src/lib.rs b/apps/panote_list/src/lib.rs new file mode 100644 index 0000000..580b308 --- /dev/null +++ b/apps/panote_list/src/lib.rs @@ -0,0 +1,43 @@ +use serde_json; +use serde_json::Value; +use std::mem::ManuallyDrop; +use wasm_serverless_lib::*; +mod r#struct; +mod r#impl; +use r#struct::*; + +trait ListApi { +fn get_notes_mata(&self,req: GetNotesMataReq) -> GetNotesMataResp; +fn create_new_note(&self,req: CreateNewNoteReq) -> CreateNewNoteResp; +fn rename_note(&self,req: RenameNoteReq) -> RenameNoteResp; +} + +pub struct Impl; + +#[no_mangle] +fn get_notes_mata(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.get_notes_mata(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn create_new_note(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.create_new_note(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} +#[no_mangle] +fn rename_note(http_json_ptr: i32, http_json_len: i32) { + let json_str = unsafe { String::from_raw_parts(http_json_ptr as *mut u8, http_json_len as usize, http_json_len as usize) }; + if let Ok(req) = serde_json::from_str::(&json_str) { + let resp = Impl.rename_note(req); + let resp_str = serde_json::to_string(&resp).unwrap(); + unsafe { write_result(resp_str.as_ptr(), resp_str.len() as i32) } + } +} diff --git a/apps/panote_list/src/struct.rs b/apps/panote_list/src/struct.rs new file mode 100644 index 0000000..46de247 --- /dev/null +++ b/apps/panote_list/src/struct.rs @@ -0,0 +1,16 @@ +use serde::{Serialize, Deserialize}; +// Requests +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetNotesMataReq { } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct CreateNewNoteReq { } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct RenameNoteReq { pub noteid: String, pub name: String } + +// Responses +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct GetNotesMataResp { pub node_id_name_list: Vec } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct CreateNewNoteResp { } +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct RenameNoteResp { } diff --git a/apps/word_count/Cargo.lock b/apps/word_count/Cargo.lock index 2307fd0..7aa0dd0 100644 --- a/apps/word_count/Cargo.lock +++ b/apps/word_count/Cargo.lock @@ -129,6 +129,9 @@ checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasm_serverless_lib" version = "0.1.0" +dependencies = [ + "wasmedge-bindgen", +] [[package]] name = "wasmedge-bindgen" diff --git a/apps/word_count/src/lib.rs b/apps/word_count/src/lib.rs index 42f37f4..45b8e65 100644 --- a/apps/word_count/src/lib.rs +++ b/apps/word_count/src/lib.rs @@ -54,7 +54,7 @@ use wasmedge_wasi_helper::wasmedge_wasi_helper::_initialize; #[no_mangle] pub fn split_file() { _initialize(); - let file_path = "files/random_words.txt"; + let file_path = "random_words.txt"; println!("split file start"); // read file let mut file = HostFile::open(file_path); diff --git a/scripts/build/_ans_build_demo_apps_each.yml b/scripts/build/_ans_build_demo_apps_each.yml index 45a098a..7210329 100644 --- a/scripts/build/_ans_build_demo_apps_each.yml +++ b/scripts/build/_ans_build_demo_apps_each.yml @@ -18,4 +18,21 @@ src: ../../apps/{{ item }}/app.yaml dest: apps/{{ item }}/app.yaml force: yes - become: yes \ No newline at end of file + become: yes +# Copy files dir if it exists +- name: Check if the files dir exists + stat: + path: ../../apps/{{ item }}/files + register: files_dir + +- name: ls dir + shell: ls ../../apps/{{ item }}/files + when: files_dir.stat.exists + +- name: Copy the files dir if it exists + shell: cp -r ../../apps/{{ item }}/files/* files + # copy: + # src: ../../apps/{{ item }}/files/* + # dest: files + become: yes + when: files_dir.stat.exists diff --git a/scripts/build/ans_build_demo_apps.yml b/scripts/build/ans_build_demo_apps.yml index e12c242..51486f1 100644 --- a/scripts/build/ans_build_demo_apps.yml +++ b/scripts/build/ans_build_demo_apps.yml @@ -7,5 +7,8 @@ - fn2 - word_count - longchain + - panote_auth + - panote_content + - panote_list - name: App needed data shell: python3 _gen_app_need_data.py \ No newline at end of file diff --git a/scripts/deploy_single_node/test_dir/files/node_config.yaml b/scripts/deploy_single_node/test_dir/files/node_config.yaml index e773ab0..2eb709f 100644 --- a/scripts/deploy_single_node/test_dir/files/node_config.yaml +++ b/scripts/deploy_single_node/test_dir/files/node_config.yaml @@ -1,7 +1,7 @@ nodes: 1: - addr: 127.0.0.1:2500 + addr: 192.168.232.129:2500 spec: [meta,master] 2: - addr: 127.0.0.1:2505 + addr: 192.168.232.129:2505 spec: [meta,worker] diff --git a/scripts/http_test.py b/scripts/http_test.py index 2432aad..de876d1 100644 --- a/scripts/http_test.py +++ b/scripts/http_test.py @@ -5,15 +5,15 @@ def run_one(): ms = time.time()*1000.0 - res = requests.get('http://127.0.0.1:2501/longchain') + res = requests.post('http://hanbaoaaa.xyz/waverless_api1/panote_auth/verify_token',json={"token": "hhhh"}) # json={'after_which': 0, # 'order_by': 0, # 'tags': [], # 'search_str': "", # 'price_range': []}, verify=False) ms_ret = time.time()*1000.0 - print(res, ms_ret-ms) + print(res, ms_ret-ms,res.text) # 10 concurrent requests by multi-threading -for i in range(10): +for i in range(1): threading.Thread(target=run_one).start() \ No newline at end of file diff --git a/src/general/fs/mod.rs b/src/general/m_fs/mod.rs similarity index 56% rename from src/general/fs/mod.rs rename to src/general/m_fs/mod.rs index 5717de5..93893c8 100644 --- a/src/general/fs/mod.rs +++ b/src/general/m_fs/mod.rs @@ -1,3 +1,6 @@ +use async_trait::async_trait; +use crossbeam_skiplist::SkipMap; +use parking_lot::Mutex; use std::{ fs::File, io::{Read, Seek}, @@ -5,31 +8,21 @@ use std::{ path::PathBuf, sync::Arc, }; - -use async_trait::async_trait; -use crossbeam_skiplist::SkipMap; -use parking_lot::Mutex; use ws_derive::LogicalModule; use crate::{ + logical_module_view_impl, result::{ErrCvt, WSResult}, - sys::{FsView, LogicalModule, LogicalModuleNewArgs}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef}, util::JoinHandleWrapper, }; -lazy_static::lazy_static! { - static ref FS: Option=None; -} -pub fn fs<'a>() -> &'a Fs { - let res = &*FS as *const Option as *mut Option; - - unsafe { (*res).as_ref().unwrap().fs() } -} - +logical_module_view_impl!(FsView); +logical_module_view_impl!(FsView, fs, Fs); #[derive(LogicalModule)] pub struct Fs { fd_files: SkipMap>>, - file_path: PathBuf, + pub file_path: PathBuf, } #[async_trait] @@ -38,11 +31,6 @@ impl LogicalModule for Fs { where Self: Sized, { - unsafe { - let res = &*FS as *const Option as *mut Option; - *res = Some(FsView::new(args.logical_modules_ref.clone())); - } - Self { fd_files: SkipMap::new(), file_path: args.nodes_config.file_dir.clone(), @@ -57,7 +45,9 @@ impl LogicalModule for Fs { impl Fs { pub fn open_file(&self, fname: &str) -> WSResult { - let f = File::open(self.file_path.join(fname)).map_err(|e| ErrCvt(e).to_ws_io_err())?; + let fp = self.file_path.join("files").join(fname); + tracing::debug!("openning file {:?}", fp); + let f = File::open(fp).map_err(|e| ErrCvt(e).to_ws_io_err())?; let fd = f.as_raw_fd(); let _ = self.fd_files.insert(fd, Arc::new(Mutex::new(f))); Ok(fd) @@ -67,13 +57,19 @@ impl Fs { Ok(()) } pub fn read_file_at(&self, fd: i32, offset: i32, buf: &mut [u8]) -> WSResult { - let f = self.fd_files.get(&fd).unwrap().value().clone(); - let mut f = f.lock(); - let _ = f - .seek(std::io::SeekFrom::Start(offset as u64)) - .map_err(|e| ErrCvt(e).to_ws_io_err())?; - // Read into the buffer - let bytes_read = f.read(buf).map_err(|e| ErrCvt(e).to_ws_io_err())?; - Ok(bytes_read) + if let Some(f) = self.fd_files.get(&fd).map(|v| v.value().clone()) { + let mut f = f.lock(); + let _ = f + .seek(std::io::SeekFrom::Start(offset as u64)) + .map_err(|e| ErrCvt(e).to_ws_io_err())?; + // Read into the buffer + let bytes_read = f.read(buf).map_err(|e| ErrCvt(e).to_ws_io_err())?; + + Ok(bytes_read) + } else { + tracing::error!("function read_file_at: invalid fd {}", fd); + + Ok(0) + } } } diff --git a/src/general/m_kv_store_engine.rs b/src/general/m_kv_store_engine.rs new file mode 100644 index 0000000..b95d143 --- /dev/null +++ b/src/general/m_kv_store_engine.rs @@ -0,0 +1,138 @@ +// pub struct KvStorage { +// // testmap: SkipMap, Vec>, +// pub view: KvStorageView, +// } + +use super::{m_fs::Fs, network::m_p2p::P2PModule}; +use crate::{ + logical_module_view_impl, + result::WSResult, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef, NodeID}, + util::JoinHandleWrapper, +}; +use axum::async_trait; +use bincode::serialize; +use bincode::serialize_into; +use serde::de::DeserializeOwned; +use serde::Serialize; +use std::sync::OnceLock; +use ws_derive::LogicalModule; + +logical_module_view_impl!(View); +logical_module_view_impl!(View, fs, Fs); +logical_module_view_impl!(View, p2p, P2PModule); + +#[derive(LogicalModule)] +pub struct KvStoreEngine { + db: OnceLock, + view: View, +} + +#[async_trait] +impl LogicalModule for KvStoreEngine { + fn inner_new(args: LogicalModuleNewArgs) -> Self + where + Self: Sized, + { + Self { + db: OnceLock::new(), + view: View::new(args.logical_modules_ref.clone()), + } + } + async fn start(&self) -> WSResult> { + let db_path = self.view.fs().file_path.join(format!( + "kv_store_engine_{}", + self.view.p2p().nodes_config.this_node() + )); + let _ = self.db.get_or_init(|| { + let db = sled::Config::default() + .path(&db_path) + .create_new(true) + .open() + .map_or_else( + |_e| sled::Config::default().path(db_path).open().unwrap(), + |v| v, + ); + db + }); + Ok(vec![]) + } +} + +impl KvStoreEngine { + pub fn set(&self, key: K, value: &K::Value) + where + K: KeyType, + { + let key = key.make_key(); + let _ = self + .db + .get() + .unwrap() + .insert(key, serialize(value).unwrap()) + .unwrap(); + } + pub fn get<'a, K>(&self, key: K) -> Option + where + K: KeyType, + { + let key = key.make_key(); + self.db.get().unwrap().get(key).map_or_else( + |e| { + tracing::error!("get kv error: {:?}", e); + None + }, + |v| v.map(|v| bincode::deserialize_from(v.as_ref()).unwrap()), + ) + } + pub fn del(&self, key: K) + where + K: KeyType, + { + let key = key.make_key(); + let _ = self.db.get().unwrap().remove(key).unwrap(); + } + pub fn flush(&self) { + let _ = self.db.get().unwrap().flush().unwrap(); + } +} + +pub trait KeyType: Serialize { + type Value: Serialize + DeserializeOwned; + fn id(&self) -> u8; + fn make_key(&self) -> Vec { + let mut key = Vec::with_capacity(1 + bincode::serialized_size(self).unwrap() as usize); + key.push(self.id()); + serialize_into(&mut key, self).unwrap(); + key + } +} + +pub struct KeyTypeKv<'a>(pub &'a [u8]); + +pub struct KeyTypeKvPosition<'a>(pub &'a [u8]); + +impl KeyType for KeyTypeKvPosition<'_> { + type Value = NodeID; + fn id(&self) -> u8 { + 0 + } +} +impl KeyType for KeyTypeKv<'_> { + type Value = Vec; + fn id(&self) -> u8 { + 1 + } +} + +impl Serialize for KeyTypeKvPosition<'_> { + fn serialize(&self, serializer: S) -> Result { + self.0.serialize(serializer) + } +} + +impl Serialize for KeyTypeKv<'_> { + fn serialize(&self, serializer: S) -> Result { + self.0.serialize(serializer) + } +} diff --git a/src/general/metric_publisher.rs b/src/general/m_metric_publisher.rs similarity index 85% rename from src/general/metric_publisher.rs rename to src/general/m_metric_publisher.rs index cc62367..748344d 100644 --- a/src/general/metric_publisher.rs +++ b/src/general/m_metric_publisher.rs @@ -3,12 +3,21 @@ use sysinfo::{CpuExt, CpuRefreshKind, RefreshKind, System, SystemExt}; use ws_derive::LogicalModule; use crate::{ + logical_module_view_impl, result::WSResult, - sys::{LogicalModule, LogicalModuleNewArgs, MetricPublisherView}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef}, util::JoinHandleWrapper, }; -use super::network::{p2p::MsgSender, proto}; +use super::network::{ + m_p2p::{MsgSender, P2PModule}, + proto, +}; + +logical_module_view_impl!(MetricPublisherView); +logical_module_view_impl!(MetricPublisherView, p2p, P2PModule); +// logical_module_view_impl!(MetricPublisherView, metric_observor, Option); +logical_module_view_impl!(MetricPublisherView, metric_publisher, MetricPublisher); #[derive(LogicalModule)] pub struct MetricPublisher { diff --git a/src/general/mod.rs b/src/general/mod.rs index b46865a..ac60728 100644 --- a/src/general/mod.rs +++ b/src/general/mod.rs @@ -1,4 +1,5 @@ -pub mod fs; pub mod kv_interface; -pub mod metric_publisher; +pub mod m_fs; +pub mod m_kv_store_engine; +pub mod m_metric_publisher; pub mod network; diff --git a/src/general/network/http_handler.rs b/src/general/network/http_handler.rs index 16fd620..2519ce3 100644 --- a/src/general/network/http_handler.rs +++ b/src/general/network/http_handler.rs @@ -1,14 +1,19 @@ -use crate::sys::{HttpHandlerView, LogicalModule}; +use crate::{ + logical_module_view_impl, + sys::{LogicalModule, LogicalModulesRef}, +}; use async_trait::async_trait; use axum::{ extract::{Path, State}, response::{IntoResponse, Response}, - routing::get, + routing::post, Router, }; use std::net::SocketAddr; use std::sync::atomic::AtomicUsize; +use tower_http::cors::CorsLayer; +use super::m_p2p::P2PModule; pub type ReqId = usize; pub struct LocalReqIdAllocator { id: AtomicUsize, @@ -27,22 +32,31 @@ impl LocalReqIdAllocator { #[async_trait] pub trait HttpHandler: LogicalModule { // fn alloc_local_req_id(&self) -> ReqId; - async fn handle_request(&self, req_fn: &str) -> Response; + async fn handle_request(&self, req_fn: &str, http_text: String) -> Response; // async fn select_node( // &self, // req: proto::sche::FnEventScheRequest, // ) -> proto::sche::FnEventScheResponse; } -pub async fn start_http_handler(request_handler_view: HttpHandlerView) { +logical_module_view_impl!(HttpHandlerView); +logical_module_view_impl!(HttpHandlerView, p2p, P2PModule); +logical_module_view_impl!(HttpHandlerView, http_handler, Box); + +pub async fn start_http_handler(modsref: LogicalModulesRef) { + let view = HttpHandlerView::new(modsref); let addr = SocketAddr::new( "0.0.0.0".parse().unwrap(), - request_handler_view.p2p().nodes_config.this.1.addr.port() + 1, + view.p2p().nodes_config.this.1.addr.port() + 1, ); tracing::info!("http start on {}", addr); let app = Router::new() - .route("/:route", get(handler)) - .with_state(request_handler_view); + // prometheus metrics + // .route("metrics") + .route("/:app/:fn", post(handler2)) + .route("/:route", post(handler)) + .layer(CorsLayer::permissive()) + .with_state(view); axum::Server::bind(&addr) .serve(app.into_make_service()) @@ -52,9 +66,28 @@ pub async fn start_http_handler(request_handler_view: HttpHandlerView) { tracing::info!("http end on {}", addr); } +async fn handler2( + Path((app, func)): Path<(String, String)>, + + // Json(json): Json, + view: State, /* _post: String*/ + + body: String, +) -> impl IntoResponse { + view.http_handler() + .handle_request(&format!("{app}/{func}"), body) + .await +} + async fn handler( route: Path, + + // Json(json): Json, view: State, /* _post: String*/ + + body: String, ) -> impl IntoResponse { - view.http_handler().handle_request(route.as_str()).await + view.http_handler() + .handle_request(route.as_str(), body) + .await } diff --git a/src/general/network/p2p.rs b/src/general/network/m_p2p.rs similarity index 98% rename from src/general/network/p2p.rs rename to src/general/network/m_p2p.rs index 156a713..a06893d 100644 --- a/src/general/network/p2p.rs +++ b/src/general/network/m_p2p.rs @@ -10,14 +10,14 @@ use std::{ }; use super::{ + m_p2p_quic::P2PQuicNode, msg_pack::{MsgPack, RPCReq}, - p2p_quic::P2PQuicNode, }; use crate::{ config::NodesConfig, - // module_view::P2PModuleLMView, + logical_module_view_impl, result::{ErrCvt, WSResult, WsNetworkConnErr, WsNetworkLogicErr}, - sys::{LogicalModule, LogicalModuleNewArgs, NodeID, P2PView}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef, NodeID}, util::JoinHandleWrapper, }; @@ -164,6 +164,9 @@ pub struct P2PModule { // unsafe impl Send for P2PModule {} // unsafe impl Sync for P2PModule {} +logical_module_view_impl!(P2PView); +logical_module_view_impl!(P2PView, p2p, P2PModule); + #[async_trait] impl LogicalModule for P2PModule { fn inner_new(args: LogicalModuleNewArgs) -> Self diff --git a/src/general/network/p2p_quic.rs b/src/general/network/m_p2p_quic.rs similarity index 94% rename from src/general/network/p2p_quic.rs rename to src/general/network/m_p2p_quic.rs index 1529fa4..68c5a07 100644 --- a/src/general/network/p2p_quic.rs +++ b/src/general/network/m_p2p_quic.rs @@ -33,12 +33,10 @@ use ws_derive::LogicalModule; use crate::{ // module_view::P2PQuicNodeLMView, - result::{ErrCvt, WSResult, WsNetworkConnErr, WsSerialErr}, - sys::{BroadcastMsg, BroadcastSender, LogicalModule, LogicalModuleNewArgs, NodeID, P2PView}, - util::JoinHandleWrapper, + logical_module_view_impl, result::{ErrCvt, WSResult, WsNetworkConnErr, WsSerialErr}, sys::{LogicalModulesRef,BroadcastMsg, BroadcastSender, LogicalModule, LogicalModuleNewArgs, NodeID}, util::JoinHandleWrapper }; -use super::p2p::{MsgId, P2PKernel, P2PModule, TaskId}; +use super::m_p2p::{MsgId, P2PKernel, P2PModule, TaskId}; // #[derive(Default, Ord, PartialEq, PartialOrd, Eq, Clone, Copy)] // struct XId(pub [u8; 32]); @@ -81,9 +79,12 @@ impl P2PQuicNodeShared { } } +logical_module_view_impl!(View); +logical_module_view_impl!(View, p2p, P2PModule); + #[derive(LogicalModule)] pub struct P2PQuicNode { - pub logical_modules_view: P2PView, + pub logical_modules_view: View, shared: Arc, } @@ -100,7 +101,7 @@ impl LogicalModule for P2PQuicNode { Self: Sized, { Self { - logical_modules_view: P2PView::new(args.logical_modules_ref.clone()), + logical_modules_view: View::new(args.logical_modules_ref.clone()), shared: P2PQuicNodeShared { btx: args.btx, locked: Mutex::new(P2PQuicNodeLocked { sub_tasks: vec![] }), @@ -295,7 +296,7 @@ impl LogicalModule for P2PQuicNode { fn new_handle_connection_task( remote_addr: SocketAddr, - view: &P2PView, + view: &View, shared: Arc, endpoint: Endpoint, connection: Connection, @@ -314,7 +315,7 @@ fn new_handle_connection_task( async fn handle_connection( remote_addr: SocketAddr, - view: &P2PView, + view: &View, shared: Arc, _endpoint: &Endpoint, connection: Connection, @@ -351,17 +352,7 @@ async fn handle_connection( if let Some(WireMsg((head, _, bytes))) = msg { match deserialize_msg_id_task_id(&head) { Ok((msg_id, task_id)) => { - tracing::debug!("new to dispatch task_id: {}", task_id); - // println!("Received from {remote_addr:?} --> {bytes:?}"); view.p2p().dispatch(remote_id, msg_id, task_id, bytes.into()); - // if bytes == *MSG_MARCO { - // let reply = Bytes::from(MSG_POLO); - // connection - // .send((Bytes::new(), Bytes::new(), reply.clone())) - // .await?; - // println!("Replied to {src:?} --> {reply:?}"); - // } - // println!(); } Err(err) => { tracing::warn!("incoming deserial head error: {:?}", err); diff --git a/src/general/network/mod.rs b/src/general/network/mod.rs index 5443e36..1f0cbc4 100644 --- a/src/general/network/mod.rs +++ b/src/general/network/mod.rs @@ -1,7 +1,7 @@ pub mod http_handler; +pub mod m_p2p; +pub mod m_p2p_quic; pub mod msg_pack; -pub mod p2p; -pub mod p2p_quic; pub mod proto { pub mod kv { diff --git a/src/general/network/msg_pack.rs b/src/general/network/msg_pack.rs index 50ddd26..5ff0263 100644 --- a/src/general/network/msg_pack.rs +++ b/src/general/network/msg_pack.rs @@ -1,7 +1,7 @@ use downcast_rs::{impl_downcast, Downcast}; use super::{ - p2p::MsgId, + m_p2p::MsgId, proto::{self, kv::KvResponse}, }; diff --git a/src/main.rs b/src/main.rs index 73c2656..161796b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ pub mod worker; pub mod cmd_arg; pub mod config; pub mod result; -mod sys; +pub mod sys; pub mod util; #[tokio::main] diff --git a/src/master/http_handler.rs b/src/master/m_http_handler.rs similarity index 72% rename from src/master/http_handler.rs rename to src/master/m_http_handler.rs index d7a6e42..d3ff600 100644 --- a/src/master/http_handler.rs +++ b/src/master/m_http_handler.rs @@ -8,18 +8,33 @@ use ws_derive::LogicalModule; // use use crate::{ - general::network::http_handler::{self, HttpHandler}, + general::network::{ + http_handler::{self, HttpHandler}, + m_p2p::P2PModule, + }, + logical_module_view_impl, result::WSResult, - sys::{HttpHandlerView, LogicalModule, LogicalModuleNewArgs, MasterHttpHandlerView}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef}, util::JoinHandleWrapper, }; +use super::{m_master::Master, m_metric_observor::MetricObservor}; + +logical_module_view_impl!(MasterHttpHandlerView); +logical_module_view_impl!(MasterHttpHandlerView, p2p, P2PModule); +logical_module_view_impl!(MasterHttpHandlerView, http_handler, Box); +logical_module_view_impl!(MasterHttpHandlerView, master, Option); +logical_module_view_impl!( + MasterHttpHandlerView, + metric_observor, + Option +); + #[derive(LogicalModule)] pub struct MasterHttpHandler { // local_req_id_allocator: LocalReqIdAllocator, // view: ScheMasterView, view: MasterHttpHandlerView, - http_handler_view: HttpHandlerView, } #[async_trait] @@ -29,19 +44,15 @@ impl LogicalModule for MasterHttpHandler { Self: Sized, { Self { - // each_fn_caching: HashMap::new(), view: MasterHttpHandlerView::new(args.logical_modules_ref.clone()), - http_handler_view: HttpHandlerView::new(args.logical_modules_ref.clone()), - // local_req_id_allocator: LocalReqIdAllocator::new(), - // view: , } } async fn start(&self) -> WSResult> { tracing::info!("start as master"); - let view = self.http_handler_view.clone(); + let view = self.view.clone(); Ok(vec![JoinHandleWrapper::from(tokio::spawn(async move { - http_handler::start_http_handler(view).await; + http_handler::start_http_handler(view.inner).await; }))]) } } @@ -67,7 +78,8 @@ impl HttpHandler for MasterHttpHandler { // fn alloc_local_req_id(&self) -> ReqId { // self.local_req_id_allocator.alloc() // } - async fn handle_request(&self, app: &str) -> Response { + async fn handle_request(&self, app: &str, _http_text: String) -> Response { + tracing::debug!("handle_request {}", app); if app == "metrics" { return self.handle_prometheus(); } @@ -101,7 +113,16 @@ impl HttpHandler for MasterHttpHandler { .unwrap() .addr; target_node.set_port(target_node.port() + 1); - Redirect::to(&*format!("http://{}/{}", target_node, app)).into_response() + tracing::debug!( + "redirect to http://hanbaoaaa.xyz/waverless_api{}/{}", + target_node, + app + ); + Redirect::temporary(&*format!( + "http://hanbaoaaa.xyz/waverless_api{}/{}", + node, app + )) + .into_response() // } } // async fn select_node( diff --git a/src/master/master.rs b/src/master/m_master.rs similarity index 90% rename from src/master/master.rs rename to src/master/m_master.rs index 95de7e4..c815abe 100644 --- a/src/master/master.rs +++ b/src/master/m_master.rs @@ -5,14 +5,17 @@ use ws_derive::LogicalModule; use crate::{ general::network::{ - p2p::{RPCHandler, RPCResponsor}, + m_p2p::{P2PModule, RPCHandler, RPCResponsor}, proto::{self, sche::MakeSchePlanResp}, }, + logical_module_view_impl, result::WSResult, - sys::{LogicalModule, LogicalModuleNewArgs, MasterView, NodeID}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef, NodeID}, util::JoinHandleWrapper, }; +use super::m_master_kv::MasterKv; + trait NodeWeighteFetcher: Send + Sync + 'static { // NOTE: get weight return node weight // larger is better @@ -69,6 +72,11 @@ impl NodeSelector for HashNodeSelector { } } +logical_module_view_impl!(MasterView); +logical_module_view_impl!(MasterView, p2p, P2PModule); +logical_module_view_impl!(MasterView, master, Option); +logical_module_view_impl!(MasterView, master_kv, Option); + #[derive(LogicalModule)] pub struct Master { // each_fn_caching: HashMap>, diff --git a/src/master/master_kv.rs b/src/master/m_master_kv.rs similarity index 74% rename from src/master/master_kv.rs rename to src/master/m_master_kv.rs index 9382417..af066eb 100644 --- a/src/master/master_kv.rs +++ b/src/master/m_master_kv.rs @@ -6,25 +6,34 @@ use tokio::sync::Notify; use ws_derive::LogicalModule; use crate::{ - general::network::{ - msg_pack::KvResponseExt, - p2p::{RPCHandler, RPCResponsor, TaskId}, - proto::{ - self, - kv::{KvRequests, KvResponse, KvResponses}, + general::{ + m_kv_store_engine::{KeyTypeKv, KeyTypeKvPosition, KvStoreEngine}, + network::{ + m_p2p::{P2PModule, RPCHandler, RPCResponsor, TaskId}, + msg_pack::KvResponseExt, + proto::{ + self, + kv::{KvRequests, KvResponse, KvResponses}, + }, }, }, + logical_module_view_impl, result::WSResult, - sys::{LogicalModule, LogicalModuleNewArgs, MasterView, NodeID}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef, NodeID}, util::JoinHandleWrapper, }; +logical_module_view_impl!(MasterKvView); +logical_module_view_impl!(MasterKvView, p2p, P2PModule); +logical_module_view_impl!(MasterKvView, master_kv, Option); +logical_module_view_impl!(MasterKvView, kv_store_engine, KvStoreEngine); + #[derive(LogicalModule)] pub struct MasterKv { kv_map: RwLock, Vec>>, lock_notifiers: RwLock, (NodeID, u32, Arc)>>, rpc_handler: RPCHandler, - view: MasterView, + view: MasterKvView, } #[async_trait] @@ -37,7 +46,7 @@ impl LogicalModule for MasterKv { kv_map: RwLock::new(HashMap::new()), lock_notifiers: RwLock::new(HashMap::new()), rpc_handler: RPCHandler::default(), - view: MasterView::new(args.logical_modules_ref.clone()), + view: MasterKvView::new(args.logical_modules_ref.clone()), } } async fn start(&self) -> WSResult> { @@ -85,21 +94,29 @@ impl MasterKv { _from: NodeID, ) -> KvResponse { tracing::debug!("handle_kv_set:{:?}", set); - let mut kvs = vec![]; + if let Some(kv) = set.kv { - let key = kv.key.clone(); - let res = self.kv_map.write().insert(kv.key, kv.value); - if let Some(v) = res { - kvs.push(proto::kv::KvPair { key, value: v }); - } + self.view + .kv_store_engine() + .set(KeyTypeKv(&kv.key), &kv.value); + self.view.kv_store_engine().set( + KeyTypeKvPosition(&kv.key), + &self.view.p2p().nodes_config.this_node(), + ); + + self.view.kv_store_engine().flush(); } - KvResponse::new_common(kvs) + KvResponse::new_common(vec![]) } async fn handle_kv_get(&self, get: proto::kv::kv_request::KvGetRequest) -> KvResponse { tracing::debug!("handle_kv_get:{:?}", get); let mut kvs = vec![]; - if let Some(v) = self.kv_map.read().get(&get.range.as_ref().unwrap().start) { + if let Some(v) = self + .view + .kv_store_engine() + .get(KeyTypeKv(&get.range.as_ref().unwrap().start)) + { kvs.push(proto::kv::KvPair { key: get.range.unwrap().start, value: v.clone(), @@ -109,18 +126,25 @@ impl MasterKv { } async fn handle_kv_delete(&self, delete: proto::kv::kv_request::KvDeleteRequest) -> KvResponse { tracing::debug!("handle_kv_delete:{:?}", delete); - let res = self - .kv_map - .write() - .remove(&delete.range.as_ref().unwrap().start); - let mut kvs = vec![]; - if let Some(v) = res { - kvs.push(proto::kv::KvPair { - key: delete.range.unwrap().start, - value: v, - }); - } - KvResponse::new_common(kvs) + // let res = self + // .kv_map + // .write() + // .remove(&delete.range.as_ref().unwrap().start); + self.view + .kv_store_engine() + .del(KeyTypeKvPosition(&delete.range.as_ref().unwrap().start)); + self.view + .kv_store_engine() + .del(KeyTypeKv(&delete.range.as_ref().unwrap().start)); + self.view.kv_store_engine().flush(); + // let mut kvs = vec![]; + // if let Some(v) = res { + // kvs.push(proto::kv::KvPair { + // key: delete.range.unwrap().start, + // value: v, + // }); + // } + KvResponse::new_common(vec![]) } async fn handle_kv_lock( &self, diff --git a/src/master/metric_observor.rs b/src/master/m_metric_observor.rs similarity index 92% rename from src/master/metric_observor.rs rename to src/master/m_metric_observor.rs index 83a4734..035dc4c 100644 --- a/src/master/metric_observor.rs +++ b/src/master/m_metric_observor.rs @@ -1,7 +1,11 @@ use crate::{ - general::network::{p2p::MsgHandler, proto}, + general::network::{ + m_p2p::{MsgHandler, P2PModule}, + proto, + }, + logical_module_view_impl, result::WSResult, - sys::{LogicalModule, LogicalModuleNewArgs, MetricObservorView, NodeID}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef, NodeID}, util::JoinHandleWrapper, }; use async_trait::async_trait; @@ -83,6 +87,10 @@ pub mod prometheus { pub struct NodeFnCacheMetric(HashSet); +logical_module_view_impl!(MetricObservorView); +logical_module_view_impl!(MetricObservorView, p2p, P2PModule); +logical_module_view_impl!(MetricObservorView, metric_observor, Option); + #[derive(LogicalModule)] pub struct MetricObservor { pub registry: Registry, diff --git a/src/master/mod.rs b/src/master/mod.rs index 9c37907..763e79a 100644 --- a/src/master/mod.rs +++ b/src/master/mod.rs @@ -1,4 +1,4 @@ -pub mod http_handler; -pub mod master; -pub mod master_kv; -pub mod metric_observor; +pub mod m_http_handler; +pub mod m_master; +pub mod m_master_kv; +pub mod m_metric_observor; diff --git a/src/sys.rs b/src/sys.rs index b546127..8db9b80 100644 --- a/src/sys.rs +++ b/src/sys.rs @@ -1,18 +1,20 @@ use crate::{ config::NodesConfig, general::{ - fs::Fs, - metric_publisher::MetricPublisher, - network::{http_handler::HttpHandler, p2p::P2PModule}, + m_fs::Fs, + m_kv_store_engine::KvStoreEngine, + m_metric_publisher::MetricPublisher, + network::{http_handler::HttpHandler, m_p2p::P2PModule}, }, master::{ - http_handler::MasterHttpHandler, master::Master, master_kv::MasterKv, - metric_observor::MetricObservor, + m_http_handler::MasterHttpHandler, m_master::Master, m_master_kv::MasterKv, + m_metric_observor::MetricObservor, }, util, worker::{ - executor::Executor, http_handler::WorkerHttpHandler, instance_manager::InstanceManager, - kv_user_client::KvUserClient, worker::WorkerCore, + m_executor::Executor, m_http_handler::WorkerHttpHandler, + m_instance_manager::InstanceManager, m_kv_user_client::KvUserClient, m_worker::WorkerCore, + wasm_host_funcs::set_singleton_modules, }, }; use crate::{ @@ -196,7 +198,7 @@ macro_rules! logical_modules { #[derive(Clone)] pub struct LogicalModulesRef { - inner: Weak>, + pub inner: Weak>, } impl LogicalModulesRef { @@ -211,6 +213,7 @@ impl LogicalModulesRef { // } // } +#[macro_export] macro_rules! logical_module_view_impl { ($module:ident,$module_name:ident,Option<$type:ty>) => { impl $module { @@ -235,7 +238,7 @@ macro_rules! logical_module_view_impl { }; ($module:ident) => { #[derive(Clone)] - pub struct $module { + struct $module { inner: LogicalModulesRef, } impl $module { @@ -308,6 +311,8 @@ logical_modules!( MetricPublisher, fs, Fs, + kv_store_engine, + KvStoreEngine, //////////////////////////// // master metric_observor, @@ -330,82 +335,6 @@ logical_modules!( Option ); -// logical_module_view_impl!(MetaKvClientView); -// logical_module_view_impl!(MetaKvClientView, meta_kv_client, Box); -// logical_module_view_impl!(MetaKvClientView, meta_kv, Option>); -// logical_module_view_impl!(MetaKvClientView, p2p, P2PModule); - -logical_module_view_impl!(MetaKvView); -// logical_module_view_impl!(MetaKvView, p2p, P2PModule); -// logical_module_view_impl!(MetaKvView, meta_kv, Option>); -// logical_module_view_impl!(MetaKvView, local_kv, Option>); - -logical_module_view_impl!(P2PView); -logical_module_view_impl!(P2PView, p2p, P2PModule); - -logical_module_view_impl!(ScheMasterView); -logical_module_view_impl!(ScheMasterView, p2p, P2PModule); - -logical_module_view_impl!(WorkerView); -logical_module_view_impl!(WorkerView, p2p, P2PModule); - -logical_module_view_impl!(HttpHandlerView); -logical_module_view_impl!(HttpHandlerView, p2p, P2PModule); -logical_module_view_impl!(HttpHandlerView, http_handler, Box); - -logical_module_view_impl!(WorkerHttpHandlerView); -logical_module_view_impl!(WorkerHttpHandlerView, p2p, P2PModule); -logical_module_view_impl!(WorkerHttpHandlerView, http_handler, Box); -logical_module_view_impl!(WorkerHttpHandlerView, executor, Option); - -logical_module_view_impl!(MasterHttpHandlerView); -logical_module_view_impl!(MasterHttpHandlerView, p2p, P2PModule); -logical_module_view_impl!(MasterHttpHandlerView, http_handler, Box); -logical_module_view_impl!(MasterHttpHandlerView, master, Option); -logical_module_view_impl!( - MasterHttpHandlerView, - metric_observor, - Option -); - -logical_module_view_impl!(MetricObservorView); -logical_module_view_impl!(MetricObservorView, p2p, P2PModule); -logical_module_view_impl!(MetricObservorView, metric_observor, Option); - -logical_module_view_impl!(MetricPublisherView); -logical_module_view_impl!(MetricPublisherView, p2p, P2PModule); -// logical_module_view_impl!(MetricPublisherView, metric_observor, Option); -logical_module_view_impl!(MetricPublisherView, metric_publisher, MetricPublisher); - -logical_module_view_impl!(KvUserClientView); -logical_module_view_impl!(KvUserClientView, p2p, P2PModule); -logical_module_view_impl!(KvUserClientView, kv_user_client, Option); -logical_module_view_impl!(KvUserClientView, instance_manager, Option); -logical_module_view_impl!(KvUserClientView, worker, Option); -logical_module_view_impl!(KvUserClientView, executor, Option); - -logical_module_view_impl!(ExecutorView); -logical_module_view_impl!(ExecutorView, p2p, P2PModule); -logical_module_view_impl!(ExecutorView, instance_manager, Option); -logical_module_view_impl!(ExecutorView, executor, Option); -logical_module_view_impl!(ExecutorView, kv_user_client, Option); - -logical_module_view_impl!(InstanceManagerView); -logical_module_view_impl!(InstanceManagerView, p2p, P2PModule); -logical_module_view_impl!( - InstanceManagerView, - instance_manager, - Option -); - -logical_module_view_impl!(FsView); -logical_module_view_impl!(FsView, fs, Fs); - -logical_module_view_impl!(MasterView); -logical_module_view_impl!(MasterView, p2p, P2PModule); -logical_module_view_impl!(MasterView, master, Option); -logical_module_view_impl!(MasterView, master_kv, Option); - fn modules_mut_ref(modules: &Arc) -> &mut LogicalModules { // let _ = SETTED_MODULES_COUNT.fetch_add(1, Ordering::SeqCst); let mu = unsafe { &mut *(Arc::downgrade(modules).as_ptr() as *mut LogicalModules) }; @@ -433,6 +362,8 @@ impl LogicalModules { inner: Arc::downgrade(&arc), }, }; + set_singleton_modules(args.logical_modules_ref.clone()); + let is_master = config.this.1.is_master(); assert!(is_master || config.this.1.is_worker()); @@ -440,6 +371,7 @@ impl LogicalModules { p2p: P2PModule::new(args.clone()), metric_publisher: MetricPublisher::new(args.clone()), fs: Fs::new(args.clone()), + kv_store_engine: KvStoreEngine::new(args.clone()), http_handler: if is_master { Box::new(MasterHttpHandler::new(args.clone())) } else { @@ -476,6 +408,7 @@ impl LogicalModules { start_module!(self, sys, http_handler); start_module!(self, sys, metric_publisher); start_module!(self, sys, fs); + start_module!(self, sys, kv_store_engine); // master start_module_opt!(self, sys, metric_observor); diff --git a/src/worker/app_meta.rs b/src/worker/app_meta.rs index f5cb57d..6a3726a 100644 --- a/src/worker/app_meta.rs +++ b/src/worker/app_meta.rs @@ -15,12 +15,14 @@ use crate::{ #[derive(Debug, Serialize, Deserialize)] #[serde(untagged)] pub enum FnEventYaml { + HttpFn { http_fn: () }, HttpApp { http_app: () }, KvSet { kv_set: usize }, } #[derive(PartialEq, Eq)] pub enum FnEvent { + HttpFn, HttpApp, KvSet(usize), } @@ -28,6 +30,7 @@ pub enum FnEvent { impl From for FnEvent { fn from(yaml: FnEventYaml) -> Self { match yaml { + FnEventYaml::HttpFn { http_fn: _ } => Self::HttpFn, FnEventYaml::HttpApp { http_app: _ } => Self::HttpApp, FnEventYaml::KvSet { kv_set } => Self::KvSet(kv_set), } @@ -250,6 +253,7 @@ impl FnMeta { } } } + FnEvent::HttpFn => {} } None }) @@ -353,6 +357,9 @@ impl From for AppMeta { } impl AppMeta { + pub fn fns(&self) -> Vec { + self.fns.iter().map(|(fnname, _)| fnname.clone()).collect() + } pub fn get_fn_meta(&self, fnname: &str) -> Option<&FnMeta> { self.fns.get(fnname) } @@ -415,6 +422,7 @@ impl AppMetaManager { for event in &fnmeta.event { match event { // not kv event, no key pattern + FnEvent::HttpFn => {} FnEvent::HttpApp => {} FnEvent::KvSet(key_index) => { let kvmeta = fnmeta.try_get_kv_meta_by_index(*key_index).unwrap(); diff --git a/src/worker/kv_storage.rs b/src/worker/kv_storage.rs deleted file mode 100644 index 3bc4059..0000000 --- a/src/worker/kv_storage.rs +++ /dev/null @@ -1,4 +0,0 @@ -// pub struct KvStorage { -// // testmap: SkipMap, Vec>, -// pub view: KvStorageView, -// } diff --git a/src/worker/executor.rs b/src/worker/m_executor.rs similarity index 67% rename from src/worker/executor.rs rename to src/worker/m_executor.rs index b025b0e..5878e72 100644 --- a/src/worker/executor.rs +++ b/src/worker/m_executor.rs @@ -1,17 +1,18 @@ use std::{mem::ManuallyDrop, sync::atomic::AtomicU32}; -use super::app_meta::FnArg; +use super::{app_meta::FnArg, m_instance_manager::InstanceManager, m_kv_user_client::KvUserClient}; use crate::{ general::network::{ http_handler::ReqId, - p2p::{RPCHandler, RPCResponsor}, + m_p2p::{P2PModule, RPCHandler, RPCResponsor}, proto::{ self, sche::{distribute_task_req, DistributeTaskResp}, }, }, + logical_module_view_impl, result::WSResult, - sys::{ExecutorView, LogicalModule, LogicalModuleNewArgs}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef}, util::JoinHandleWrapper, worker::wasm::{WasmInstance, WasmValue}, }; @@ -19,6 +20,7 @@ use async_trait::async_trait; use tokio::{sync::oneshot, task::JoinHandle}; #[cfg(target_os = "linux")] use wasmedge_sdk::r#async::AsyncState; +use wasmedge_sdk::Vm; use ws_derive::LogicalModule; pub type SubTaskId = u32; @@ -27,6 +29,12 @@ pub type SubTaskNotifier = oneshot::Sender; pub type SubTaskWaiter = oneshot::Receiver; +logical_module_view_impl!(ExecutorView); +logical_module_view_impl!(ExecutorView, p2p, P2PModule); +logical_module_view_impl!(ExecutorView, instance_manager, Option); +logical_module_view_impl!(ExecutorView, executor, Option); +logical_module_view_impl!(ExecutorView, kv_user_client, Option); + #[derive(LogicalModule)] pub struct Executor { sub_task_id: AtomicU32, @@ -34,6 +42,20 @@ pub struct Executor { view: ExecutorView, } +pub trait VmExt { + fn vm_instance_name(&self) -> String; +} + +impl VmExt for Vm { + fn vm_instance_name(&self) -> String { + self.instance_names() + .into_iter() + .filter(|v| &*v != "env" && &*v != "wasi_snapshot_preview1") + .next() + .unwrap() + } +} + // pub struct FunctionCtxBuilder { // pub app: String, // pub req_id: ReqId, @@ -66,17 +88,20 @@ pub enum EventCtx { impl EventCtx { pub fn conv_to_wasm_params(&self, fn_arg: &FnArg, vm: &WasmInstance) -> Option> { fn prepare_vec_in_vm(vm: &WasmInstance, v: &[u8]) -> (i32, i32) { + let vm_ins = vm.vm_instance_name(); let ptr = vm .run_func( - Some(&vm.instance_names()[0]), + Some(&vm_ins), "allocate", vec![WasmValue::from_i32(v.len() as i32)], ) - .unwrap()[0] + .unwrap_or_else(|err| { + panic!("err:{:?} vm instance names:{:?}", err, vm.instance_names()) + })[0] .to_i32(); let mut mem = ManuallyDrop::new(unsafe { Vec::from_raw_parts( - vm.named_module(&vm.instance_names()[0]) + vm.named_module(&vm_ins) .unwrap() .memory("memory") .unwrap() @@ -108,6 +133,7 @@ pub struct FunctionCtx { pub func: String, pub req_id: ReqId, pub event_ctx: EventCtx, + pub res: Option, /// remote scheduling tasks pub sub_waiters: Vec>, // pub trigger_node: NodeID, } @@ -169,32 +195,69 @@ impl Executor { app: req.app, func: req.func, req_id: 0, + res: None, event_ctx: match req.trigger.unwrap() { distribute_task_req::Trigger::KvKeySet(key) => EventCtx::KvSet { key }, }, sub_waiters: vec![], }; - self.execute(ctx).await; + let _ = self.execute(ctx).await; if let Err(err) = resp.send_resp(DistributeTaskResp {}).await { tracing::error!("send sche resp for app:{app} fn:{func} failed with err: {err}"); } } - pub async fn handle_http_task(&self, appname: &str, req_id: ReqId, text: String) { + pub async fn handle_http_task( + &self, + route: &str, + req_id: ReqId, + text: String, + ) -> Option { + let split = route.split("/").into_iter().collect::>(); + + // trigger app + let appname = split[0]; let app_meta_man = self.view.instance_manager().app_meta_manager.read().await; if let Some(app) = app_meta_man.get_app_meta(appname) { - if let Some(funcname) = app.http_trigger_fn() { - let ctx = FunctionCtx { - app: appname.to_owned(), - func: funcname.to_owned(), - req_id, - event_ctx: EventCtx::Http(text), - sub_waiters: vec![], - }; - drop(app_meta_man); - self.execute(ctx).await; - // self.execute().await; + if split.len() == 1 { + if let Some(funcname) = app.http_trigger_fn() { + let ctx = FunctionCtx { + app: appname.to_owned(), + func: funcname.to_owned(), + req_id, + res: None, + event_ctx: EventCtx::Http(text), + sub_waiters: vec![], + }; + drop(app_meta_man); + return self.execute(ctx).await; + // self.execute().await; + } else { + tracing::warn!("app {} http trigger not found", appname); + } + } else if split.len() == 2 { + let funcname = split[1]; + if let Some(_func) = app.get_fn_meta(funcname) { + let ctx = FunctionCtx { + app: appname.to_owned(), + func: funcname.to_owned(), + req_id, + res: None, + event_ctx: EventCtx::Http(text), + sub_waiters: vec![], + }; + drop(app_meta_man); + return self.execute(ctx).await; + } else { + tracing::warn!("func {} not found, exist:{:?}", funcname, app.fns()); + } + } else { + tracing::warn!("not support route: {}", route); } + } else { + tracing::warn!("app {} not found", appname); } + + None } // pub async fn execute_http_app(&self, fn_ctx_builder: FunctionCtxBuilder) { // let app_meta_man = self.view.instance_manager().app_meta_manager.read().await; @@ -226,7 +289,7 @@ impl Executor { // // .finish_using(&sche_req.app, vm) // // .await // } - async fn execute(&self, fn_ctx: FunctionCtx) { + async fn execute(&self, fn_ctx: FunctionCtx) -> Option { let app = fn_ctx.app.clone(); let func = fn_ctx.func.clone(); let event = fn_ctx.event_ctx.clone(); @@ -241,8 +304,13 @@ impl Executor { .instance_manager() .instance_running_function .write() - .insert(vm.instance_names()[0].clone(), fn_ctx); - + .insert(vm.vm_instance_name().to_owned(), fn_ctx); + tracing::debug!( + "start run instance {} app {} fn {}", + vm.vm_instance_name(), + app, + func + ); // TODO: input value should be passed from context, like http request or prev trigger let params = fnmeta .args @@ -251,16 +319,21 @@ impl Executor { .flatten() .collect::>(); + tracing::debug!("execure params: {:?}", params); + #[cfg(target_os = "linux")] - let _ = vm - .run_func_async( - &AsyncState::new(), - Some(&vm.instance_names()[0]), - func, - params, - ) - .await - .unwrap_or_else(|_| panic!("vm instance names {:?}", vm.instance_names())); + { + let mut a = None; + if vm.active_module().is_err() { + a = Some(vm.vm_instance_name()) + } + if let Err(err) = vm + .run_func_async(&AsyncState::new(), a.as_ref().map(|s| &**s), func, params) + .await + { + tracing::error!("run func failed with err: {}", err); + } + } #[cfg(target_os = "macos")] let _ = vm .run_func(Some(&vm.instance_names()[0]), func, params) @@ -271,21 +344,27 @@ impl Executor { .instance_manager() .instance_running_function .write() - .remove(&vm.instance_names()[0]) + .remove(&vm.vm_instance_name()) .unwrap(); - + tracing::debug!( + "finish run instance {} fn {}", + vm.vm_instance_name(), + fn_ctx.func + ); while let Some(t) = fn_ctx.sub_waiters.pop() { let _ = t.await.unwrap(); } - self.view.instance_manager().finish_using(&app, vm).await + self.view.instance_manager().finish_using(&app, vm).await; + + fn_ctx.res } else { tracing::warn!("app {} func {} not found", app, func); - return; + None } } else { tracing::warn!("app {} not found", app); - return; - }; + None + } // let _ = vm // .run_func_async( diff --git a/src/worker/http_handler.rs b/src/worker/m_http_handler.rs similarity index 57% rename from src/worker/http_handler.rs rename to src/worker/m_http_handler.rs index 3243133..134657f 100644 --- a/src/worker/http_handler.rs +++ b/src/worker/m_http_handler.rs @@ -1,7 +1,11 @@ use crate::{ - general::network::http_handler::{start_http_handler, HttpHandler, LocalReqIdAllocator}, + general::network::{ + http_handler::{start_http_handler, HttpHandler, LocalReqIdAllocator}, + m_p2p::P2PModule, + }, + logical_module_view_impl, result::WSResult, - sys::{HttpHandlerView, LogicalModule, LogicalModuleNewArgs, WorkerHttpHandlerView}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef}, util::JoinHandleWrapper, }; use async_trait::async_trait; @@ -11,10 +15,11 @@ use axum::{ }; use ws_derive::LogicalModule; +use super::m_executor::Executor; + #[derive(LogicalModule)] pub struct WorkerHttpHandler { view: WorkerHttpHandlerView, - http_handler_view: HttpHandlerView, local_req_id_allocator: LocalReqIdAllocator, } @@ -26,34 +31,43 @@ impl LogicalModule for WorkerHttpHandler { { Self { view: WorkerHttpHandlerView::new(args.logical_modules_ref.clone()), - http_handler_view: HttpHandlerView::new(args.logical_modules_ref.clone()), local_req_id_allocator: LocalReqIdAllocator::new(), } } async fn start(&self) -> WSResult> { tracing::info!("start as worker"); - let view = self.http_handler_view.clone(); + let view = self.view.clone(); Ok(vec![JoinHandleWrapper::from(tokio::spawn(async move { - start_http_handler(view).await; + start_http_handler(view.inner).await; }))]) } } +logical_module_view_impl!(WorkerHttpHandlerView); +logical_module_view_impl!(WorkerHttpHandlerView, p2p, P2PModule); +logical_module_view_impl!(WorkerHttpHandlerView, http_handler, Box); +logical_module_view_impl!(WorkerHttpHandlerView, executor, Option); + #[async_trait] impl HttpHandler for WorkerHttpHandler { - async fn handle_request(&self, app: &str) -> Response { - self.view + async fn handle_request(&self, route: &str, http_text: String) -> Response { + tracing::debug!("handle_request {}", route); + if let Some(res) = self + .view .executor() - .handle_http_task(app, self.local_req_id_allocator.alloc(), "".to_owned()) + .handle_http_task(route, self.local_req_id_allocator.alloc(), http_text) // .execute_http_app(FunctionCtxBuilder::new( // app.to_owned(), // self.local_req_id_allocator.alloc(), // self.request_handler_view.p2p().nodes_config.this.0, // )) - .await; - - StatusCode::OK.into_response() + .await + { + (StatusCode::OK, res).into_response() + } else { + StatusCode::OK.into_response() + } } // async fn select_node( // &self, diff --git a/src/worker/instance_manager.rs b/src/worker/m_instance_manager.rs similarity index 93% rename from src/worker/instance_manager.rs rename to src/worker/m_instance_manager.rs index 92e3fb1..882f677 100644 --- a/src/worker/instance_manager.rs +++ b/src/worker/m_instance_manager.rs @@ -1,7 +1,9 @@ -use super::{app_meta::AppMetaManager, executor::FunctionCtx, wasm::WasmInstance}; +use super::{app_meta::AppMetaManager, m_executor::FunctionCtx, wasm::WasmInstance}; use crate::{ + general::network::m_p2p::P2PModule, + logical_module_view_impl, result::WSResult, - sys::{InstanceManagerView, LogicalModule, LogicalModuleNewArgs}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef}, util::JoinHandleWrapper, worker::wasm_host_funcs, // worker::host_funcs, }; @@ -155,7 +157,8 @@ impl EachAppCache { let vm = vm .register_module( Some(&format!( - "{}", + "{}{}", + instance_name, self.next_instance_id.fetch_add(1, Ordering::Relaxed) )), module, @@ -172,6 +175,14 @@ impl EachAppCache { } } +logical_module_view_impl!(InstanceManagerView); +logical_module_view_impl!(InstanceManagerView, p2p, P2PModule); +logical_module_view_impl!( + InstanceManagerView, + instance_manager, + Option +); + #[derive(LogicalModule)] pub struct InstanceManager { // cache: Mutex>, diff --git a/src/worker/kv_user_client.rs b/src/worker/m_kv_user_client.rs similarity index 85% rename from src/worker/kv_user_client.rs rename to src/worker/m_kv_user_client.rs index c89344c..d9e59bb 100644 --- a/src/worker/kv_user_client.rs +++ b/src/worker/m_kv_user_client.rs @@ -4,12 +4,13 @@ use crate::{ general::{ kv_interface::{KvInterface, KvOptions}, network::{ - p2p::RPCCaller, + m_p2p::{P2PModule, RPCCaller}, proto::kv::{KvRequests, KvResponses}, }, }, + logical_module_view_impl, result::WSResult, - sys::{KvUserClientView, LogicalModule, LogicalModuleNewArgs}, + sys::{LogicalModule, LogicalModuleNewArgs, LogicalModulesRef}, util::JoinHandleWrapper, }; use async_trait::async_trait; @@ -17,8 +18,17 @@ use async_trait::async_trait; use ws_derive::LogicalModule; +use super::{m_executor::Executor, m_instance_manager::InstanceManager, m_worker::WorkerCore}; + // use super::super::kv_interface::KvInterface; +logical_module_view_impl!(KvUserClientView); +logical_module_view_impl!(KvUserClientView, p2p, P2PModule); +logical_module_view_impl!(KvUserClientView, kv_user_client, Option); +logical_module_view_impl!(KvUserClientView, instance_manager, Option); +logical_module_view_impl!(KvUserClientView, worker, Option); +logical_module_view_impl!(KvUserClientView, executor, Option); + #[derive(LogicalModule)] pub struct KvUserClient { // testmap: SkipMap, Vec>, @@ -74,10 +84,11 @@ lazy_static::lazy_static! { // static ref NEXT_CACHE_ID: AtomicI32=AtomicI32::new(0); } -pub fn kv_user_client() -> &'static KvUserClient { - let res = &*KV_USER_CLIENT as *const Option as *mut Option; - unsafe { (*res).as_ref().unwrap().kv_user_client() } -} +// pub fn kv_user_client() -> &'static KvUserClient { +// let res = &*KV_USER_CLIENT as *const Option as *mut Option; +// unsafe { (*res).as_ref().unwrap().kv_user_client() } +// } + #[async_trait] impl KvInterface for KvUserClient { diff --git a/src/worker/worker.rs b/src/worker/m_worker.rs similarity index 77% rename from src/worker/worker.rs rename to src/worker/m_worker.rs index 8a4d37b..fcd39ef 100644 --- a/src/worker/worker.rs +++ b/src/worker/m_worker.rs @@ -1,13 +1,19 @@ -use crate::{sys::WorkerView, util::JoinHandleWrapper}; +use crate::{ + general::network::m_p2p::P2PModule, logical_module_view_impl, sys::LogicalModulesRef, + util::JoinHandleWrapper, +}; use async_trait::async_trait; use ws_derive::LogicalModule; use crate::{ - general::network::{p2p::RPCCaller, proto}, + general::network::{m_p2p::RPCCaller, proto}, result::WSResult, sys::{LogicalModule, LogicalModuleNewArgs}, }; +logical_module_view_impl!(WorkerView); +logical_module_view_impl!(WorkerView, p2p, P2PModule); + #[derive(LogicalModule)] pub struct WorkerCore { pub rpc_caller_make_sche: RPCCaller, diff --git a/src/worker/mod.rs b/src/worker/mod.rs index 7d3ad49..f0b4c26 100644 --- a/src/worker/mod.rs +++ b/src/worker/mod.rs @@ -1,13 +1,12 @@ pub mod app_meta; -pub mod executor; pub mod function_event; -pub mod http_handler; -pub mod instance_manager; -pub mod kv_storage; -pub mod kv_user_client; +pub mod m_executor; +pub mod m_http_handler; +pub mod m_instance_manager; +pub mod m_kv_user_client; +pub mod m_worker; pub mod wasm; pub mod wasm_host_funcs; -pub mod worker; // use axum::{extract::Path, routing::get, Router}; // // use lazy_static::lazy_static; // use lazy_static::lazy_static; diff --git a/src/worker/wasm_host_funcs/fs.rs b/src/worker/wasm_host_funcs/fs.rs index 6f404f6..a3b0c2a 100644 --- a/src/worker/wasm_host_funcs/fs.rs +++ b/src/worker/wasm_host_funcs/fs.rs @@ -1,5 +1,4 @@ -use super::{utils, HostFuncRegister}; -use crate::general::fs::fs; +use super::{utils, utils::m_fs, HostFuncRegister}; #[cfg(target_os = "macos")] use wasmer::{imports, Function, FunctionType, Imports}; @@ -16,17 +15,29 @@ type OpenFileArgs = (i32, i32, i32); fn open_file(caller: Caller, args: Vec) -> Result, HostFuncError> { let fname = utils::u8slice(&caller, args[0].to_i32(), args[1].to_i32()); let res = utils::mutref::(&caller, args[2].to_i32()); - *res = fs().open_file(std::str::from_utf8(fname).unwrap()).unwrap(); + if let Ok(f) = m_fs().open_file(std::str::from_utf8(fname).unwrap()) { + *res = f; + } else { + tracing::error!( + "function failed to open file {}", + std::str::from_utf8(fname).unwrap() + ); + *res = -1; + } Ok(vec![]) } fn read_file_at(caller: Caller, args: Vec) -> Result, HostFuncError> { let fd = args[0].to_i32(); + if fd < 0 { + tracing::error!("function read_file_at: invalid fd"); + return Ok(vec![]); + } let data = utils::mutu8sclice(&caller, args[1].to_i32(), args[2].to_i32()).unwrap(); let offset = args[3].to_i32(); let retlen = utils::mutref::(&caller, args[4].to_i32()); - *retlen = fs().read_file_at(fd, offset, data).unwrap() as i32; + *retlen = m_fs().read_file_at(fd, offset, data).unwrap() as i32; Ok(vec![]) } @@ -40,15 +51,17 @@ async fn read_file_at_async( args: Vec, _ctx: *mut T, ) -> Result, HostFuncError> { - tokio::task::spawn_blocking(move || { + if let Err(err) = tokio::task::spawn_blocking(move || { let fd = args[0].to_i32(); let data = utils::mutu8sclice(&caller, args[1].to_i32(), args[2].to_i32()).unwrap(); let offset = args[3].to_i32(); let retlen = utils::mutref::(&caller, args[4].to_i32()); - *retlen = fs().read_file_at(fd, offset, data).unwrap() as i32; + *retlen = m_fs().read_file_at(fd, offset, data).unwrap() as i32; }) .await - .unwrap(); + { + tracing::error!("function read_file_at_async: {}", err); + } Ok(vec![]) } @@ -57,7 +70,7 @@ fn read_file_at(fd: i32, data_ptr: i32, data_len: i32, offset: i32, retlen_ptr: let data = utils::mutu8sclice(&caller, args[1].to_i32(), args[2].to_i32()).unwrap(); let offset = args[3].to_i32(); let retlen = utils::mutref::(&caller, args[4].to_i32()); - *retlen = fs().read_file_at(fd, offset, data).unwrap() as i32; + *retlen = m_fs().read_file_at(fd, offset, data).unwrap() as i32; } pub(super) struct FsFuncsRegister; diff --git a/src/worker/wasm_host_funcs/kv.rs b/src/worker/wasm_host_funcs/kv.rs index 99d9df2..3b6ab1b 100644 --- a/src/worker/wasm_host_funcs/kv.rs +++ b/src/worker/wasm_host_funcs/kv.rs @@ -1,4 +1,4 @@ -use super::{utils, HostFuncRegister}; +use super::{utils, utils::m_kv_user_client, HostFuncRegister}; use crate::general::{ kv_interface::{KvInterface, KvOptions}, network::{ @@ -9,7 +9,6 @@ use crate::general::{ }, }, }; -use crate::worker::kv_user_client::kv_user_client; use moka::sync::Cache; use std::{sync::atomic::AtomicI32, time::Duration}; #[cfg(target_os = "macos")] @@ -219,7 +218,7 @@ async fn kv_batch_ope( } } // tracing::debug!("requests:{:?}", requests); - match kv_user_client() + match m_kv_user_client() .call( KvRequests { requests, diff --git a/src/worker/wasm_host_funcs/mod.rs b/src/worker/wasm_host_funcs/mod.rs index bea23ca..c9ca18f 100644 --- a/src/worker/wasm_host_funcs/mod.rs +++ b/src/worker/wasm_host_funcs/mod.rs @@ -2,10 +2,13 @@ use wasmedge_sdk::{ImportObject, ImportObjectBuilder, NeverType}; mod fs; mod kv; +mod result; use fs::FsFuncsRegister; use kv::KvFuncsRegister; +use crate::sys::LogicalModulesRef; + mod utils { use std::ptr::NonNull; @@ -13,8 +16,13 @@ mod utils { use wasmedge_sdk::{Caller, CallingFrame, Instance, Memory}; use crate::{ + general::m_fs::Fs, + sys::LogicalModulesRef, util::SendNonNull, - worker::{executor::FunctionCtx, kv_user_client::kv_user_client}, + worker::{ + m_executor::FunctionCtx, m_instance_manager::InstanceManager, + m_kv_user_client::KvUserClient, + }, }; trait WasmCtx { @@ -84,9 +92,7 @@ mod utils { pub fn current_app_fn_ctx(caller: &impl WasmCtx) -> SendNonNull { let app_fn = SendNonNull(NonNull::from( - kv_user_client() - .view - .instance_manager() + m_instance_manager() .instance_running_function .read() .get(&caller.instance().unwrap().name().unwrap()) @@ -94,6 +100,49 @@ mod utils { )); app_fn } + + lazy_static::lazy_static! { + pub(super) static ref MODULES: Option=None; + } + + pub fn m_kv_user_client() -> &'static KvUserClient { + unsafe { + &(*MODULES.as_ref().unwrap().inner.as_ptr()) + .as_ref() + .unwrap() + .kv_user_client + .as_ref() + .unwrap() + } + } + + pub fn m_fs<'a>() -> &'a Fs { + unsafe { + &(*MODULES.as_ref().unwrap().inner.as_ptr()) + .as_ref() + .unwrap() + .fs + } + } + + pub fn m_instance_manager() -> &'static InstanceManager { + unsafe { + &(*MODULES.as_ref().unwrap().inner.as_ptr()) + .as_ref() + .unwrap() + .instance_manager + .as_ref() + .unwrap() + } + } +} + +pub fn set_singleton_modules(modules: LogicalModulesRef) { + // *utils::MODULES = Some(modules); + unsafe { + *(&*utils::MODULES as *const _ as *mut _) = Some(modules); + } + assert!(utils::MODULES.is_some()); } // #[cfg(target_os = "macos")] @@ -115,9 +164,12 @@ trait HostFuncRegister { #[cfg(target_os = "linux")] pub fn new_import_obj() -> ImportObject { + use crate::worker::wasm_host_funcs::result::ResultFuncsRegister; + let builder = ImportObjectBuilder::new(); let builder = KvFuncsRegister {}.register(builder); let builder = FsFuncsRegister {}.register(builder); + let builder = ResultFuncsRegister.register(builder); builder.build::("env", None).unwrap() } diff --git a/src/worker/wasm_host_funcs/result.rs b/src/worker/wasm_host_funcs/result.rs new file mode 100644 index 0000000..ff7152c --- /dev/null +++ b/src/worker/wasm_host_funcs/result.rs @@ -0,0 +1,30 @@ +use super::{utils, HostFuncRegister}; + +#[cfg(target_os = "macos")] +use wasmer::{imports, Function, FunctionType, Imports}; + +#[cfg(target_os = "linux")] +use wasmedge_sdk::{ + error::HostFuncError, host_function, Caller, ImportObjectBuilder, NeverType, WasmValue, +}; + +// fname_ptr, fname_len, fd_ptr +type WriteResultArgs = (i32, i32); +#[cfg_attr(target_os = "linux", host_function)] +fn write_result(caller: Caller, args: Vec) -> Result, HostFuncError> { + let fname = utils::u8slice(&caller, args[0].to_i32(), args[1].to_i32()); + unsafe { utils::current_app_fn_ctx(&caller).0.as_mut() }.res = + Some(std::str::from_utf8(fname).unwrap().to_string()); + + Ok(vec![]) +} + +pub(super) struct ResultFuncsRegister; + +impl HostFuncRegister for ResultFuncsRegister { + fn register(&self, builder: ImportObjectBuilder) -> ImportObjectBuilder { + builder + .with_func::("write_result", write_result, None) + .unwrap() + } +}