Skip to content

fix(core): skip redundant chain packages after full fallback#526

Merged
JusterZhu merged 1 commit into
release/1.1.0-package-type-migrationfrom
fix/chain-fallback-skip-covered-versions
Jun 20, 2026
Merged

fix(core): skip redundant chain packages after full fallback#526
JusterZhu merged 1 commit into
release/1.1.0-package-type-migrationfrom
fix/chain-fallback-skip-covered-versions

Conversation

@JusterZhu

Copy link
Copy Markdown
Collaborator

Problem

When a chain package fails and falls back to a full replacement package, the application state is already at or beyond the full package's version. However, the pipeline loop continues processing subsequent chain packages with version ≤ the fallback version, causing redundant work (re-extracting and re-applying the same full package multiple times).

Root Cause

AbstractStrategy.ExecuteAsync iterates over all UpdateVersions in order, with no awareness that a previous fallback has already brought the application to a higher version. Each chain package failure independently triggers the same full-package fallback.

Solution

Track fallbackEffectiveVersion — the highest version achieved via full-package fallback — and skip any remaining chain packages whose version ≤ that value.

Changes

File Change
VersionEntry.cs Added FallbackFullVersion property
DownloadAsset.cs Added FallbackFullVersion field
DownloadPlanBuilder.cs Populate FallbackFullVersion from matching full package
ClientStrategy.cs Pass FallbackFullVersion to VersionEntry
AbstractStrategy.cs Track fallbackEffectiveVersion, skip covered chain packages
tests/ClientTest/Program.cs Enable StopOnFirstError, use PackageType.Full enum
tests/UpgradeTest/Program.cs Enable StopOnFirstError

Verification

Test output after fix:

AbstractStrategy.ExecuteAsync: skipping 2.0.0 (Client_C_v2.0.0) — already covered by fallback full package v3.0.0.
AbstractStrategy.ExecuteAsync: skipping 3.0.0 (Client_C_v3.0.0) — already covered by fallback full package v3.0.0.

When a chain package fails and falls back to a full replacement package,
the application state is already at or beyond the full package's version.
Subsequent chain packages with version ≤ the fallback version are now
skipped, avoiding redundant work.

Changes:
- Add FallbackFullVersion to VersionEntry, DownloadAsset for version tracking
- Populate FallbackFullVersion in DownloadPlanBuilder from matching full package
- Track fallbackEffectiveVersion in AbstractStrategy.ExecuteAsync loop
- Skip chain packages whose version ≤ fallbackEffectiveVersion
- Enable StopOnFirstError in ClientTest and UpgradeTest for fallback testing
- Use PackageType enum instead of magic number in ClientTest display

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

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 prevents redundant work during update application when a chain (diff) package fails and falls back to a full replacement package. After a successful full fallback, it tracks the effective version reached and skips subsequent chain packages that are already covered by that fallback version.

Changes:

  • Add FallbackFullVersion to the download/config models and populate it when building the download plan.
  • Pass FallbackFullVersion through ClientStrategy into VersionEntry.
  • In AbstractStrategy.ExecuteAsync, track the highest fallback full version and skip covered chain packages.
  • Update test programs to enable DiffPipeline “stop on first error” and adjust test output labeling.

Reviewed changes

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

Show a summary per file
File Description
tests/UpgradeTest/Program.cs Enables WithStopOnFirstError(true) for the diff pipeline in upgrade test harness.
tests/ClientTest/Program.cs Enables WithStopOnFirstError(true) and adjusts package type display logic in client test harness.
src/c#/GeneralUpdate.Core/Strategy/ClientStrategy.cs Propagates FallbackFullVersion from DownloadAsset into VersionEntry.
src/c#/GeneralUpdate.Core/Strategy/AbstractStrategy.cs Tracks fallback effective version and skips redundant chain packages after full fallback.
src/c#/GeneralUpdate.Core/Download/Models/DownloadAsset.cs Adds FallbackFullVersion to the download asset model.
src/c#/GeneralUpdate.Core/Download/DownloadPlanBuilder.cs Populates FallbackFullVersion by matching chain entries to fallback full packages.
src/c#/GeneralUpdate.Core/Configuration/VersionEntry.cs Adds FallbackFullVersion to the version entry contract for pipeline logic.

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

Comment on lines +161 to +168
if (fallbackEffectiveVersion != null
&& version.PackageType == (int)PackageType.Chain
&& Semver.TryParse(version.Version, out var versionSv)
&& versionSv <= fallbackEffectiveVersion)
{
GeneralTracer.Info($"AbstractStrategy.ExecuteAsync: skipping {version.Version} ({version.Name}) — already covered by fallback full package v{fallbackEffectiveVersion}.");
continue;
}
Comment on lines +216 to +221
if (!string.IsNullOrEmpty(version.FallbackFullVersion)
&& Semver.TryParse(version.FallbackFullVersion, out var ffv)
&& (fallbackEffectiveVersion == null || ffv > fallbackEffectiveVersion))
{
fallbackEffectiveVersion = ffv;
}
Comment on lines +10 to +11
using GeneralUpdate.Core.Pipeline;
using GeneralUpdate.Core.Configuration;
foreach (var vi in e.Info.Body)
{
var mode = vi.IsCrossVersion == true ? "CVP" : "Chain";
var mode = vi.PackageType == (int)PackageType.Full ? "Full" : "Chain";
@JusterZhu JusterZhu merged commit fbc7a16 into release/1.1.0-package-type-migration Jun 20, 2026
1 check passed
@JusterZhu JusterZhu deleted the fix/chain-fallback-skip-covered-versions branch June 20, 2026 09:45
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.

fix: chain fallback loop processes redundant packages after full package fallback

2 participants