diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..0a45842 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,118 @@ +name: Check + +on: + pull_request: + workflow_dispatch: + +env: + cache_nonce: 0 + +jobs: + build: + name: Build + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Cache prebuilt binaries + uses: actions/cache@v4 + with: + path: ~/.cache/storage-bindings + key: storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}-${{ env.cache_nonce }} + restore-keys: | + storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}- + storage-bindings-${{ runner.os }}- + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang libclang-dev + + - name: Install mise + uses: jdx/mise-action@v3 + with: + enable: true + cache: true + + - name: Run cargo build + run: cargo build --all-features --release + + lint: + name: Lint + runs-on: ubuntu-latest + timeout-minutes: 30 + needs: build + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Cache prebuilt binaries + uses: actions/cache@v4 + with: + path: ~/.cache/storage-bindings + key: storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}-${{ env.cache_nonce }} + restore-keys: | + storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}- + storage-bindings-${{ runner.os }}- + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang libclang-dev + + - name: Install mise + uses: jdx/mise-action@v3 + with: + enable: true + cache: true + + - name: Install rustfmt and clippy + run: rustup component add rustfmt clippy + + - name: Run cargo check + run: cargo check --all-targets --all-features + + - name: Run cargo fmt + run: cargo fmt --all -- --check + + - name: Run cargo clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + test: + name: Test + runs-on: ubuntu-latest + timeout-minutes: 30 + needs: build + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Cache prebuilt binaries + uses: actions/cache@v4 + with: + path: ~/.cache/storage-bindings + key: storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}-${{ env.cache_nonce }} + restore-keys: | + storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}- + storage-bindings-${{ runner.os }}- + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang libclang-dev + + - name: Install mise + uses: jdx/mise-action@v3 + with: + enable: true + cache: true + + - name: Run cargo test + run: cargo test --all-features + env: + TZ: UTC diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..8ff9414 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,159 @@ +name: Publish + +on: + push: + tags: + - "v*" + branches: + - main + workflow_dispatch: + +env: + cache_nonce: 0 + +jobs: + build: + name: Build + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Cache prebuilt binaries + uses: actions/cache@v4 + with: + path: ~/.cache/storage-bindings + key: storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}-${{ env.cache_nonce }} + restore-keys: | + storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}- + storage-bindings-${{ runner.os }}- + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang libclang-dev + + - name: Install mise + uses: jdx/mise-action@v3 + with: + enable: true + cache: true + + - name: Run cargo build + run: cargo build --all-features --release + + lint: + name: Lint + runs-on: ubuntu-latest + timeout-minutes: 30 + needs: build + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Cache prebuilt binaries + uses: actions/cache@v4 + with: + path: ~/.cache/storage-bindings + key: storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}-${{ env.cache_nonce }} + restore-keys: | + storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}- + storage-bindings-${{ runner.os }}- + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang libclang-dev + + - name: Install mise + uses: jdx/mise-action@v3 + with: + enable: true + cache: true + + - name: Install rustfmt and clippy + run: rustup component add rustfmt clippy + + - name: Run cargo check + run: cargo check --all-targets --all-features + + - name: Run cargo fmt + run: cargo fmt --all -- --check + + - name: Run cargo clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + test: + name: Test + runs-on: ubuntu-latest + timeout-minutes: 30 + needs: build + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Cache prebuilt binaries + uses: actions/cache@v4 + with: + path: ~/.cache/storage-bindings + key: storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}-${{ env.cache_nonce }} + restore-keys: | + storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}- + storage-bindings-${{ runner.os }}- + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang libclang-dev + + - name: Install mise + uses: jdx/mise-action@v3 + with: + enable: true + cache: true + + - name: Run cargo test + run: cargo test --all-features + env: + TZ: UTC + + publish: + name: Publish + runs-on: ubuntu-latest + timeout-minutes: 30 + needs: [lint, test, build] + if: startsWith(github.ref, 'refs/tags/v') + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Cache prebuilt binaries + uses: actions/cache@v4 + with: + path: ~/.cache/storage-bindings + key: storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}-${{ env.cache_nonce }} + restore-keys: | + storage-bindings-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}- + storage-bindings-${{ runner.os }}- + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang libclang-dev + + - name: Install mise + uses: jdx/mise-action@v3 + with: + enable: true + cache: true + + - name: Login to crates.io + run: echo "${{ secrets.CRATES_API_TOKEN }}" | cargo login + + - name: Publish to crates.io + run: cargo publish --all-features diff --git a/lefthook.yml b/lefthook.yml index 1a4728d..796e64a 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -43,6 +43,6 @@ pre-commit: parallel: true jobs: - - run: cargo check --workspace - - run: cargo fmt -- --check - - run: cargo clippy + - run: cargo check --all-targets --all-features + - run: cargo fmt --all -- --check + - run: cargo clippy --all-targets --all-features -- -D warnings diff --git a/src/callback.rs b/src/callback.rs index 5548d94..69b8e11 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -32,7 +32,9 @@ impl Default for CallbackContext { impl CallbackContext { pub fn new() -> Self { let id = { - let mut next_id = NEXT_CALLBACK_ID.lock().unwrap(); + let mut next_id = NEXT_CALLBACK_ID + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); let id = *next_id; *next_id += 1; id @@ -133,6 +135,9 @@ impl Drop for CallbackContext { fn drop(&mut self) { if let Ok(mut registry) = CALLBACK_REGISTRY.lock() { registry.remove(&self.id); + } else if let Err(poisoned) = CALLBACK_REGISTRY.lock() { + let mut registry = poisoned.into_inner(); + registry.remove(&self.id); } } } @@ -152,7 +157,9 @@ impl CallbackFuture { let context = Arc::new(CallbackContext::new()); { - let mut registry = CALLBACK_REGISTRY.lock().unwrap(); + let mut registry = CALLBACK_REGISTRY + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); registry.insert(context.id(), context.clone()); } @@ -219,7 +226,9 @@ pub fn with_libstorage_lock(f: F) -> R where F: FnOnce() -> R, { - let _lock = LIBSTORAGE_MUTEX.lock().unwrap(); + let _lock = LIBSTORAGE_MUTEX + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); f() } @@ -253,6 +262,9 @@ pub unsafe extern "C" fn c_callback( let context = { if let Ok(registry) = CALLBACK_REGISTRY.lock() { registry.get(&callback_id).cloned() + } else if let Err(poisoned) = CALLBACK_REGISTRY.lock() { + let registry = poisoned.into_inner(); + registry.get(&callback_id).cloned() } else { None } diff --git a/tests/thread_safe_tests.rs b/tests/thread_safe_tests.rs index 2036627..79561f4 100644 --- a/tests/thread_safe_tests.rs +++ b/tests/thread_safe_tests.rs @@ -73,8 +73,8 @@ async fn test_concurrent_access() { } } -#[test] -fn test_send_sync_traits() { +#[tokio::test(flavor = "multi_thread")] +async fn test_send_sync_traits() { fn assert_send() {} fn assert_sync() {} @@ -88,8 +88,8 @@ fn test_send_sync_traits() { assert_send::>(); } -#[test] -fn test_clone_trait() { +#[tokio::test(flavor = "multi_thread")] +async fn test_clone_trait() { let temp_dir = tempdir().unwrap(); let config = StorageConfig::new().data_dir(temp_dir.path());