Add bootstrap pipeline with envrionment specific logic#2277
Conversation
WalkthroughAdds a local DB bootstrap pipeline: new pipeline modules and adapters (client/producer), schema/version metadata and per-target watermarks, SQL query/upsert/insert helpers, LocalDbError variants and DATABASE_SCHEMA_VERSION, CLI/settings wiring for bootstrap threshold, and related tests. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Client as ClientBootstrapAdapter
participant Producer as ProducerBootstrapAdapter
participant Core as BootstrapPipeline (default/ensure_schema)
participant DB as LocalDbQueryExecutor
User->>Client: run(db, schema_ver, config)
Client->>Core: inspect_state(db, target_key)
Core->>DB: fetch_db_metadata / fetch_target_watermark
DB-->>Core: metadata / watermark
Core-->>Client: BootstrapState
alt missing tables or schema mismatch
Client->>Core: reset_db(db, schema_ver)
Core->>DB: clear_tables / create_tables / insert_db_metadata
DB-->>Core: OK
end
alt dump configured
alt client: threshold exceeded or fresh
Client->>DB: execute dump_stmt
DB-->>Client: OK / Error
else producer
Producer->>Core: reset_db(db, schema_ver)
Producer->>DB: execute dump_stmt?
DB-->>Producer: OK / Error
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (4)tauri-app/**📄 CodeRabbit inference engine (AGENTS.md)
Files:
packages/webapp/**/*.{svelte,ts}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
packages/{webapp,ui-components}/**/*.{svelte,ts}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
packages/**📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (5)📓 Common learnings📚 Learning: 2025-11-06T12:08:39.643ZApplied to files:
📚 Learning: 2025-10-19T20:24:08.629ZApplied to files:
📚 Learning: 2025-04-09T12:58:03.399ZApplied to files:
📚 Learning: 2025-04-09T13:00:24.640ZApplied to files:
🔇 Additional comments (3)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 6
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (24)
crates/cli/src/commands/local_db/mod.rs(1 hunks)crates/cli/src/commands/local_db/pipeline/bootstrap.rs(1 hunks)crates/cli/src/commands/local_db/pipeline/mod.rs(1 hunks)crates/common/src/local_db/mod.rs(3 hunks)crates/common/src/local_db/pipeline/adapters/apply.rs(1 hunks)crates/common/src/local_db/pipeline/adapters/bootstrap.rs(1 hunks)crates/common/src/local_db/pipeline/adapters/mod.rs(1 hunks)crates/common/src/local_db/pipeline/traits.rs(3 hunks)crates/common/src/local_db/query/clear_tables/mod.rs(2 hunks)crates/common/src/local_db/query/clear_tables/query.sql(1 hunks)crates/common/src/local_db/query/create_tables/mod.rs(1 hunks)crates/common/src/local_db/query/create_tables/query.sql(1 hunks)crates/common/src/local_db/query/fetch_db_metadata/mod.rs(1 hunks)crates/common/src/local_db/query/fetch_db_metadata/query.sql(1 hunks)crates/common/src/local_db/query/fetch_target_watermark/mod.rs(1 hunks)crates/common/src/local_db/query/fetch_target_watermark/query.sql(1 hunks)crates/common/src/local_db/query/insert_db_metadata/mod.rs(1 hunks)crates/common/src/local_db/query/insert_db_metadata/query.sql(1 hunks)crates/common/src/local_db/query/mod.rs(1 hunks)crates/common/src/local_db/query/upsert_target_watermark/mod.rs(1 hunks)crates/common/src/local_db/query/upsert_target_watermark/query.sql(1 hunks)crates/common/src/raindex_client/local_db/mod.rs(1 hunks)crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs(1 hunks)crates/common/src/raindex_client/local_db/pipeline/mod.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
crates/*/{src,tests,benches,examples}/**/*.rs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Rust code must pass clippy with all warnings denied (cargo clippy --workspace --all-targets --all-features -D warnings)
Files:
crates/common/src/local_db/pipeline/adapters/mod.rscrates/common/src/raindex_client/local_db/mod.rscrates/cli/src/commands/local_db/pipeline/mod.rscrates/common/src/local_db/mod.rscrates/common/src/local_db/pipeline/adapters/apply.rscrates/common/src/local_db/query/fetch_db_metadata/mod.rscrates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/local_db/query/fetch_target_watermark/mod.rscrates/common/src/local_db/query/mod.rscrates/common/src/local_db/query/create_tables/mod.rscrates/common/src/local_db/query/upsert_target_watermark/mod.rscrates/cli/src/commands/local_db/mod.rscrates/common/src/raindex_client/local_db/pipeline/mod.rscrates/common/src/local_db/pipeline/adapters/bootstrap.rscrates/common/src/local_db/pipeline/traits.rscrates/common/src/local_db/query/insert_db_metadata/mod.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rscrates/common/src/local_db/query/clear_tables/mod.rs
crates/**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
Rust code lives in the workspace under crates/* (e.g., cli, common, bindings, js_api, quote, subgraph, settings, math, integration_tests)
Files:
crates/common/src/local_db/pipeline/adapters/mod.rscrates/common/src/raindex_client/local_db/mod.rscrates/cli/src/commands/local_db/pipeline/mod.rscrates/common/src/local_db/mod.rscrates/common/src/local_db/pipeline/adapters/apply.rscrates/common/src/local_db/query/fetch_db_metadata/mod.rscrates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/local_db/query/fetch_target_watermark/mod.rscrates/common/src/local_db/query/mod.rscrates/common/src/local_db/query/create_tables/mod.rscrates/common/src/local_db/query/upsert_target_watermark/mod.rscrates/cli/src/commands/local_db/mod.rscrates/common/src/raindex_client/local_db/pipeline/mod.rscrates/common/src/local_db/pipeline/adapters/bootstrap.rscrates/common/src/local_db/pipeline/traits.rscrates/common/src/local_db/query/insert_db_metadata/mod.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rscrates/common/src/local_db/query/clear_tables/mod.rs
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Format Rust with nix develop -c cargo fmt --all
Lint Rust with nix develop -c rainix-rs-static (preconfigured flags)
Use snake_case for Rust crates/modules and PascalCase for types
Files:
crates/common/src/local_db/pipeline/adapters/mod.rscrates/common/src/raindex_client/local_db/mod.rscrates/cli/src/commands/local_db/pipeline/mod.rscrates/common/src/local_db/mod.rscrates/common/src/local_db/pipeline/adapters/apply.rscrates/common/src/local_db/query/fetch_db_metadata/mod.rscrates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/local_db/query/fetch_target_watermark/mod.rscrates/common/src/local_db/query/mod.rscrates/common/src/local_db/query/create_tables/mod.rscrates/common/src/local_db/query/upsert_target_watermark/mod.rscrates/cli/src/commands/local_db/mod.rscrates/common/src/raindex_client/local_db/pipeline/mod.rscrates/common/src/local_db/pipeline/adapters/bootstrap.rscrates/common/src/local_db/pipeline/traits.rscrates/common/src/local_db/query/insert_db_metadata/mod.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rscrates/common/src/local_db/query/clear_tables/mod.rs
🧠 Learnings (1)
📚 Learning: 2025-10-06T14:41:41.909Z
Learnt from: findolor
PR: rainlanguage/rain.orderbook#2159
File: crates/cli/src/commands/local_db/sync/runner/mod.rs:52-113
Timestamp: 2025-10-06T14:41:41.909Z
Learning: The local DB sync CLI command (crates/cli/src/commands/local_db/sync/) is designed for CI-only usage, and simple println! statements are preferred over structured logging for status messages.
Applied to files:
crates/cli/src/commands/local_db/mod.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
- GitHub Check: build-tauri (ubuntu-22.04, true)
🔇 Additional comments (24)
crates/common/src/raindex_client/local_db/pipeline/mod.rs (1)
1-1: LGTM!Standard module declaration that exposes the bootstrap submodule to the public API.
crates/common/src/local_db/query/upsert_target_watermark/mod.rs (2)
5-23: LGTM!The function correctly builds a parameterized SQL statement with proper handling of the optional
last_hashparameter, mappingNonetoSqlValue::Null. Parameter binding order aligns with the SQL template placeholders.
25-77: LGTM!Comprehensive test coverage validating parameter binding order, types, SQL template matching, and both the presence and absence of
last_hash. The tests ensure correctness of the upsert statement generation.crates/common/src/raindex_client/local_db/mod.rs (1)
7-7: LGTM!Standard module declaration exposing the pipeline submodule.
crates/common/src/local_db/query/fetch_db_metadata/query.sql (1)
1-1: LGTM!The query correctly fetches the singleton metadata row. Ensure the
db_metadatatable is initialized before this query is executed (see comment oncreate_tables/query.sql).crates/cli/src/commands/local_db/pipeline/mod.rs (1)
1-1: LGTM!Standard module declaration exposing the bootstrap submodule for CLI commands.
crates/common/src/local_db/pipeline/adapters/mod.rs (1)
2-2: LGTM!Standard module declaration that adds the bootstrap adapter to the public API surface alongside existing adapters.
crates/common/src/local_db/query/create_tables/query.sql (1)
3-9: No action required — db_metadata initialization is already properly implemented.The bootstrap flow in
crates/common/src/local_db/pipeline/adapters/bootstrap.rsexplicitly initializes thedb_metadatasingleton in thereset_dbmethod (lines 100–105) with the correct sequence: clear tables → create tables → insert metadata row. This ensures the table and its singleton row are initialized before any queries can read from it.Likely an incorrect or invalid review comment.
crates/common/src/local_db/pipeline/adapters/apply.rs (1)
70-70: Type consistency verified and correct.The
TargetKey.chain_idfield isu32, and thegenerate_erc20_token_statementsfunction (aliased asbuild_token_upserts) expects au32parameter. The removal of the cast is justified—no conversion is needed.crates/common/src/local_db/query/clear_tables/query.sql (1)
3-4: LGTM!The addition of DROP TABLE statements for the new tables
target_watermarksanddb_metadatais correct and maintains transactional consistency. TheIF EXISTSclause ensures safety even if the tables haven't been created yet.crates/common/src/local_db/query/fetch_target_watermark/query.sql (1)
1-3: LGTM!The query correctly fetches target watermark data using the composite key of
chain_idandorderbook_address. The parameter bindings are properly specified.crates/common/src/local_db/query/insert_db_metadata/query.sql (1)
1-1: Verify that INSERT is appropriate for the usage pattern.This INSERT statement will fail if a row with
id=1already exists. If this query is intended only for initial bootstrap of an empty database, the current approach is acceptable. However, if it may be called during database reset or re-initialization scenarios, consider using an UPSERT pattern instead:INSERT INTO db_metadata (id, db_schema_version) VALUES (1, ?1) ON CONFLICT(id) DO UPDATE SET db_schema_version = excluded.db_schema_version;Can you confirm whether this query is exclusively used during initial bootstrap, or if it might be called when
db_metadataalready contains data?crates/common/src/local_db/query/upsert_target_watermark/query.sql (1)
1-6: LGTM!Excellent use of the UPSERT pattern. The conflict resolution on the composite key
(chain_id, orderbook_address)is correct, and the automaticupdated_attimestamp tracking viaCURRENT_TIMESTAMPprovides proper audit trail functionality.crates/common/src/local_db/query/create_tables/mod.rs (1)
6-7: LGTM!The addition of
db_metadataandtarget_watermarkstoREQUIRED_TABLESis correct and aligns with the new table definitions. The existing test coverage will validate that the correspondingCREATE TABLEstatements exist in the SQL schema.crates/common/src/local_db/query/mod.rs (1)
4-20: LGTM!The new module exports follow the existing pattern and correctly expose the new query functionality for database metadata and target watermark operations.
crates/cli/src/commands/local_db/mod.rs (1)
4-8: LGTM!The addition of the
pipelinemodule and the re-export ofSyncLocalDbproperly extend the CLI's local database command surface. The changes follow the existing module organization pattern.crates/common/src/local_db/query/clear_tables/mod.rs (3)
17-26: LGTM!The
normalize_identhelper correctly handles various SQL identifier quoting styles (backticks, double quotes, brackets) and provides case-insensitive comparison. This is appropriate for matching table names across different SQL formatting conventions.
28-37: LGTM!Good refactoring to make the test more flexible. Checking for the generic
"drop table if exists"pattern rather than a specific table name makes the test more maintainable as the table set evolves.
39-83: LGTM!Excellent test coverage! The
drops_all_required_tablestest comprehensively validates that the clear operation drops exactly the set of required tables—no more, no less. The parsing logic correctly extracts table names from DROP TABLE statements, and the set-based comparison with clear error reporting makes test failures easy to diagnose.crates/common/src/local_db/query/insert_db_metadata/mod.rs (1)
5-7: LGTMStatement builder and tests look correct; parameter binding and template checks are solid.
Also applies to: 13-21, 31-38
crates/cli/src/commands/local_db/pipeline/bootstrap.rs (1)
61-77: Confirm unconditional reset semanticsrun() always resets the DB before optionally importing a dump. If keeping existing data is ever desired in producer flows, consider inspecting state and gating reset (akin to Client adapter). Otherwise, please confirm this is intentional for producer.
crates/common/src/local_db/mod.rs (1)
25-25: LGTMSchema version constant and new LocalDbError variants with readable messages are coherent and ready for use in the bootstrap pipeline.
Also applies to: 123-137, 195-213
crates/common/src/local_db/query/fetch_db_metadata/mod.rs (1)
5-17: LGTMStatic SQL inclusion and zero-parameter statement are appropriate; tests cover template, columns, and serde.
Also applies to: 23-37
crates/common/src/local_db/query/fetch_target_watermark/mod.rs (1)
16-24: LGTMParameterized statement and address formatting are correct; tests robustly validate both.
Also applies to: 50-75
| impl ProducerBootstrapAdapter { | ||
| #[cfg(test)] | ||
| pub fn new() -> Self { | ||
| Self {} | ||
| } | ||
| } |
There was a problem hiding this comment.
Expose a consistent constructor (remove #[cfg(test)])
new() is test-only here, unlike ClientBootstrapAdapter which exposes new() publicly. This asymmetry can hinder non-test usage.
Apply:
- #[cfg(test)]
- pub fn new() -> Self {
- Self {}
- }
+ pub const fn new() -> Self {
+ Self {}
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| impl ProducerBootstrapAdapter { | |
| #[cfg(test)] | |
| pub fn new() -> Self { | |
| Self {} | |
| } | |
| } | |
| impl ProducerBootstrapAdapter { | |
| pub const fn new() -> Self { | |
| Self {} | |
| } | |
| } |
🤖 Prompt for AI Agents
In crates/cli/src/commands/local_db/pipeline/bootstrap.rs around lines 13 to 18,
the impl for ProducerBootstrapAdapter marks pub fn new() with #[cfg(test)]
making the constructor test-only and inconsistent with ClientBootstrapAdapter;
remove the #[cfg(test)] attribute so new() is always compiled and available,
ensuring the adapter exposes a consistent public constructor across builds.
There was a problem hiding this comment.
@findolor, understood! I'll leave the constructor as-is.
| async fn ensure_schema<DB>( | ||
| &self, | ||
| db: &DB, | ||
| db_schema_version: Option<u32>, | ||
| ) -> Result<(), LocalDbError> | ||
| where | ||
| DB: LocalDbQueryExecutor + ?Sized, | ||
| { | ||
| let rows = db | ||
| .query_json::<Vec<DbMetadataRow>>(&fetch_db_metadata_stmt()) | ||
| .await?; | ||
| if let Some(row) = rows.first() { | ||
| let expected = db_schema_version.unwrap_or(DATABASE_SCHEMA_VERSION); | ||
| if row.db_schema_version != expected { | ||
| return Err(LocalDbError::SchemaVersionMismatch { | ||
| expected, | ||
| found: row.db_schema_version, | ||
| }); | ||
| } | ||
| return Ok(()); | ||
| } | ||
| return Err(LocalDbError::MissingDbMetadataRow); | ||
| } | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
Make ensure_schema clippy-clean (remove needless returns)
To satisfy clippy with -D warnings, avoid trailing return. Equivalent, clearer flow:
Apply:
- if let Some(row) = rows.first() {
- let expected = db_schema_version.unwrap_or(DATABASE_SCHEMA_VERSION);
- if row.db_schema_version != expected {
- return Err(LocalDbError::SchemaVersionMismatch {
- expected,
- found: row.db_schema_version,
- });
- }
- return Ok(());
- }
- return Err(LocalDbError::MissingDbMetadataRow);
+ if let Some(row) = rows.first() {
+ let expected = db_schema_version.unwrap_or(DATABASE_SCHEMA_VERSION);
+ if row.db_schema_version != expected {
+ Err(LocalDbError::SchemaVersionMismatch {
+ expected,
+ found: row.db_schema_version,
+ })
+ } else {
+ Ok(())
+ }
+ } else {
+ Err(LocalDbError::MissingDbMetadataRow)
+ }Then verify:
As per coding guidelines.
🏁 Script executed:
#!/bin/bash
# Clippy must pass per coding guidelines
nix develop -c cargo clippy --workspace --all-targets --all-features -D warningsLength of output: 41
Let me verify the actual code in the file and check for similar issues:
🏁 Script executed:
#!/bin/bash
# View the ensure_schema method to verify it matches the review comment
fd -t f "bootstrap.rs" -x cat {} | head -100Length of output: 2612
🏁 Script executed:
#!/bin/bash
# Search for other trailing returns in the same file that might violate clippy
rg -n "return (Ok|Err)" crates/common/src/local_db/pipeline/adapters/bootstrap.rsLength of output: 316
🏁 Script executed:
#!/bin/bash
# Check file structure and imports
fd -t f "bootstrap.rs" crates/common/src/local_db/pipeline/adapters/Length of output: 57
🏁 Script executed:
#!/bin/bash
# View the DefaultBootstrapAdapter::ensure_schema implementation
rg -n -A 30 "impl DefaultBootstrapAdapter" crates/common/src/local_db/pipeline/adapters/bootstrap.rsLength of output: 1031
🏁 Script executed:
#!/bin/bash
# Check context around lines 168, 178 to see if they're in scope of this review
rg -n -B 3 -A 3 "return Err\(LocalDbQueryError" crates/common/src/local_db/pipeline/adapters/bootstrap.rsLength of output: 666
🏁 Script executed:
#!/bin/bash
# View larger context around lines 165-180 to identify the struct/method
rg -n -B 20 "let Some(body) = self.json_map.get" crates/common/src/local_db/pipeline/adapters/bootstrap.rs | head -40Length of output: 0
🏁 Script executed:
#!/bin/bash
# View lines around 160-185 directly
cat crates/common/src/local_db/pipeline/adapters/bootstrap.rs | sed -n '155,185p' | cat -nLength of output: 1374
🏁 Script executed:
#!/bin/bash
# View lines 120-160 to see module/struct context
cat crates/common/src/local_db/pipeline/adapters/bootstrap.rs | sed -n '120,160p' | cat -nLength of output: 1707
🏁 Script executed:
#!/bin/bash
# Search for #[cfg(test)] declaration in the file
rg -n "#\[cfg\(test\)\]" crates/common/src/local_db/pipeline/adapters/bootstrap.rsLength of output: 16
🏁 Script executed:
#!/bin/bash
# Show lines 100-125 to find module start
cat crates/common/src/local_db/pipeline/adapters/bootstrap.rs | sed -n '100,125p' | cat -nLength of output: 1054
Make ensure_schema and test helpers clippy-clean (remove needless returns)
The review comment correctly identifies needless returns in ensure_schema (lines 32-55) with a valid fix. However, the same clippy violation exists in test helper code that must also be fixed to satisfy cargo clippy --workspace --all-targets --all-features -D warnings:
- Line 168:
MockDb::query_json– trailingreturn Err(...) - Line 178:
MockDb::query_text– trailingreturn Err(...)
Apply the proposed diff for ensure_schema. Additionally, refactor lines 168 and 178 to use expression style (remove trailing returns and use else clause pattern) to ensure the full workspace passes clippy.
🤖 Prompt for AI Agents
In crates/common/src/local_db/pipeline/adapters/bootstrap.rs around lines 32-55,
change the function ensure_schema to remove needless `return` statements by
using expression style (e.g., replace `return Ok(());` and `return Err(...)`
with `Ok(())` and `Err(...)` as final expressions) as in the proposed diff; also
update the test helper implementations at lines ~168 and ~178
(MockDb::query_json and MockDb::query_text) to eliminate trailing `return
Err(...)` and use expression-style returns or an `else` expression so the
functions end with `Err(...)`/`Ok(...)` directly instead of `return`, ensuring
clippy no longer flags needless_return across the workspace.
There was a problem hiding this comment.
clippy does not give us any issues
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if clippy reports any issues with the bootstrap.rs file
cd crates/common && cargo clippy --all-targets --all-features -- -D warnings 2>&1 | head -100
Length of output: 109
🏁 Script executed:
#!/bin/bash
# Check the clippy configuration in the workspace
cat Cargo.toml | grep -A 20 "\[workspace.lints"
Length of output: 0
🏁 Script executed:
#!/bin/bash
# Also check for clippy.toml or .clippy.toml configuration files
fd -t f "clippy.toml" -H
fd -t f ".clippy.toml" -H
Length of output: 0
🏁 Script executed:
#!/bin/bash
# Check for rust-toolchain or clippy allow configurations in the file itself
cat crates/common/src/local_db/pipeline/adapters/bootstrap.rs | head -30
Length of output: 1353
🏁 Script executed:
#!/bin/bash
# Check for any clippy allow attributes or workspace configuration
rg -n "clippy::" Cargo.toml
rg -n "clippy::" rust-toolchain.toml 2>/dev/null || echo "No rust-toolchain.toml"
Length of output: 22
🏁 Script executed:
#!/bin/bash
# Check the beginning of the bootstrap.rs file for any clippy attributes
rg -n "#\[allow\(clippy" crates/common/src/local_db/pipeline/adapters/bootstrap.rs
rg -n "#!\[allow\(clippy" crates/common/src/local_db/pipeline/adapters/bootstrap.rs
Length of output: 0
@findolor, thank you for verifying! I apologize for the incorrect suggestion. If clippy passes cleanly in your local environment, then the code is fine as-is. The explicit return statements don't appear to be triggering any warnings in your configuration.
Feel free to disregard the suggestion about removing those returns. 👍
(\(\
( -.-)
o_(")(")
| -- Per-target watermarks keyed by (chain_id, orderbook_address) | ||
| CREATE TABLE IF NOT EXISTS target_watermarks ( | ||
| chain_id INTEGER NOT NULL, | ||
| orderbook_address TEXT NOT NULL, | ||
| last_block INTEGER NOT NULL DEFAULT 0, | ||
| last_hash TEXT, | ||
| updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
| PRIMARY KEY (chain_id, orderbook_address) | ||
| ); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider indexing strategy for query patterns.
The composite primary key on (chain_id, orderbook_address) supports lookups by chain_id efficiently. If queries commonly filter by orderbook_address alone or perform range scans on last_block, consider adding separate indexes.
🤖 Prompt for AI Agents
In crates/common/src/local_db/query/create_tables/query.sql around lines 11 to
19, the table target_watermarks has a composite primary key (chain_id,
orderbook_address) but lacks standalone indexes for access patterns that filter
by orderbook_address alone or perform range scans on last_block; add a
non-unique index on orderbook_address and an index (or b-tree) on last_block (or
a composite index like (orderbook_address, last_block) if queries commonly
combine those) using CREATE INDEX IF NOT EXISTS so those filters and range scans
are efficient.
There was a problem hiding this comment.
it's fine we are not going to have a lot of rows in this table
There was a problem hiding this comment.
@findolor, understood! For a table with low row count, the additional index overhead isn't justified. The primary key on (chain_id, orderbook_address) will handle the typical lookup patterns efficiently.
✏️ Learnings added
Learnt from: findolor
PR: rainlanguage/rain.orderbook#2277
File: crates/common/src/local_db/query/create_tables/query.sql:11-19
Timestamp: 2025-10-28T14:11:56.622Z
Learning: In the target_watermarks table (crates/common/src/local_db/query/create_tables/query.sql), additional indexes beyond the composite primary key (chain_id, orderbook_address) are not needed because the table will have a small number of rows.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
| async fn is_fresh_db<E: LocalDbQueryExecutor + ?Sized>( | ||
| self, | ||
| db: &E, | ||
| target_key: &TargetKey, | ||
| ) -> Result<bool, LocalDbError> { | ||
| let rows: Vec<TargetWatermarkRow> = db | ||
| .query_json(&fetch_target_watermark_stmt( | ||
| target_key.chain_id, | ||
| target_key.orderbook_address, | ||
| )) | ||
| .await?; | ||
| Ok(rows.is_empty()) | ||
| } |
There was a problem hiding this comment.
Don’t take self by value in is_fresh_db
Method doesn’t consume self; taking by value is unnecessary and may trip clippy. Use &self.
Apply:
- async fn is_fresh_db<E: LocalDbQueryExecutor + ?Sized>(
- self,
+ async fn is_fresh_db<E: LocalDbQueryExecutor + ?Sized>(
+ &self,
db: &E,
target_key: &TargetKey,
) -> Result<bool, LocalDbError> {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async fn is_fresh_db<E: LocalDbQueryExecutor + ?Sized>( | |
| self, | |
| db: &E, | |
| target_key: &TargetKey, | |
| ) -> Result<bool, LocalDbError> { | |
| let rows: Vec<TargetWatermarkRow> = db | |
| .query_json(&fetch_target_watermark_stmt( | |
| target_key.chain_id, | |
| target_key.orderbook_address, | |
| )) | |
| .await?; | |
| Ok(rows.is_empty()) | |
| } | |
| async fn is_fresh_db<E: LocalDbQueryExecutor + ?Sized>( | |
| &self, | |
| db: &E, | |
| target_key: &TargetKey, | |
| ) -> Result<bool, LocalDbError> { | |
| let rows: Vec<TargetWatermarkRow> = db | |
| .query_json(&fetch_target_watermark_stmt( | |
| target_key.chain_id, | |
| target_key.orderbook_address, | |
| )) | |
| .await?; | |
| Ok(rows.is_empty()) | |
| } |
🤖 Prompt for AI Agents
In crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs around lines
41 to 53, the method signature takes self by value but does not consume it;
change the signature to take &self (i.e. async fn is_fresh_db<E:
LocalDbQueryExecutor + ?Sized>(&self, db: &E, target_key: &TargetKey) ->
Result<bool, LocalDbError>) and adjust any impl blocks or trait
definitions/clients calling this method to use &self instead of moving the
instance.
There was a problem hiding this comment.
@findolor, understood! Since the struct implements Copy and clippy doesn't flag it, the current signature is fine. Thanks for checking!
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs (1)
10-10: Consider making the threshold configurable.The hardcoded
BLOCK_NUMBER_THRESHOLDof 10,000 blocks may not be appropriate for all supported chains (different block times, finality characteristics). While this was mentioned in a past review, it remains hardcoded.A past review suggested adding it to
BootstrapConfig:pub struct BootstrapConfig { pub target_key: TargetKey, pub dump_stmt: Option<SqlStatement>, pub latest_block: u64, + pub block_number_threshold: u64, }Then use
config.block_number_thresholdinstead of the constant. Provide 10,000 as the default when constructingBootstrapConfig.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
crates/cli/src/commands/local_db/pipeline/bootstrap.rs(1 hunks)crates/common/src/local_db/pipeline/adapters/bootstrap.rs(1 hunks)crates/common/src/local_db/pipeline/mod.rs(2 hunks)crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
crates/*/{src,tests,benches,examples}/**/*.rs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Rust code must pass clippy with all warnings denied (cargo clippy --workspace --all-targets --all-features -D warnings)
Files:
crates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/local_db/pipeline/mod.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rscrates/common/src/local_db/pipeline/adapters/bootstrap.rs
crates/**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
Rust code lives in the workspace under crates/* (e.g., cli, common, bindings, js_api, quote, subgraph, settings, math, integration_tests)
Files:
crates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/local_db/pipeline/mod.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rscrates/common/src/local_db/pipeline/adapters/bootstrap.rs
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Format Rust with nix develop -c cargo fmt --all
Lint Rust with nix develop -c rainix-rs-static (preconfigured flags)
Use snake_case for Rust crates/modules and PascalCase for types
Files:
crates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/local_db/pipeline/mod.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rscrates/common/src/local_db/pipeline/adapters/bootstrap.rs
🧠 Learnings (11)
📓 Common learnings
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:25:47.873Z
Learning: After each new commit review for rainlanguage/rain.orderbook repository, generate a PR size report in a separate comment with the format: "TOTAL=number ADDITIONS=number DELETIONS=number". This report should exclude irrelevant files such as lock files (e.g., package-lock.json, cargo.lock).
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T22:14:22.646Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, I must consistently report the PR size after EVERY new commit in the exact format "TOTAL=number\nADDITIONS=number\nDELETIONS=number" without any formatting blocks. The report must exclude lock files (package-lock.json, yarn.lock, pnpm-lock.yaml, cargo.lock) and can be included either as part of the review or as a separate comment.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T22:14:22.646Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, I must consistently report the PR size after EVERY new commit in the exact format "TOTAL=number\nADDITIONS=number\nDELETIONS=number" without any additional text or formatting blocks. The report must exclude lock files (package-lock.json, yarn.lock, pnpm-lock.yaml, cargo.lock) and can be included either as part of the review or as a separate comment.
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2123
File: crates/common/src/raindex_client/local_db/mod.rs:23-29
Timestamp: 2025-10-06T11:13:29.956Z
Learning: In `crates/common/src/raindex_client/local_db/mod.rs`, the `Default` implementation for `LocalDb` that creates an RPC client pointing to `http://localhost:4444` is acceptable because the RPC client must be explicitly configured before actual usage in production scenarios.
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2145
File: crates/common/src/raindex_client/local_db/query/create_tables/query.sql:71-72
Timestamp: 2025-10-06T11:44:07.888Z
Learning: The local DB feature in the rain.orderbook codebase is not live yet (as of PR #2145), so schema migrations for existing databases are not required when modifying table structures in `crates/common/src/raindex_client/local_db/query/create_tables/query.sql`.
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2159
File: crates/cli/src/commands/local_db/sync/runner/mod.rs:52-113
Timestamp: 2025-10-06T14:41:41.909Z
Learning: The local DB sync CLI command (crates/cli/src/commands/local_db/sync/) is designed for CI-only usage, and simple println! statements are preferred over structured logging for status messages.
📚 Learning: 2025-10-06T14:41:41.909Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2159
File: crates/cli/src/commands/local_db/sync/runner/mod.rs:52-113
Timestamp: 2025-10-06T14:41:41.909Z
Learning: The local DB sync CLI command (crates/cli/src/commands/local_db/sync/) is designed for CI-only usage, and simple println! statements are preferred over structured logging for status messages.
Applied to files:
crates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/local_db/pipeline/mod.rscrates/common/src/local_db/pipeline/adapters/bootstrap.rs
📚 Learning: 2025-07-09T07:42:48.458Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1975
File: crates/js_api/src/config.rs:44-45
Timestamp: 2025-07-09T07:42:48.458Z
Learning: User findolor prefers to defer code improvements and refactoring suggestions to future PRs when they are not directly related to the current PR's scope, even when the suggestions are valid improvements.
Applied to files:
crates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rs
📚 Learning: 2025-10-06T11:13:29.956Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2123
File: crates/common/src/raindex_client/local_db/mod.rs:23-29
Timestamp: 2025-10-06T11:13:29.956Z
Learning: In `crates/common/src/raindex_client/local_db/mod.rs`, the `Default` implementation for `LocalDb` that creates an RPC client pointing to `http://localhost:4444` is acceptable because the RPC client must be explicitly configured before actual usage in production scenarios.
Applied to files:
crates/cli/src/commands/local_db/pipeline/bootstrap.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rs
📚 Learning: 2025-06-18T19:24:40.518Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1938
File: crates/settings/src/yaml/orderbook.rs:185-199
Timestamp: 2025-06-18T19:24:40.518Z
Learning: In crates/settings/src/yaml/orderbook.rs, the user prefers not to refactor get_orderbook_by_network_key to handle multiple orderbooks per network key since their current architecture maintains a one-to-one mapping between orderbooks and networks. They would consider the refactoring if the system evolves to support multiple orderbooks per network in the future.
Applied to files:
crates/common/src/local_db/pipeline/mod.rs
📚 Learning: 2025-10-14T07:51:55.148Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2202
File: crates/common/src/raindex_client/local_db/sync.rs:33-34
Timestamp: 2025-10-14T07:51:55.148Z
Learning: In `crates/common/src/raindex_client/local_db/sync.rs`, the hard-coded `DEFAULT_SYNC_CHAIN_ID` constant (set to `SUPPORTED_LOCAL_DB_CHAINS[0]`) will be replaced with proper chain ID handling in downstream PRs as part of the multi-network/orderbook implementation.
Applied to files:
crates/common/src/local_db/pipeline/mod.rscrates/common/src/raindex_client/local_db/pipeline/bootstrap.rs
📚 Learning: 2025-06-18T18:24:32.049Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1938
File: crates/settings/src/yaml/orderbook.rs:180-199
Timestamp: 2025-06-18T18:24:32.049Z
Learning: In crates/settings/src/yaml/orderbook.rs, the user prefers to avoid refactoring duplicate search logic between get_orderbook_by_address and get_orderbook_by_network_key when there are only 2 functions, indicating they would consider it if more similar functions are added in the future.
Applied to files:
crates/common/src/local_db/pipeline/mod.rs
📚 Learning: 2025-10-21T05:15:50.518Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2256
File: crates/common/src/raindex_client/local_db/query/fetch_tables.rs:7-7
Timestamp: 2025-10-21T05:15:50.518Z
Learning: In Rust 2021+ editions, passing a reference to a temporary into an async function within the same expression (e.g., `exec.query_json(&fetch_tables_stmt()).await`) is safe and idiomatic. The temporary lifetime is extended across the await point, so this pattern should not be flagged as an issue.
Applied to files:
crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs
📚 Learning: 2025-06-20T07:51:08.790Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1941
File: crates/js_api/src/raindex/vaults.rs:175-181
Timestamp: 2025-06-20T07:51:08.790Z
Learning: In the RaindexClient vault methods, `&self` parameters are intentionally kept for API consistency to make all vault operations instance methods, even when the methods don't use client state. This is a design preference for maintaining a uniform interface.
Applied to files:
crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs
📚 Learning: 2025-05-14T05:52:04.270Z
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 1715
File: crates/js_api/src/common/mod.rs:15-22
Timestamp: 2025-05-14T05:52:04.270Z
Learning: The project doesn't require `#[repr(transparent)]` for newtype wrappers in WASM contexts such as `AddOrderCalldata` and `RemoveOrderCalldata` as the current implementation is working as expected without it.
Applied to files:
crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs
📚 Learning: 2025-10-06T08:05:02.438Z
Learnt from: CR
Repo: rainlanguage/rain.orderbook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-06T08:05:02.438Z
Learning: Applies to crates/*/{src,tests,benches,examples}/**/*.rs : Rust code must pass clippy with all warnings denied (cargo clippy --workspace --all-targets --all-features -D warnings)
Applied to files:
crates/common/src/local_db/pipeline/adapters/bootstrap.rs
🧬 Code graph analysis (3)
crates/cli/src/commands/local_db/pipeline/bootstrap.rs (8)
crates/common/src/local_db/pipeline/adapters/bootstrap.rs (4)
new(172-174)run(119-129)db(50-51)query_text(201-208)crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs (4)
new(16-18)run(55-98)query_text(170-177)target_key(180-185)crates/common/src/local_db/query/clear_tables/mod.rs (1)
clear_tables_stmt(7-9)crates/common/src/raindex_client/local_db/query/create_tables.rs (1)
create_tables(4-9)crates/common/src/local_db/query/create_tables/mod.rs (1)
create_tables_stmt(28-30)crates/common/src/local_db/query/insert_db_metadata/mod.rs (1)
insert_db_metadata_stmt(5-7)crates/common/src/local_db/query/mod.rs (1)
database(48-52)crates/common/src/local_db/query/sql_statement.rs (1)
sql(60-62)
crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs (8)
crates/common/src/local_db/query/fetch_target_watermark/mod.rs (1)
fetch_target_watermark_stmt(16-24)crates/common/src/local_db/query/clear_tables/mod.rs (1)
clear_tables_stmt(7-9)crates/common/src/raindex_client/local_db/query/create_tables.rs (1)
create_tables(4-9)crates/common/src/local_db/query/create_tables/mod.rs (1)
create_tables_stmt(28-30)crates/common/src/local_db/query/fetch_db_metadata/mod.rs (1)
fetch_db_metadata_stmt(15-17)crates/common/src/local_db/query/fetch_tables/mod.rs (1)
fetch_tables_stmt(12-14)crates/common/src/local_db/query/insert_db_metadata/mod.rs (1)
insert_db_metadata_stmt(5-7)crates/common/src/local_db/query/sql_statement.rs (1)
sql(60-62)
crates/common/src/local_db/pipeline/adapters/bootstrap.rs (10)
crates/common/src/raindex_client/local_db/query/clear_tables.rs (1)
clear_tables(6-11)crates/common/src/local_db/query/clear_tables/mod.rs (1)
clear_tables_stmt(7-9)crates/common/src/raindex_client/local_db/query/create_tables.rs (1)
create_tables(4-9)crates/common/src/local_db/query/create_tables/mod.rs (1)
create_tables_stmt(28-30)crates/common/src/local_db/query/fetch_db_metadata/mod.rs (1)
fetch_db_metadata_stmt(15-17)crates/common/src/local_db/query/fetch_tables/mod.rs (1)
fetch_tables_stmt(12-14)crates/common/src/local_db/query/fetch_target_watermark/mod.rs (1)
fetch_target_watermark_stmt(16-24)crates/common/src/local_db/query/insert_db_metadata/mod.rs (1)
insert_db_metadata_stmt(5-7)crates/common/src/local_db/query/sql_statement.rs (1)
sql(60-62)crates/common/src/local_db/query/mod.rs (2)
database(48-52)deserialization(58-62)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
- GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-test)
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
- GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-legal)
- GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
- GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
- GitHub Check: standard-tests (ubuntu-latest, ob-rs-test, true)
- GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
- GitHub Check: git-clean
- GitHub Check: test
- GitHub Check: test
- GitHub Check: test
- GitHub Check: Deploy-Docs-Preview
- GitHub Check: build-tauri (ubuntu-22.04, true)
- GitHub Check: Deploy-Preview-Push
🔇 Additional comments (10)
crates/common/src/local_db/pipeline/mod.rs (2)
11-11: LGTM! Bootstrap surface properly exposed.The re-export of bootstrap types (
BootstrapConfig,BootstrapPipeline,BootstrapState) provides a clean public API for the pipeline module.
29-29: LGTM! Chain ID type change is appropriate.The change from
u64tou32forchain_idis correct, as blockchain chain IDs (per EIP-155) fit within u32 range, and this aligns with standard practice.crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs (2)
64-98: LGTM! Bootstrap logic is well-structured.The conditional bootstrap flow correctly handles multiple scenarios:
- Missing tables → reset → ensure schema → apply dump if fresh
- Schema mismatch → reset → apply dump if fresh
- Valid schema + threshold exceeded → reset → apply dump
- Valid schema + within threshold → no-op
The logic correctly recognizes that
reset_dbclears thetarget_watermarkstable, making subsequentis_fresh_dbchecks returntrue. The threshold error (line 88-94) is intentionally used as a control flow signal rather than propagated, which is appropriate here.
195-589: LGTM! Comprehensive test coverage.The test suite thoroughly covers the bootstrap scenarios:
- State-based reset triggers (missing tables, schema errors)
- Dump application logic (fresh DB detection, threshold checking)
- Boundary conditions (exact threshold value)
- Error propagation (unexpected ensure_schema errors)
- Mixed scenarios (schema errors + dump application)
The tests verify both the presence and ordering of SQL operations, ensuring correct transactional behavior.
crates/common/src/local_db/pipeline/adapters/bootstrap.rs (6)
16-28: LGTM! Well-designed configuration types.
BootstrapConfigandBootstrapStateprovide clear separation between input parameters and inspected state. The optionality ofdump_stmtandlast_synced_blockappropriately reflects their conditional presence.
42-64: LGTM! Schema validation logic is correct.The
ensure_schemadefault implementation properly:
- Validates schema version against expected value (override or default)
- Returns specific error variants for missing metadata vs. version mismatch
- Allows implementors to override if needed
Based on past review discussion, clippy accepts the current return style.
66-100: LGTM! State inspection handles edge cases well.The
inspect_stateimplementation correctly:
- Uses case-insensitive table name comparison (lines 77, 82) to handle database case sensitivity variations
- Conditionally queries
target_watermarksonly when the table exists (line 84)- Returns
Noneforlast_synced_blockwhen watermarks table is missing or empty
102-117: LGTM! Reset sequence is correct.The
reset_dboperation performs the three required steps in the correct order:
- Clear existing data
- Recreate schema
- Initialize metadata
This ensures a clean slate for bootstrap operations.
119-129: LGTM! Appropriate default for abstract operation.The
runmethod correctly returnsMissingBootstrapImplementationby default, forcing implementors to provide environment-specific bootstrap logic. This follows the trait's design as an extensible abstraction.
211-589: LGTM! Excellent test coverage of trait defaults.The test suite thoroughly validates all default trait implementations:
ensure_schema: version matching, mismatches, overrides, missing metadatainspect_state: table presence, watermark queries, case insensitivity, error handlingreset_db: operation ordering, version handling, partial failure propagationThe
MockDbapproach effectively tracks call order and verifies SQL statement execution.
| async fn run<DB>( | ||
| &self, | ||
| db: &DB, | ||
| db_schema_version: Option<u32>, | ||
| config: &BootstrapConfig, | ||
| ) -> Result<(), LocalDbError> | ||
| where | ||
| DB: LocalDbQueryExecutor + ?Sized, | ||
| { | ||
| self.reset_db(db, db_schema_version).await?; | ||
|
|
||
| if let Some(dump_stmt) = &config.dump_stmt { | ||
| db.query_text(dump_stmt).await?; | ||
| } | ||
|
|
||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Unconditional reset behavior should be documented or reconsidered.
The run method always calls reset_db without inspecting the current database state (no calls to inspect_state or ensure_schema first). This means every bootstrap operation in producer mode wipes the entire database, even if the schema is already correct and data exists.
Compare this to ClientBootstrapAdapter (in crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs) which conditionally resets based on state inspection, schema validation, and threshold checks.
If the unconditional reset is intentional for the producer workflow (e.g., always starting with a clean slate for dump generation), consider:
- Adding a doc comment explaining this destructive behavior
- Or, adding a minimal schema check before reset to avoid unnecessary data loss
Consider adding documentation:
#[async_trait::async_trait(?Send)]
impl BootstrapPipeline for ProducerBootstrapAdapter {
+ /// Producer bootstrap always resets the database to ensure a clean slate
+ /// for dump generation, regardless of current schema or data state.
async fn run<DB>(
&self,
db: &DB,Or consider adding a schema check to avoid unnecessary resets:
async fn run<DB>(
&self,
db: &DB,
db_schema_version: Option<u32>,
config: &BootstrapConfig,
) -> Result<(), LocalDbError>
where
DB: LocalDbQueryExecutor + ?Sized,
{
// Only reset if needed
if self.ensure_schema(db, db_schema_version).await.is_err() {
self.reset_db(db, db_schema_version).await?;
}
if let Some(dump_stmt) = &config.dump_stmt {
db.query_text(dump_stmt).await?;
}
Ok(())
}🤖 Prompt for AI Agents
In crates/cli/src/commands/local_db/pipeline/bootstrap.rs around lines 19–35,
the run() unconditionally calls reset_db which wipes the DB; either document
this destructive behavior or avoid unnecessary resets—add a short doc comment on
the method explaining that producer bootstrap intentionally starts from a clean
DB if that is intended, and implement a minimal schema check before resetting:
call ensure_schema(db, db_schema_version).await and only call reset_db if
ensure_schema reports an error/invalid schema (or if inspection indicates reset
is required), then proceed to apply dump_stmt as before; keep error handling and
return types intact.
There was a problem hiding this comment.
@findolor, understood! I'll skip this suggestion. The unconditional reset behavior will remain as-is in the producer bootstrap flow.
/\_/\
( o.o )
> ^ <
/| |
(| |)
🧠 Learnings used
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2159
File: crates/cli/src/commands/local_db/sync/runner/mod.rs:52-113
Timestamp: 2025-10-06T14:41:41.909Z
Learning: The local DB sync CLI command (crates/cli/src/commands/local_db/sync/) is designed for CI-only usage, and simple println! statements are preferred over structured logging for status messages.
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2123
File: crates/common/src/raindex_client/local_db/mod.rs:23-29
Timestamp: 2025-10-06T11:13:29.956Z
Learning: In `crates/common/src/raindex_client/local_db/mod.rs`, the `Default` implementation for `LocalDb` that creates an RPC client pointing to `http://localhost:4444` is acceptable because the RPC client must be explicitly configured before actual usage in production scenarios.
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2237
File: crates/common/src/raindex_client/local_db/sync.rs:79-89
Timestamp: 2025-10-18T10:38:41.273Z
Learning: In `crates/common/src/raindex_client/local_db/sync.rs`, the sync_database method currently only supports indexing a single orderbook per chain ID, which is why `.first()` is used to select the orderbook configuration. Multi-orderbook support per chain ID is planned for future PRs.
Learnt from: findolor
Repo: rainlanguage/rain.orderbook PR: 2145
File: crates/common/src/raindex_client/local_db/query/create_tables/query.sql:71-72
Timestamp: 2025-10-06T11:44:07.888Z
Learning: The local DB feature in the rain.orderbook codebase is not live yet (as of PR #2145), so schema migrations for existing databases are not required when modifying table structures in `crates/common/src/raindex_client/local_db/query/create_tables/query.sql`.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:24:53.708Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, provide a separate comment after each review with PR size statistics in the format: `TOTAL=number ADDITIONS=number DELETIONS=number`, excluding lock files like package-lock.json and cargo.lock.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T21:25:47.873Z
Learning: After each new commit review for rainlanguage/rain.orderbook repository, generate a PR size report in a separate comment with the format: "TOTAL=number ADDITIONS=number DELETIONS=number". This report should exclude irrelevant files such as lock files (e.g., package-lock.json, cargo.lock).
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T22:14:22.646Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, I must consistently report the PR size after EVERY new commit in the exact format "TOTAL=number\nADDITIONS=number\nDELETIONS=number" without any formatting blocks. The report must exclude lock files (package-lock.json, yarn.lock, pnpm-lock.yaml, cargo.lock) and can be included either as part of the review or as a separate comment.
Learnt from: rouzwelt
Repo: rainlanguage/rain.orderbook PR: 0
File: :0-0
Timestamp: 2025-05-21T22:14:22.646Z
Learning: For PR #1884 in rainlanguage/rain.orderbook, I must consistently report the PR size after EVERY new commit in the exact format "TOTAL=number\nADDITIONS=number\nDELETIONS=number" without any additional text or formatting blocks. The report must exclude lock files (package-lock.json, yarn.lock, pnpm-lock.yaml, cargo.lock) and can be included either as part of the review or as a separate comment.
|
@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment: S/M/L PR Classification Guidelines:This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed. Small (S)Characteristics:
Review Effort: Would have taken 5-10 minutes Examples:
Medium (M)Characteristics:
Review Effort: Would have taken 15-30 minutes Examples:
Large (L)Characteristics:
Review Effort: Would have taken 45+ minutes Examples:
Additional Factors to ConsiderWhen deciding between sizes, also consider:
Notes:
|
|
Tip For best results, initiate chat on the files or code changes. SIZE=L 🧠 Learnings used |
Caution
Do not merge before: rainlanguage/rain.strategies#67
Motivation
See issues:
sync_database_with_servicesinto Testable Stages #2233Solution
db_metadataandtarget_watermarkstables and related queriesBootstrapPipelinetrait to fit better for our requirementsDefaultBootstrapPipelineimplementation that is shared by both client and producerClientBootstrapPipelineimplementation for client run flowProducerBootstrapPipelineimplementation for producer run flowChecks
By submitting this for review, I'm confirming I've done the following:
Summary by CodeRabbit
New Features
Bug Fixes