Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: CI

permissions:
contents: read

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown

- name: Cache cargo dependencies
uses: Swatinem/rust-cache@v2

- name: Check WASM compilation
run: cargo check --target wasm32-unknown-unknown

format:
name: Format
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt

- name: Check formatting
run: cargo fmt --all -- --check

clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
components: clippy

- name: Cache cargo dependencies
uses: Swatinem/rust-cache@v2

- name: Run clippy
run: cargo clippy --target wasm32-unknown-unknown -- -D warnings
79 changes: 79 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Release

run-name: "Release run '${{ github.head_ref || github.ref_name }}'"

on:
workflow_dispatch:

jobs:
semver:
name: semver
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check semver
uses: obi1kenobi/cargo-semver-checks-action@v2

release:
name: Process Release
runs-on: ubuntu-latest
needs: semver
permissions:
contents: write # required for creating tags and GitHub releases
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Cache dependencies
uses: Swatinem/rust-cache@v2

- name: Install a TOML parser
run: |
curl -L https://github.com/tamasfe/taplo/releases/download/0.8.1/taplo-full-linux-x86_64.gz | gunzip - > taplo
chmod +x taplo
sudo mv taplo /usr/bin/taplo

- name: Configure git
run: |
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git config --add --bool push.autoSetupRemote true

- name: Extract version from branch name
id: version
run: |
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
VERSION="${BRANCH_NAME#release/}"
echo "Version from branch: $VERSION"

# Validate version matches Cargo.toml
CARGO_VERSION=$(taplo get -f Cargo.toml "package.version")
if [ "$VERSION" != "$CARGO_VERSION" ]; then
echo "Error: Branch version ($VERSION) doesn't match Cargo.toml version ($CARGO_VERSION)"
exit 1
fi

echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Create and push tag
run: |
git tag -a "v${{ steps.version.outputs.version }}" -m "Release version ${{ steps.version.outputs.version }}"
git push origin "v${{ steps.version.outputs.version }}"

- name: Publish crate
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.version.outputs.version }}
name: Release ${{ steps.version.outputs.version }}
draft: false
prerelease: false
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "indxdb"
publish = true
edition = "2021"
version = "0.11.0"
version = "0.12.0"
readme = "CARGO.md"
authors = ["Tobie Morgan Hitchcock <tobie@surrealdb.com>"]
description = "A key-value database engine abstraction layer for IndexedDB running in WASM"
Expand Down
96 changes: 70 additions & 26 deletions src/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ impl Transaction {

/// Open a fresh read-only IDB store for a single read request.
fn fresh_read_store(&self) -> Result<Store, Error> {
let tx = self.db.transaction(&["kv"], TransactionMode::ReadOnly)
.map_err(|_| Error::TxError)?;
let tx =
self.db.transaction(&["kv"], TransactionMode::ReadOnly).map_err(|_| Error::TxError)?;
tx.store("kv").map_err(|_| Error::TxError)
}

Expand Down Expand Up @@ -145,8 +145,8 @@ impl Transaction {
return Ok(());
}

let flush_tx = self.db.transaction(&["kv"], TransactionMode::ReadWrite)
.map_err(|_| Error::TxError)?;
let flush_tx =
self.db.transaction(&["kv"], TransactionMode::ReadWrite).map_err(|_| Error::TxError)?;
let flush_store = flush_tx.store("kv").map_err(|_| Error::TxError)?;

// Build an iterator of (JsValue, Option<JsValue>) for put_all, and
Expand Down Expand Up @@ -308,9 +308,13 @@ impl Transaction {
if self.done {
return Err(Error::TxClosed);
}
let Range { start, end } = rng;
let Range {
start,
end,
} = rng;
let dir = Some(Direction::Next);
let kr = KeyRange::bound(&start.clone().convert(), &end.clone().convert(), None, Some(true));
let kr =
KeyRange::bound(&start.clone().convert(), &end.clone().convert(), None, Some(true));
let kr = kr.map_err(|e| Error::IndexedDbError(e.to_string()))?;

let store = self.fresh_read_store()?;
Expand All @@ -321,13 +325,19 @@ impl Transaction {
let key: Key = k.convert();
match self.buffer.get(&key) {
Some(Buffered::Del) => {}
_ => { merged.insert(key, ()); }
_ => {
merged.insert(key, ());
}
}
}
for (key, op) in self.buffer.range(start..end) {
match op {
Buffered::Set(_) => { merged.insert(key.clone(), ()); }
Buffered::Del => { merged.remove(key); }
Buffered::Set(_) => {
merged.insert(key.clone(), ());
}
Buffered::Del => {
merged.remove(key);
}
}
}

Expand All @@ -339,9 +349,13 @@ impl Transaction {
if self.done {
return Err(Error::TxClosed);
}
let Range { start, end } = rng;
let Range {
start,
end,
} = rng;
let dir = Some(Direction::Prev);
let kr = KeyRange::bound(&end.clone().convert(), &start.clone().convert(), None, Some(true));
let kr =
KeyRange::bound(&end.clone().convert(), &start.clone().convert(), None, Some(true));
let kr = kr.map_err(|e| Error::IndexedDbError(e.to_string()))?;

let store = self.fresh_read_store()?;
Expand All @@ -352,13 +366,19 @@ impl Transaction {
let key: Key = k.convert();
match self.buffer.get(&key) {
Some(Buffered::Del) => {}
_ => { merged.insert(key, ()); }
_ => {
merged.insert(key, ());
}
}
}
for (key, op) in self.buffer.range(start..end) {
match op {
Buffered::Set(_) => { merged.insert(key.clone(), ()); }
Buffered::Del => { merged.remove(key); }
Buffered::Set(_) => {
merged.insert(key.clone(), ());
}
Buffered::Del => {
merged.remove(key);
}
}
}

Expand All @@ -370,9 +390,13 @@ impl Transaction {
if self.done {
return Err(Error::TxClosed);
}
let Range { start, end } = rng;
let Range {
start,
end,
} = rng;
let dir = Some(Direction::Next);
let kr = KeyRange::bound(&start.clone().convert(), &end.clone().convert(), None, Some(true));
let kr =
KeyRange::bound(&start.clone().convert(), &end.clone().convert(), None, Some(true));
let kr = kr.map_err(|e| Error::IndexedDbError(e.to_string()))?;

let store = self.fresh_read_store()?;
Expand All @@ -384,14 +408,22 @@ impl Transaction {
let val: Val = v.convert();
match self.buffer.get(&key) {
Some(Buffered::Del) => {}
Some(Buffered::Set(bv)) => { merged.insert(key, bv.clone()); }
None => { merged.insert(key, val); }
Some(Buffered::Set(bv)) => {
merged.insert(key, bv.clone());
}
None => {
merged.insert(key, val);
}
}
}
for (key, op) in self.buffer.range(start..end) {
match op {
Buffered::Set(v) => { merged.insert(key.clone(), v.clone()); }
Buffered::Del => { merged.remove(key); }
Buffered::Set(v) => {
merged.insert(key.clone(), v.clone());
}
Buffered::Del => {
merged.remove(key);
}
}
}

Expand All @@ -403,9 +435,13 @@ impl Transaction {
if self.done {
return Err(Error::TxClosed);
}
let Range { start, end } = rng;
let Range {
start,
end,
} = rng;
let dir = Some(Direction::Prev);
let kr = KeyRange::bound(&end.clone().convert(), &start.clone().convert(), None, Some(true));
let kr =
KeyRange::bound(&end.clone().convert(), &start.clone().convert(), None, Some(true));
let kr = kr.map_err(|e| Error::IndexedDbError(e.to_string()))?;

let store = self.fresh_read_store()?;
Expand All @@ -417,14 +453,22 @@ impl Transaction {
let val: Val = v.convert();
match self.buffer.get(&key) {
Some(Buffered::Del) => {}
Some(Buffered::Set(bv)) => { merged.insert(key, bv.clone()); }
None => { merged.insert(key, val); }
Some(Buffered::Set(bv)) => {
merged.insert(key, bv.clone());
}
None => {
merged.insert(key, val);
}
}
}
for (key, op) in self.buffer.range(start..end) {
match op {
Buffered::Set(v) => { merged.insert(key.clone(), v.clone()); }
Buffered::Del => { merged.remove(key); }
Buffered::Set(v) => {
merged.insert(key.clone(), v.clone());
}
Buffered::Del => {
merged.remove(key);
}
}
}

Expand Down
Loading