Skip to content

fix(syncer-updates): separate target from floors in update logic#1291

Open
ervcz wants to merge 1 commit into
mainfrom
fix/floors-in-multiple-batch
Open

fix(syncer-updates): separate target from floors in update logic#1291
ervcz wants to merge 1 commit into
mainfrom
fix/floors-in-multiple-batch

Conversation

@ervcz

@ervcz ervcz commented Jan 13, 2026

Copy link
Copy Markdown
Collaborator

Problem

When more floor packages exist than NEBRASKA_MAX_FLOORS_PER_RESPONSE, the server incorrectly included the target in every batch. This caused syncers to skip remaining floors.

Solution

  • Server returns only floors (no target) when more floors remain beyond the limit
  • Target is included only when all floors have been sent
  • Syncer tracks highest floor version for next request when no target is present

Changes

  • GetUpdatePackagesForSyncer returns (floors, target, error) separately
  • GetRequiredChannelFloorsWithLimit uses LIMIT+1 to detect remaining floors
  • Syncer updates tracked version to highest floor when target is nil
  • Added TestFloorLimitPagination and TestSyncer_FloorLimitVersionTracking
  • Updated ADR-002 and operator guide documentation

@ervcz ervcz marked this pull request as ready for review January 23, 2026 09:53
@ervcz ervcz requested a review from a team as a code owner January 23, 2026 09:53
@ervcz ervcz force-pushed the fix/floors-in-multiple-batch branch from 4fc1de7 to ca2d4b8 Compare January 23, 2026 10:01
@ervcz ervcz force-pushed the feat/capture-oem-attribute branch 3 times, most recently from 17439e7 to efd1f3d Compare January 26, 2026 11:43
@ervcz ervcz force-pushed the feat/capture-oem-attribute branch from 2d52519 to 410381d Compare February 6, 2026 07:04
@ervcz ervcz force-pushed the feat/capture-oem-attribute branch from 410381d to 0ef741f Compare February 13, 2026 09:23
@ervcz ervcz force-pushed the feat/capture-oem-attribute branch from 0ef741f to db18dd5 Compare March 3, 2026 06:42
@ervcz ervcz force-pushed the feat/capture-oem-attribute branch 2 times, most recently from a0b40ea to a345261 Compare March 11, 2026 17:34
@ervcz ervcz force-pushed the feat/capture-oem-attribute branch from 7c54b45 to cbf596a Compare March 19, 2026 08:38
@ervcz ervcz force-pushed the feat/capture-oem-attribute branch 4 times, most recently from 71a3566 to a2e56c4 Compare April 21, 2026 07:43
@ervcz ervcz force-pushed the feat/capture-oem-attribute branch from a2e56c4 to 2875f04 Compare April 28, 2026 13:39
Base automatically changed from feat/capture-oem-attribute to main April 28, 2026 13:45
Bug: Syncer received batches with the target even if there were still
floor packages waiting to be sent. The target would have been used
by the next syncer omaha request and that prevented preparing the
remaining floors to be sent.

- Update GetUpdatePackagesForSyncer to handle floors and target separately
- Fix tests for multi-step-updates floor pagination for syncers
- Modify update selection to prioritize floors before target package
- Add LIMIT+1 query pattern for floor pagination detection
- Update architecture decisions doc

Signed-off-by: Ervin Rácz <ervin.racz@protonmail.com>
Copilot AI review requested due to automatic review settings June 29, 2026 11:56
@ervcz ervcz force-pushed the fix/floors-in-multiple-batch branch from ca2d4b8 to 02fcbcd Compare June 29, 2026 11:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes floor-package pagination for syncer update responses by separating floors from the target in the server update selection logic, and teaching the syncer to advance its reported version across floor-only batches until the target is finally included.

Changes:

  • Server API now returns (floors, target, error) for syncers, omitting the target when more floors remain past NEBRASKA_MAX_FLOORS_PER_RESPONSE.
  • Floor query uses a LIMIT + 1 strategy to detect whether additional floors remain.
  • Syncer tracks the highest floor version when no target is present; adds pagination-focused tests and updates ADR documentation.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
docs/ARD-001-multi-step-updates.md Removes the standalone ARD doc (content consolidated elsewhere).
docs/architecture-decisions.md Adds ADR-002 describing multi-step updates and the floor pagination behavior.
backend/pkg/syncer/syncer.go Updates multi-manifest processing to advance tracked version when receiving floor-only batches.
backend/pkg/syncer/syncer_multimanifest_test.go Adds a syncer-side test for floor limit version tracking across rounds.
backend/pkg/omaha/omaha.go Splits syncer response assembly into floors vs target; omits target when more floors remain.
backend/pkg/omaha/omaha_floors_test.go Refactors/extends Omaha tests to cover floor pagination and target inclusion rules.
backend/pkg/omaha/helpers_test.go Adds a shared doSyncerRequest helper for Omaha syncer test requests.
backend/pkg/api/updates.go Refactors update selection helpers and syncer update API to return floors and target separately.
backend/pkg/api/packages.go Minor formatting cleanup in a SQL query.
backend/pkg/api/packages_floors.go Introduces GetRequiredChannelFloorsWithLimit with LIMIT+1 pagination detection.
backend/pkg/api/packages_floors_test.go Updates tests to use the new floor query API and verifies the hasMore flag.

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

Comment on lines +113 to +117
- If package 3602.2.0 requires 3510.2.0 as prerequisite
- Later, 3815.0.0 is released WITHOUT prerequisites if prerquisit is not inherited
- Clients can jump directly to 3815.0.0, bypassing 3510.2.0

This means ALL future packages would need to inherit prerequisites, even for unrelated changes. Floor-based semantics solve this by making checkpoints a channel policy, not a package property. This way we have a central management of update path instead of tracking prerequisits for all later packages individually.
Comment on lines +480 to +483
// After round 1: syncer should track highest floor (2000.0.0)
// Channel should NOT be updated (no target in response)
trackedVersion := syncer.versions[desc]
t.Logf("After round 1, syncer tracked version: %s", trackedVersion)
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