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
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ on:
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
Expand Down
23 changes: 22 additions & 1 deletion .github/workflows/postgres-extension-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ on:
- '.github/workflows/postgres-extension-ci.yml'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
Expand Down Expand Up @@ -101,6 +105,10 @@ jobs:
run: cargo pgrx init --pg${{ matrix.pg_version }}=/opt/homebrew/opt/postgresql@${{ matrix.pg_version }}/bin/pg_config
working-directory: crates/ruvector-postgres

- name: Configure macOS extension linking
if: runner.os == 'macOS'
run: echo 'RUSTFLAGS=-D warnings -C link-arg=-undefined -C link-arg=dynamic_lookup' >> "$GITHUB_ENV"

- name: Check code formatting
run: cargo fmt --all -- --check
working-directory: crates/ruvector-postgres
Expand Down Expand Up @@ -159,6 +167,7 @@ jobs:
benchmark:
name: Benchmark
runs-on: ubuntu-latest
timeout-minutes: 30
if: github.event_name == 'pull_request'

steps:
Expand All @@ -185,7 +194,19 @@ jobs:
working-directory: crates/ruvector-postgres

- name: Run benchmarks
run: cargo bench --no-default-features --features pg17 -- --output-format bencher | tee benchmark-output.txt
# The quantization benches link extension entry points that PostgreSQL
# supplies at load time, so they cannot be executed as standalone
# Linux binaries. Run the self-contained Criterion targets here; the
# quantization paths are covered by the pgrx test jobs above.
run: |
set -o pipefail
cargo bench --no-default-features --features pg17 \
--bench distance_bench \
--bench e2e_bench \
--bench hybrid_bench \
--bench index_bench \
--bench integrity_bench \
-- --output-format bencher | tee benchmark-output.txt
working-directory: crates/ruvector-postgres

- name: Store benchmark result
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ruvector-postgres-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ jobs:
run: cargo pgrx init --pg${{ matrix.pg_version }}=/opt/homebrew/opt/postgresql@${{ matrix.pg_version }}/bin/pg_config
working-directory: crates/ruvector-postgres

- name: Configure macOS extension linking
if: runner.os == 'macOS'
run: echo 'RUSTFLAGS=-D warnings -C link-arg=-undefined -C link-arg=dynamic_lookup' >> "$GITHUB_ENV"

- name: Build extension
run: cargo build --no-default-features --features pg${{ matrix.pg_version }} --release
working-directory: crates/ruvector-postgres
Expand Down
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 crates/ruvector-graph/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ruvector-graph"
version.workspace = true
version = "2.3.1"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
33 changes: 29 additions & 4 deletions crates/ruvector-graph/src/distributed/replication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl GraphReplication {
&format!("{}:9001", primary_node),
ReplicaRole::Primary,
)
.map_err(|e| GraphError::ReplicationError(e))?;
.map_err(|e| GraphError::ReplicationError(e.to_string()))?;

// Add secondary replicas
for (idx, node) in replica_nodes.iter().enumerate() {
Expand All @@ -121,7 +121,7 @@ impl GraphReplication {
&format!("{}:9001", node),
ReplicaRole::Secondary,
)
.map_err(|e| GraphError::ReplicationError(e))?;
.map_err(|e| GraphError::ReplicationError(e.to_string()))?;
}

let replica_set = Arc::new(replica_set);
Expand Down Expand Up @@ -215,8 +215,11 @@ impl GraphReplication {
.ok_or_else(|| GraphError::ShardError(format!("Shard {} not initialized", shard_id)))?;

// Serialize operation
let data = bincode::encode_to_vec(&op, bincode::config::standard())
.map_err(|e| GraphError::SerializationError(e.to_string()))?;
// Graph properties contain `serde_json::Value`, whose `deserialize_any`
// representation is not supported by bincode 2's serde adapter. JSON
// preserves those dynamically typed values and remains wire-stable.
let _data =
serde_json::to_vec(&op).map_err(|e| GraphError::SerializationError(e.to_string()))?;

// Append to replication log
// Note: In production, the sync_manager would handle actual replication
Expand Down Expand Up @@ -404,4 +407,26 @@ mod tests {
assert_eq!(stats.total_shards, 0);
assert_eq!(stats.strategy, ReplicationStrategy::FullShard);
}

#[test]
fn replication_operations_preserve_dynamic_json_properties() {
let op = ReplicationOp::AddNode(NodeData {
id: "node-1".to_string(),
properties: HashMap::from([(
"kind".to_string(),
serde_json::Value::String("test".to_string()),
)]),
labels: vec!["Example".to_string()],
});

let encoded = serde_json::to_vec(&op).unwrap();
let decoded: ReplicationOp = serde_json::from_slice(&encoded).unwrap();
match decoded {
ReplicationOp::AddNode(node) => {
assert_eq!(node.id, "node-1");
assert_eq!(node.labels, vec!["Example"]);
}
_ => panic!("unexpected replication operation"),
}
}
}
Loading
Loading