diff --git a/.github/json_matrices/build-matrix.json b/.github/json_matrices/build-matrix.json index 642114e207..dff057084b 100644 --- a/.github/json_matrices/build-matrix.json +++ b/.github/json_matrices/build-matrix.json @@ -5,43 +5,19 @@ "RUNNER": "ubuntu-latest", "ARCH": "x64", "TARGET": "x86_64-unknown-linux-gnu", - "PACKAGE_MANAGERS": [ - "pypi", - "npm", - "maven" - ], + "PACKAGE_MANAGERS": ["pypi", "npm", "maven"], "run": "always", - "languages": [ - "python", - "node", - "java", - "go", - "dotnet" - ] + "languages": ["python", "node", "java", "go", "dotnet"] }, { "OS": "ubuntu", "NAMED_OS": "linux", - "RUNNER": [ - "self-hosted", - "Linux", - "ARM64" - ], + "RUNNER": ["self-hosted", "Linux", "ARM64"], "ARCH": "arm64", "TARGET": "aarch64-unknown-linux-gnu", - "PACKAGE_MANAGERS": [ - "pypi", - "npm", - "maven" - ], + "PACKAGE_MANAGERS": ["pypi", "npm", "maven"], "CONTAINER": "2_28", - "languages": [ - "python", - "node", - "java", - "go", - "dotnet" - ] + "languages": ["python", "node", "java", "go", "dotnet"] }, { "OS": "macos", @@ -49,18 +25,8 @@ "RUNNER": "macos-12", "ARCH": "x64", "TARGET": "x86_64-apple-darwin", - "PACKAGE_MANAGERS": [ - "pypi", - "npm", - "maven" - ], - "languages": [ - "python", - "node", - "java", - "go", - "dotnet" - ] + "PACKAGE_MANAGERS": ["pypi", "npm", "maven"], + "languages": ["python", "node", "java", "go", "dotnet"] }, { "OS": "macos", @@ -68,37 +34,19 @@ "RUNNER": "macos-latest", "ARCH": "arm64", "TARGET": "aarch64-apple-darwin", - "PACKAGE_MANAGERS": [ - "pypi", - "npm", - "maven" - ], - "languages": [ - "python", - "node", - "java", - "go", - "dotnet" - ] + "PACKAGE_MANAGERS": ["pypi", "npm", "maven"], + "languages": ["python", "node", "java", "go", "dotnet"] }, { "OS": "ubuntu", "NAMED_OS": "linux", "ARCH": "arm64", "TARGET": "aarch64-unknown-linux-musl", - "RUNNER": [ - "self-hosted", - "Linux", - "ARM64" - ], + "RUNNER": ["self-hosted", "Linux", "ARM64"], "IMAGE": "node:lts-alpine3.19", "CONTAINER_OPTIONS": "--user root --privileged --rm", - "PACKAGE_MANAGERS": [ - "npm" - ], - "languages": [ - "node" - ] + "PACKAGE_MANAGERS": ["npm"], + "languages": ["node"] }, { "OS": "ubuntu", @@ -108,12 +56,8 @@ "RUNNER": "ubuntu-latest", "IMAGE": "node:lts-alpine3.19", "CONTAINER_OPTIONS": "--user root --privileged", - "PACKAGE_MANAGERS": [ - "npm" - ], - "languages": [ - "node" - ] + "PACKAGE_MANAGERS": ["npm"], + "languages": ["node"] }, { "OS": "amazon-linux", @@ -123,12 +67,6 @@ "TARGET": "x86_64-unknown-linux-gnu", "IMAGE": "amazonlinux:latest", "PACKAGE_MANAGERS": [], - "languages": [ - "python", - "node", - "java", - "go", - "dotnet" - ] + "languages": ["python", "node", "java", "go", "dotnet"] } ] diff --git a/.github/json_matrices/supported-languages-versions.json b/.github/json_matrices/supported-languages-versions.json index cc9c9a5eea..8b22e7b090 100644 --- a/.github/json_matrices/supported-languages-versions.json +++ b/.github/json_matrices/supported-languages-versions.json @@ -22,6 +22,6 @@ { "language": "go", "versions": ["1.22.0", "1.18.10"], - "always-run-versions": ["1.22.0"] + "always-run-versions": ["1.22.0", "1.18.10"] } ] diff --git a/.github/workflows/java-cd.yml b/.github/workflows/java-cd.yml index 215ac6248e..f4c0146342 100644 --- a/.github/workflows/java-cd.yml +++ b/.github/workflows/java-cd.yml @@ -86,8 +86,6 @@ jobs: echo "No cleaning needed" fi - uses: actions/checkout@v4 - - - name: Set up JDK uses: actions/setup-java@v4 with: @@ -229,7 +227,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Set up JDK uses: actions/setup-java@v4 diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml index efed8d9da4..43539d3d6b 100644 --- a/.github/workflows/java.yml +++ b/.github/workflows/java.yml @@ -83,7 +83,6 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: gradle/actions/wrapper-validation@v3 @@ -207,7 +206,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: ./.github/workflows/lint-rust with: @@ -226,7 +224,6 @@ jobs: run: sudo chown -R $USER:$USER /home/ubuntu/actions-runner/_work/valkey-glide - uses: actions/checkout@v4 - - name: Set up JDK uses: actions/setup-java@v4 diff --git a/.github/workflows/lint-rust/action.yml b/.github/workflows/lint-rust/action.yml index 863ad305bc..35c5e313c5 100644 --- a/.github/workflows/lint-rust/action.yml +++ b/.github/workflows/lint-rust/action.yml @@ -14,7 +14,6 @@ runs: using: "composite" steps: - uses: actions/checkout@v4 - - name: Install Rust toolchain and protoc uses: ./.github/workflows/install-rust-and-protoc diff --git a/.github/workflows/redis-rs.yml b/.github/workflows/redis-rs.yml index cdc4967759..d0c1b00830 100644 --- a/.github/workflows/redis-rs.yml +++ b/.github/workflows/redis-rs.yml @@ -45,12 +45,11 @@ jobs: engine-version: "7.2.5" github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Cache dependencies + - name: Cache dependencies uses: Swatinem/rust-cache@v2 with: - cache-on-failure: true - workspaces: ./glide-core/redis-rs/redis - + cache-on-failure: true + workspaces: ./glide-core/redis-rs/redis - name: Build project run: cargo build --release diff --git a/glide-core/redis-rs/scripts/get_command_info.py b/glide-core/redis-rs/scripts/get_command_info.py index dcba666bff..4c719dd4d4 100644 --- a/glide-core/redis-rs/scripts/get_command_info.py +++ b/glide-core/redis-rs/scripts/get_command_info.py @@ -1,3 +1,4 @@ +# type: ignore import argparse import json import os diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index 4bea91dd83..3ac7743cec 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -1349,6 +1349,9 @@ export async function transactionTest( baseTransaction.xgroupDestroy(key9, groupName2); responseData.push(["xgroupDestroy(key9, groupName2)", true]); + baseTransaction.wait(1, 200); + responseData.push(["wait(1, 200)", 1]); + baseTransaction.rename(key9, key10); responseData.push(["rename(key9, key10)", "OK"]); baseTransaction.exists([key10]); @@ -1713,9 +1716,6 @@ export async function transactionTest( responseData.push(["sortReadOnly(key21)", ["1", "2", "3"]]); } - baseTransaction.wait(1, 200); - if (gte(version, "7.0.0")) responseData.push(["wait(1, 200)", 1]); - else responseData.push(["wait(1, 200)", 0]); return responseData; } diff --git a/python/Cargo.toml b/python/Cargo.toml index 16ec93f10c..aaf49762df 100644 --- a/python/Cargo.toml +++ b/python/Cargo.toml @@ -16,7 +16,7 @@ pyo3 = { version = "^0.22", features = [ "num-bigint", "gil-refs", ] } -bytes = { version = "1.6.0" } +bytes = { version = "^1.8" } redis = { path = "../glide-core/redis-rs/redis", features = [ "aio", "tokio-comp", diff --git a/python/python/glide/async_commands/server_modules/json.py b/python/python/glide/async_commands/server_modules/json.py index e4bff32b79..3c98672d9f 100644 --- a/python/python/glide/async_commands/server_modules/json.py +++ b/python/python/glide/async_commands/server_modules/json.py @@ -704,114 +704,6 @@ async def debug_memory( ) -async def arrlen( - client: TGlideClient, - key: TEncodable, - path: Optional[TEncodable] = None, -) -> Optional[TJsonResponse[int]]: - """ - Retrieves the length of the array at the specified `path` within the JSON document stored at `key`. - - Args: - client (TGlideClient): The client to execute the command. - key (TEncodable): The key of the JSON document. - path (Optional[TEncodable]): The path within the JSON document. Defaults to None. - - Returns: - Optional[TJsonResponse[int]]: - For JSONPath (`path` starts with `$`): - Returns a list of integer replies for every possible path, indicating the length of the array, - or None for JSON values matching the path that are not an array. - If `path` doesn't exist, an empty array will be returned. - For legacy path (`path` doesn't starts with `$`): - Returns the length of the array at `path`. - If multiple paths match, the length of the first array match is returned. - If the JSON value at `path` is not a array or if `path` doesn't exist, an error is raised. - If `key` doesn't exist, None is returned. - - Examples: - >>> from glide import json - >>> await json.set(client, "doc", "$", '{"a": [1, 2, 3], "b": {"a": [1, 2], "c": {"a": 42}}}') - b'OK' # JSON is successfully set for doc - >>> await json.arrlen(client, "doc", "$") - [None] # No array at the root path. - >>> await json.arrlen(client, "doc", "$.a") - [3] # Retrieves the length of the array at path $.a. - >>> await json.arrlen(client, "doc", "$..a") - [3, 2, None] # Retrieves lengths of arrays found at all levels of the path `..a`. - >>> await json.arrlen(client, "doc", "..a") - 3 # Legacy path retrieves the first array match at path `..a`. - >>> await json.arrlen(client, "non_existing_key", "$.a") - None # Returns None because the key does not exist. - - >>> await json.set(client, "doc", "$", '[1, 2, 3, 4]') - b'OK' # JSON is successfully set for doc - >>> await json.arrlen(client, "doc") - 4 # Retrieves lengths of arrays in root. - """ - args = ["JSON.ARRLEN", key] - if path: - args.append(path) - return cast( - Optional[TJsonResponse[int]], - await client.custom_command(args), - ) - - -async def arrlen( - client: TGlideClient, - key: TEncodable, - path: Optional[TEncodable] = None, -) -> Optional[TJsonResponse[int]]: - """ - Retrieves the length of the array at the specified `path` within the JSON document stored at `key`. - - Args: - client (TGlideClient): The client to execute the command. - key (TEncodable): The key of the JSON document. - path (Optional[TEncodable]): The path within the JSON document. Defaults to None. - - Returns: - Optional[TJsonResponse[int]]: - For JSONPath (`path` starts with `$`): - Returns a list of integer replies for every possible path, indicating the length of the array, - or None for JSON values matching the path that are not an array. - If `path` doesn't exist, an empty array will be returned. - For legacy path (`path` doesn't starts with `$`): - Returns the length of the array at `path`. - If multiple paths match, the length of the first array match is returned. - If the JSON value at `path` is not a array or if `path` doesn't exist, an error is raised. - If `key` doesn't exist, None is returned. - - Examples: - >>> from glide import json - >>> await json.set(client, "doc", "$", '{"a": [1, 2, 3], "b": {"a": [1, 2], "c": {"a": 42}}}') - b'OK' # JSON is successfully set for doc - >>> await json.arrlen(client, "doc", "$") - [None] # No array at the root path. - >>> await json.arrlen(client, "doc", "$.a") - [3] # Retrieves the length of the array at path $.a. - >>> await json.arrlen(client, "doc", "$..a") - [3, 2, None] # Retrieves lengths of arrays found at all levels of the path `..a`. - >>> await json.arrlen(client, "doc", "..a") - 3 # Legacy path retrieves the first array match at path `..a`. - >>> await json.arrlen(client, "non_existing_key", "$.a") - None # Returns None because the key does not exist. - - >>> await json.set(client, "doc", "$", '[1, 2, 3, 4]') - b'OK' # JSON is successfully set for doc - >>> await json.arrlen(client, "doc") - 4 # Retrieves lengths of arrays in root. - """ - args = ["JSON.ARRLEN", key] - if path: - args.append(path) - return cast( - Optional[TJsonResponse[int]], - await client.custom_command(args), - ) - - async def delete( client: TGlideClient, key: TEncodable, diff --git a/python/python/tests/test_pubsub.py b/python/python/tests/test_pubsub.py index 4c2e5757e8..c6335ae242 100644 --- a/python/python/tests/test_pubsub.py +++ b/python/python/tests/test_pubsub.py @@ -13,9 +13,9 @@ GlideClusterClientConfiguration, ProtocolVersion, ) -from glide.constants import OK, TEncodable +from glide.constants import OK from glide.exceptions import ConfigurationError -from glide.glide_client import BaseClient, GlideClient, GlideClusterClient, TGlideClient +from glide.glide_client import GlideClient, GlideClusterClient, TGlideClient from tests.conftest import create_client from tests.utils.utils import check_if_server_version_lt, get_random_string diff --git a/python/src/lib.rs b/python/src/lib.rs index d00034e8cf..8a1a0d3444 100644 --- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -10,6 +10,7 @@ use pyo3::prelude::*; use pyo3::types::{PyAny, PyBool, PyBytes, PyDict, PyFloat, PyList, PySet}; use pyo3::Python; use redis::Value; +use std::sync::Arc; pub const DEFAULT_TIMEOUT_IN_MILLISECONDS: u32 = glide_core::client::DEFAULT_RESPONSE_TIMEOUT.as_millis() as u32; @@ -113,31 +114,41 @@ fn glide(_py: Python, m: &Bound) -> PyResult<()> { DEFAULT_TIMEOUT_IN_MILLISECONDS, )?; m.add("MAX_REQUEST_ARGS_LEN", MAX_REQUEST_ARGS_LEN)?; + m.add_function(wrap_pyfunction!(py_log, m)?)?; + m.add_function(wrap_pyfunction!(py_init, m)?)?; + m.add_function(wrap_pyfunction!(start_socket_listener_external, m)?)?; + m.add_function(wrap_pyfunction!(value_from_pointer, m)?)?; + m.add_function(wrap_pyfunction!(create_leaked_value, m)?)?; + m.add_function(wrap_pyfunction!(create_leaked_bytes_vec, m)?)?; - #[pyfn(m)] + #[pyfunction] fn py_log(log_level: Level, log_identifier: String, message: String) { log(log_level, log_identifier, message); } - #[pyfn(m)] + #[pyfunction] #[pyo3(signature = (level=None, file_name=None))] fn py_init(level: Option, file_name: Option<&str>) -> Level { init(level, file_name) } - - #[pyfn(m)] + #[pyfunction] fn start_socket_listener_external(init_callback: PyObject) -> PyResult { - start_socket_listener(move |socket_path| { - Python::with_gil(|py| { - match socket_path { - Ok(path) => { - let _ = init_callback.call_bound(py, (path, py.None()), None); - } - Err(error_message) => { - let _ = init_callback.call_bound(py, (py.None(), error_message), None); - } - }; - }); + let init_callback = Arc::new(init_callback); + start_socket_listener({ + let init_callback = Arc::clone(&init_callback); + move |socket_path| { + let init_callback = Arc::clone(&init_callback); + Python::with_gil(|py| { + match socket_path { + Ok(path) => { + let _ = init_callback.call_bound(py, (path, py.None()), None); + } + Err(error_message) => { + let _ = init_callback.call_bound(py, (py.None(), error_message), None); + } + }; + }); + } }); Ok(Python::with_gil(|py| "OK".into_py(py))) } @@ -213,13 +224,13 @@ fn glide(_py: Python, m: &Bound) -> PyResult<()> { } } - #[pyfn(m)] + #[pyfunction] pub fn value_from_pointer(py: Python, pointer: u64) -> PyResult { let value = unsafe { Box::from_raw(pointer as *mut Value) }; resp_value_to_py(py, *value) } - #[pyfn(m)] + #[pyfunction] /// This function is for tests that require a value allocated on the heap. /// Should NOT be used in production. pub fn create_leaked_value(message: String) -> usize { @@ -227,7 +238,7 @@ fn glide(_py: Python, m: &Bound) -> PyResult<()> { Box::leak(Box::new(value)) as *mut Value as usize } - #[pyfn(m)] + #[pyfunction] pub fn create_leaked_bytes_vec(args_vec: Vec<&PyBytes>) -> usize { // Convert the bytes vec -> Bytes vector let bytes_vec: Vec = args_vec @@ -241,7 +252,6 @@ fn glide(_py: Python, m: &Bound) -> PyResult<()> { } Ok(()) } - impl From for Level { fn from(level: logger_core::Level) -> Self { match level {