Skip to content

chore: migrate rust/composite_query to icp-cli#1398

Open
marc0olo wants to merge 15 commits into
masterfrom
chore/migrate-rust-composite-query-to-icp-cli
Open

chore: migrate rust/composite_query to icp-cli#1398
marc0olo wants to merge 15 commits into
masterfrom
chore/migrate-rust-composite-query-to-icp-cli

Conversation

@marc0olo

@marc0olo marc0olo commented Jun 16, 2026

Copy link
Copy Markdown
Member

Summary

Migrates rust/composite_query from dfx to icp-cli.

Removed: dfx.json, BUILD.md, legacy workflow rust-composite_query-example.yml, old src/ layout

Changed:

  • Canister sources reorganised into backend/ (the Map canister, deployed) and bucket/ (the Bucket canister, compile-time dependency only) with a workspace Cargo.toml
  • Management canister usage updated from removed ic_cdk::api::management_canister to ic-cdk-management-canister = "0.1.1"
  • Inter-canister calls updated to ic_cdk::call::Call::bounded_wait + .candid_tuple().candid() uses decode_one (single value) while method responses require decode_args, so .candid_tuple() is correct
  • Cycle allocation per bucket changed from fixed 10T to dynamic (balance / (NUM_PARTITIONS + 1)), mirroring the Motoko approach
  • Routing made bounds-safe: get_partition_for_key returns Option<Principal> so get, get_update, and put return None gracefully before initialization instead of trapping

Added:

  • icp.yaml with custom build steps — bucket is built first so its WASM is available for include_bytes! in backend; only backend is deployed, Bucket instances are created on demand at runtime
  • test.sh with 7 tests covering put, composite query get, get_update, null lookup, multi-partition routing, and lookup
  • rust-composite_query job in the existing composite_query.yml workflow

Test plan

  • icp network start -d && icp deploy --cycles 30t && bash test.sh passes locally
  • CI rust-composite_query job passes

🤖 Generated with Claude Code

@marc0olo marc0olo force-pushed the chore/migrate-rust-composite-query-to-icp-cli branch from 1b6a681 to 60a8fd4 Compare June 17, 2026 17:00
@marc0olo marc0olo closed this Jun 19, 2026
@marc0olo marc0olo force-pushed the chore/migrate-rust-composite-query-to-icp-cli branch from 60a8fd4 to 8f077c8 Compare June 19, 2026 06:35
marc0olo and others added 2 commits June 19, 2026 09:38
- Replace dfx.json with icp.yaml using @dfinity/rust@v3.3.0
- Rename canisters: kv_frontend → caller, data_partition → callee
- Move each canister into its own subdirectory (caller/, callee/)
- Update workspace Cargo.toml to reference new members
- Rewrite caller/lib.rs: replace ic_cdk::api::management_canister with
  ic-cdk-management-canister crate, replace ic_cdk::api::call::call with
  ic_cdk::call::Call::bounded_wait pattern
- Add Makefile with 7 tests covering put, composite query get, get_update,
  null lookup, multi-partition routing, and lookup composite query
- Add rust-toolchain.toml with wasm32-unknown-unknown target
- Add rust-composite_query job to composite_query.yml workflow
- Delete legacy rust-composite_query-example.yml workflow
- Update README with icp-cli deploy instructions and architecture diagram

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…1.0.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@marc0olo marc0olo reopened this Jun 19, 2026
marc0olo and others added 7 commits June 19, 2026 09:53
…fixes

- Replace recipe with custom build steps: callee is built first so its
  WASM is available for include_bytes! in the caller. Only caller is
  deployed; callee is a compile-time dependency, not a deployed canister.
- Add ic_cdk::export_candid!() to both caller and callee
- Remove redundant networks block from icp.yaml
- Add Node.js to README prerequisites
- Fix make topup -> icp canister top-up --amount 30t caller

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Aligns with the Motoko example (Map/Bucket) and icp-cli conventions:
- caller/ -> backend/ (package: backend) — the Map canister, deployed via icp.yaml
- callee/ -> bucket/ (package: bucket) — the Bucket canister, built as a
  compile-time dependency embedded via include_bytes! in backend

Also fixes pre-existing include_bytes! path bug: ../../target/ was pointing
one level too high (to rust/target/ instead of rust/composite_query/target/).
Corrected to ../target/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ke Motoko

Fixed InsufficientLiquidCycleBalance in CI: hardcoded 10T per bucket
exceeded the available balance. Now divides evenly like the Motoko example:
  cycleShare = Cycles.balance() / (NUM_PARTITIONS + 1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ic-cdk 0.20's candid::<T>() uses decode_one (single value) but a canister
method's return is encoded as a Candid argument list, which requires
decode_args (used by candid_tuple). Using candid::<T>() caused all
inter-canister call responses to decode silently as None, making test 2
fail (put returned null instead of the previous value).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…og messages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@marc0olo marc0olo marked this pull request as ready for review June 19, 2026 08:30
@marc0olo marc0olo requested review from a team as code owners June 19, 2026 08:30
@marc0olo marc0olo requested a review from Copilot June 19, 2026 08:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Migrates rust/composite_query from the legacy dfx-based layout to an icp-cli-compatible setup, restructuring the Rust code into a workspace with a deployable backend (Map) canister that dynamically creates Bucket child canisters at runtime, and updating CI/testing accordingly.

Changes:

  • Replaced dfx project config and old src/ canister layout with an icp.yaml-driven build and a Rust workspace (backend/ + bucket/).
  • Updated management canister integration to ic-cdk-management-canister and modernized inter-canister call decoding (.candid_tuple()).
  • Added a test.sh suite and wired a new rust-composite_query job into the shared workflow.

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
rust/composite_query/test.sh Adds an icp-cli test script covering key behaviors (put/get/get_update/lookup/routing).
rust/composite_query/rust-toolchain.toml Ensures the wasm target is available for builds.
rust/composite_query/README.md Updates documentation for icp-cli deploy/test flow and explains architecture.
rust/composite_query/icp.yaml Introduces custom build steps to build/embed bucket.wasm and inject candid metadata.
rust/composite_query/Cargo.toml Converts the project into a workspace with backend and bucket members.
rust/composite_query/backend/lib.rs New backend canister that shards keys across dynamically created bucket canisters.
rust/composite_query/backend/Cargo.toml Adds the backend crate dependencies (ic-cdk, ic-cdk-management-canister).
rust/composite_query/bucket/lib.rs Updates bucket canister implementation and adds candid export.
rust/composite_query/bucket/Cargo.toml Adds the bucket crate definition and dependencies.
.github/workflows/composite_query.yml Adds a Rust job (containerized) for the migrated example.
.github/workflows/rust-composite_query-example.yml Removes the legacy dfx-based workflow.
rust/composite_query/dfx.json Removes legacy dfx configuration.
rust/composite_query/src/kv_frontend/lib.rs Removes the legacy frontend canister implementation.
rust/composite_query/src/kv_frontend/Cargo.toml Removes legacy frontend crate config.
rust/composite_query/src/kv_frontend.did Removes legacy frontend candid file.
rust/composite_query/src/data_partition/Cargo.toml Removes legacy partition canister crate config.
rust/composite_query/src/data_partition.did Removes legacy partition candid file.
rust/composite_query/Cargo.lock Removes the previous lockfile from the old workspace structure.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rust/composite_query/backend/lib.rs
Comment thread rust/composite_query/backend/lib.rs
Comment thread rust/composite_query/backend/lib.rs
Comment thread rust/composite_query/backend/lib.rs
…state

- get_partition_for_key returns Option<Principal> using .get() instead of
  direct indexing — safe for empty or partially-initialized CANISTER_IDS
- put/get/get_update return None early if the bucket for the key is not
  yet available (empty state or partial init from concurrent put)
- lookup uses .get().map().unwrap_or_default() instead of direct indexing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 5 comments.

Comment thread rust/composite_query/backend/lib.rs Outdated
Comment thread rust/composite_query/README.md
Comment thread rust/composite_query/icp.yaml Outdated
Comment thread rust/composite_query/test.sh
Comment thread rust/composite_query/test.sh Outdated
marc0olo and others added 3 commits June 19, 2026 11:07
- Compute cycle_share once before the loop so all buckets receive the
  same amount (fixes the decreasing-allocation bug)
- Update ic-wasm install hint to use npm instead of GitHub repo link
- Test 1: assert return value is null (new key has no previous value)
- Test 7: assert canister ID is non-empty (not just that index 1 appears)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removing the null assertion from test 1 — the return value is the
previous value for key 1 (null on first run, a nat on subsequent runs).
Tests 2-7 are already idempotent since they overwrite the same keys
with the same values each time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-runs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 3 comments.

Comment thread rust/composite_query/README.md Outdated
Comment thread rust/composite_query/backend/lib.rs Outdated
Comment thread rust/composite_query/backend/lib.rs
- Change lookup from #[query(composite = true)] to plain #[query] —
  it makes no inter-canister calls so composite = true is misleading;
  the composite query showcase is fully covered by get()
- Fix README: backend creates all 5 Bucket canisters on the first put
  call (not lazily per key as the old wording implied)
- Fix stale 'data partitions' comment -> 'Bucket canisters'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 1 comment.

Comment on lines +31 to 35
### Prerequisites

```bash
dfx canister call kv_frontend put '(1:nat, 1337:nat)'
(null)
dfx canister call kv_frontend put '(1:nat, 42:nat)'
(opt (1_337 : nat))
```
- Node.js
- icp-cli: `npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm`

candid-extractor is not part of the standard icp-cli prerequisites
(npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm). The custom build
steps are only needed to compile bucket before backend; dropping the
Candid interface extraction step removes the extra dependency.
The canister is fully functional without the candid:service WASM metadata.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants