Skip to content

feat(api): list bean batches across beans - #646

Merged
tadelv merged 3 commits into
mainfrom
odev/issue-564-bulk-bean-batches
Aug 24, 2026
Merged

feat(api): list bean batches across beans#646
tadelv merged 3 commits into
mainfrom
odev/issue-564-bulk-bean-batches

Conversation

@ODevStudio

@ODevStudio ODevStudio commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

What changed, and why?

  • Add GET /api/v1/bean-batches so inventory clients can fetch batches for
    every bean with one request instead of one request and SQLite query per bean.
  • Use one Drift query, preserve the existing default archived filter, accept
    includeArchived=true, and support the same conditional ETag behavior as
    the existing bean and per-bean batch collection routes.
  • Exclude batches whose parent bean is archived from the default collection,
    matching the motivating beans-then-batches workflow.
  • Keep the per-bean and single-batch routes unchanged. No speculative
    multi-ID filter or embedded-bean response was added.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore / infra
  • Plugin (DYE2 or bundled skin)

Scope (select all touched areas)

  • BLE transport / device comms
  • REST API / handlers
  • WebSocket API
  • Machine state / shot logic
  • Scale / weight / flow
  • Profiles / beans / grinders / workflows
  • WebUI skins
  • Plugins / JS runtime
  • UI / Flutter widgets
  • Storage / Drift database
  • CI / build / infra
  • Docs / specs

Linked Issues

Fixes #564

Remaining validation before merge: Maintainer review of the additive endpoint and a live API smoke with curl. No hardware is required.

Root Cause (if bug fix)

N/A - this adds a bulk read route for existing bean-batch data.

Regression Test Plan (if bug fix or refactor)

N/A - feature coverage in test/webserver/beans_handler_test.dart and
test/database/bean_dao_test.dart locks in cross-bean results, archived
batch and parent-bean filtering, one-query behavior, and conditional GET.

Documentation Obligations (required)

  • API spec updated: assets/api/rest_v1.yml or assets/api/websocket_v1.yml (if REST/WebSocket changed)
  • API docs updated: doc/Api.md (if user-facing endpoint changed)
  • Plugin docs updated: doc/Plugins.md (if events/API changed)
  • Skin docs updated: doc/Skins.md (if skin behavior changed)
  • Profile docs updated: doc/Profiles.md (if profile handling changed)
  • Device docs updated: doc/DeviceManagement.md (if device flows changed)
  • N/A - no docs affected

Security Impact (required)

  • New or changed REST endpoints? Yes; adds read-only
    GET /api/v1/bean-batches.
  • New or changed WebSocket topics? No.
  • New or changed network calls? No.
  • BLE/USB surface changed? No.
  • File system access changed? No.
  • Plugin sandbox boundary changed? No.
  • Risk and mitigation: The route exposes only batch records already available
    through per-bean routes, remains read-only, excludes archived batches and
    parent beans by default, and supports ETag validation.

User-Visible Changes

  • API clients can fetch bean batches across all beans with one request instead
    of issuing one request per bean.
  • Existing per-bean and single-batch routes and response objects are unchanged.

Verification

Local gates (run before pushing)

  • dart format lib test - no remaining candidate changes
  • flutter analyze - clean
  • flutter test - 3,181 passed, 1 skipped
  • ./scripts/fetch_dye2_plugin.sh - not rerun for this local draft

Manual verification (if applicable)

  • OS / platform tested: Windows test host; live app did not launch.
  • Simulated devices? (simulate=1): No; CMake stopped the build first.
  • Real hardware? (DE1/Bengle/scale): No, not applicable.
  • What you personally verified and how: Real Shelf handler and Drift DAO paths
    through integration tests.
  • Edge cases checked: Archived batches, archived parent beans,
    includeArchived=true, cross-bean ordering, ETag, and 304 Not Modified.
  • What you did not verify: A live curl request against a running app.

Evidence

  • Test output (failing before + passing after)
  • Log snippets
  • Screenshot / recording (UI changes)
  • curl / websocat output (API changes)

Detailed evidence:

  • Regression-first handler tests failed with 404 before the route existed,
    then passed with cross-bean results, archived filtering, and 304 handling.
  • The archived-parent regression exposed the inconsistent default collection
    before the follow-up and passes at the DAO and API-handler levels afterward.
  • flutter test test/webserver/beans_handler_test.dart test/database/bean_dao_test.dart (36 passed)
  • flutter analyze (no issues)
  • flutter test with the package-matched QuickJS DLL on PATH and the
    repository's temporary LF normalization for the line-ending-sensitive
    AsyncAPI assertion (3,181 passed, 1 skipped)
  • git diff --cached --check before commit (clean)
  • Attempted flutter run --no-pub -d windows --dart-define=simulate=1 for a
    live curl smoke. The local build stopped before launch because Flutter
    selected CMake 3.20 while the Firebase SDK requires CMake 3.22 or newer.

Compatibility & Migration

  • Backward compatible? Yes; this is an additive route.
  • Config / env changes needed? No.
  • Database migration needed? No; the existing beanBatches table is queried.
  • Exact steps: None.

Risks & Mitigations

  • Risk: A bulk collection could add database or response overhead for large
    inventories.
    • Mitigation: Use one Drift query, keep archived batches and parent beans
      excluded by default, and support conditional requests with ETag.

Contributor Responsibility

AI-assisted development is allowed. The submitter remains responsible for the submitted work.

  • I have reviewed and understand all changes in this PR and take responsibility for their correctness, security, behavior, licensing, and provenance, including any AI-assisted or AI-generated work.

Add a conditional collection endpoint backed by one Drift query so inventory clients no longer need one batch request per bean. Keep archived filtering aligned with the existing per-bean route and update the REST contract.
@ODevStudio
ODevStudio marked this pull request as ready for review August 22, 2026 14:07
@ODevStudio
ODevStudio requested a review from tadelv August 22, 2026 15:15
@tadelv
tadelv merged commit 4d18505 into main Aug 24, 2026
5 checks passed
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.

N+1 query pattern: no bulk "list all batches" endpoint forces clients into one GET per bean

2 participants