From 58427772b7f72dd2a7f5df58e6fa019c595f51a0 Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Mon, 3 Nov 2025 10:06:44 +0200 Subject: [PATCH 1/4] refactor: rename zrange to zrange_by_score and update related documentation --- examples/key-value/src/lib.rs | 6 +++--- src/proxywasm/key_value.rs | 29 +++++++++++++++++++++++------ src/proxywasm/mod.rs | 2 +- wit/key-value.wit | 12 ++++++------ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/examples/key-value/src/lib.rs b/examples/key-value/src/lib.rs index 4722689..cd83067 100644 --- a/examples/key-value/src/lib.rs +++ b/examples/key-value/src/lib.rs @@ -79,12 +79,12 @@ fn main(req: Request) -> Result> { } body.write_all(b"zrange()\n")?; - match store.zrange("myset", 0.0, 100.0) { + match store.zrange_by_score("myset", 0.0, 100.0) { Ok(values) => { - for value in values { + for (value, score) in values { body.write_all(b"get_by_range=")?; body.extend(value); - body.write_all(b"\n")?; + body.write_all(format!(", {}\n", score).as_bytes())?; } } Err(error) => { diff --git a/src/proxywasm/key_value.rs b/src/proxywasm/key_value.rs index e1189c1..8c86338 100644 --- a/src/proxywasm/key_value.rs +++ b/src/proxywasm/key_value.rs @@ -121,15 +121,17 @@ impl Store { } } - /// Get the values associated with the specified `key` stored in sorted set + /// Get all the elements with score from the sorted set at `key` with a f64 score between min and max + /// (including elements with score equal to min or max). The elements are considered to be ordered from low to high + /// scores. /// - /// Returns empty `Vec` if the key does not exist or min and max are out of index. - pub fn zrange(&self, key: &str, min: f64, max: f64) -> Result>, Error> { + /// Returns empty `Vec` if the key does not exist or min and max are out of score. + pub fn zrange_by_score(&self, key: &str, min: f64, max: f64) -> Result, f64)>, Error> { let mut return_data: *mut u8 = null_mut(); let mut return_size: usize = 0; unsafe { - match super::proxy_kv_store_zrange( + match super::proxy_kv_store_zrange_by_score( self.handle, key.as_ptr(), key.len(), @@ -142,9 +144,24 @@ impl Store { if !return_data.is_null() { let data = Vec::from_raw_parts(return_data, return_size, return_size); - let data: Vec> = utils::deserialize_list(&data) + let data: Vec<(Vec, f64)> = utils::deserialize_list(&data) .into_iter() - .map(|v| v.to_vec()) + .map(|v| { + let mut value = v.to_vec(); + let sz = size_of::(); + if value.len() > sz { + let npos = value.len() - sz; + let score = value.split_off(npos); + let score = f64::from_le_bytes( + <[u8; 8]>::try_from(&score[0..sz]).expect("Failed to convert score bytes to f64: expected 8 bytes"), + ); + (value, score) + } else { + // return and empty vector and 0.0 score if deserialization fails + // empty key should never happen + (vec![], 0.0) + } + }) .collect(); Ok(data) } else { diff --git a/src/proxywasm/mod.rs b/src/proxywasm/mod.rs index edc8c43..df958ad 100644 --- a/src/proxywasm/mod.rs +++ b/src/proxywasm/mod.rs @@ -35,7 +35,7 @@ extern "C" { return_value_size: *mut usize, ) -> u32; - fn proxy_kv_store_zrange( + fn proxy_kv_store_zrange_by_score( handle: u32, key_data: *const u8, key_size: usize, diff --git a/wit/key-value.wit b/wit/key-value.wit index 93b382d..6a9c2e9 100644 --- a/wit/key-value.wit +++ b/wit/key-value.wit @@ -1,7 +1,5 @@ interface key-value { type value = list; - type list-result = list; - type zlist-result = list>; /// FastEdge key-value persistent store resource resource store { @@ -21,16 +19,18 @@ interface key-value { /// Returns an array of elements as a list of keys. scan: func(pattern: string) -> result, error>; - /// Get the values associated with the specified `key` stored in sorted set ordered by f64 score + /// Get all the elements with score from the sorted set at `key` with a f64 score between min and max + /// (including elements with score equal to min or max). The elements are considered to be ordered from low to high + /// scores. /// - /// Returns empty `Vec` if the key does not exist or min and max are out of index. - zrange: func(key: string, min: f64, max: f64) -> result; + /// Returns empty `Vec` if the key does not exist or min and max are out of score. + zrange-by-score: func(key: string, min: f64, max: f64) -> result>, error>; /// Interface to scan through a sorted set by key /// It matches glob-style pattern filter on each elements from the retrieved collection. /// /// Returns an array of elements as a list of value of the Sorted Set. - zscan: func(key: string, pattern: string) -> result; + zscan: func(key: string, pattern: string) -> result>, error>; /// Determines whether a given item was added to a Bloom filter. /// From 637e055d5ca813c17e18aa792779b2b5de37d86c Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Mon, 3 Nov 2025 16:17:55 +0200 Subject: [PATCH 2/4] refactor: remove all WIT files to add its as submodule --- wit/dictionary.wit | 6 ----- wit/http-client.wit | 5 ---- wit/http-handler.wit | 4 ---- wit/http.wit | 38 ------------------------------- wit/key-value.wit | 54 -------------------------------------------- wit/secret.wit | 20 ---------------- wit/world.wit | 12 ---------- 7 files changed, 139 deletions(-) delete mode 100644 wit/dictionary.wit delete mode 100644 wit/http-client.wit delete mode 100644 wit/http-handler.wit delete mode 100644 wit/http.wit delete mode 100644 wit/key-value.wit delete mode 100644 wit/secret.wit delete mode 100644 wit/world.wit diff --git a/wit/dictionary.wit b/wit/dictionary.wit deleted file mode 100644 index be0eb3b..0000000 --- a/wit/dictionary.wit +++ /dev/null @@ -1,6 +0,0 @@ -interface dictionary { - /// Get the value associated with the specified `key` - /// - /// Returns `ok(none)` if the key does not exist. - get: func(name: string) -> option; -} \ No newline at end of file diff --git a/wit/http-client.wit b/wit/http-client.wit deleted file mode 100644 index 8e58295..0000000 --- a/wit/http-client.wit +++ /dev/null @@ -1,5 +0,0 @@ -interface http-client { - use http.{request, response, error}; - - send-request: func(req: request) -> result; -} diff --git a/wit/http-handler.wit b/wit/http-handler.wit deleted file mode 100644 index e66a319..0000000 --- a/wit/http-handler.wit +++ /dev/null @@ -1,4 +0,0 @@ -interface http-handler { - use http.{request, response}; - process: func(req: request) -> response; -} diff --git a/wit/http.wit b/wit/http.wit deleted file mode 100644 index de8f11e..0000000 --- a/wit/http.wit +++ /dev/null @@ -1,38 +0,0 @@ -interface http { - type http-status = u16; - type body = list; - type headers = list>; - type uri = string; - - enum method { - get, - post, - put, - delete, - head, - patch, - options - } - - record request { - method: method, - uri: uri, - headers: headers, - body: option, - } - - record response { - status: http-status, - headers: option, - body: option, - } - - enum error { - success, - destination-not-allowed, - invalid-url, - request-error, - runtime-error, - too-many-requests, - } -} diff --git a/wit/key-value.wit b/wit/key-value.wit deleted file mode 100644 index 6a9c2e9..0000000 --- a/wit/key-value.wit +++ /dev/null @@ -1,54 +0,0 @@ -interface key-value { - type value = list; - - /// FastEdge key-value persistent store resource - resource store { - /// Open the store with the specified name. - /// - /// `error::no-such-store` will be raised if the `name` is not recognized. - open: static func(name: string) -> result; - - /// Get the value associated with the specified `key` - /// - /// Returns `ok(none)` if the key does not exist. - get: func(key: string) -> result, error>; - - /// Interface to scan over keys in the store. - /// It matches glob-style pattern filter on each element from the retrieved collection. - /// - /// Returns an array of elements as a list of keys. - scan: func(pattern: string) -> result, error>; - - /// Get all the elements with score from the sorted set at `key` with a f64 score between min and max - /// (including elements with score equal to min or max). The elements are considered to be ordered from low to high - /// scores. - /// - /// Returns empty `Vec` if the key does not exist or min and max are out of score. - zrange-by-score: func(key: string, min: f64, max: f64) -> result>, error>; - - /// Interface to scan through a sorted set by key - /// It matches glob-style pattern filter on each elements from the retrieved collection. - /// - /// Returns an array of elements as a list of value of the Sorted Set. - zscan: func(key: string, pattern: string) -> result>, error>; - - /// Determines whether a given item was added to a Bloom filter. - /// - /// Returns one of these replies: 'true' means that, with high probability, item was already added to the filter, - /// and 'false' means that key does not exist or that item had not been added to the filter. - bf-exists: func(key: string, item: string) -> result; - } - - /// The set of errors which may be raised by functions in this interface - variant error { - /// The host does not recognize the store label requested. - no-such-store, - /// The requesting component does not have access to the specified store - /// (which may or may not exist). - access-denied, - /// Some unexpected internal error has occurred. - internal-error, - /// Some implementation-specific error has occurred (e.g. I/O) - other(string) - } -} \ No newline at end of file diff --git a/wit/secret.wit b/wit/secret.wit deleted file mode 100644 index ab61507..0000000 --- a/wit/secret.wit +++ /dev/null @@ -1,20 +0,0 @@ -interface secret { - /// Get the secret associated with the specified `key` efective at current timestamp. - /// Returns `ok(none)` if the key does not exist. - get: func(key: string) -> result, error>; - - /// Get the secret associated with the specified `key` effective `at` given timestamp in seconds. - /// Returns `ok(none)` if the key does not exist. - get-effective-at: func(key: string, at: u32) -> result, error>; - - /// The set of errors which may be raised by functions in this interface - variant error { - /// The requesting component does not have access to the specified key - /// (which may or may not exist). - access-denied, - /// Decryption error. - decrypt-error, - /// Some implementation-specific error has occurred (e.g. I/O) - other(string) - } -} \ No newline at end of file diff --git a/wit/world.wit b/wit/world.wit deleted file mode 100644 index 9c23fe1..0000000 --- a/wit/world.wit +++ /dev/null @@ -1,12 +0,0 @@ -package gcore:fastedge; - -world reactor { - import http; - import http-client; - - import dictionary; - import secret; - import key-value; - - export http-handler; -} \ No newline at end of file From 17be7ffb794955cf58f66b3c81fa331661693957 Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Mon, 3 Nov 2025 16:19:46 +0200 Subject: [PATCH 3/4] feat: add wit submodule for improved dependency management --- .gitmodules | 3 +++ wit | 1 + 2 files changed, 4 insertions(+) create mode 160000 wit diff --git a/.gitmodules b/.gitmodules index 99fff1b..1c13a03 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "wasi-nn"] path = wasi-nn url = https://github.com/WebAssembly/wasi-nn.git +[submodule "wit"] + path = wit + url = https://github.com/G-Core/FastEdge-wit.git diff --git a/wit b/wit new file mode 160000 index 0000000..561aa99 --- /dev/null +++ b/wit @@ -0,0 +1 @@ +Subproject commit 561aa99135425fb2a7a01feb989614fcbd083a50 From a88e2bafa7bd38c6e3fa2bbfbf5555cb366cb897 Mon Sep 17 00:00:00 2001 From: Ruslan Pislari Date: Tue, 4 Nov 2025 10:24:22 +0200 Subject: [PATCH 4/4] Update src/proxywasm/key_value.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/proxywasm/key_value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proxywasm/key_value.rs b/src/proxywasm/key_value.rs index 8c86338..37383cb 100644 --- a/src/proxywasm/key_value.rs +++ b/src/proxywasm/key_value.rs @@ -157,7 +157,7 @@ impl Store { ); (value, score) } else { - // return and empty vector and 0.0 score if deserialization fails + // return an empty vector and 0.0 score if deserialization fails // empty key should never happen (vec![], 0.0) }