Skip to content

Commit b771292

Browse files
committed
fix: AppType filtering, RecordId reporting, and MainOnly scenario report
- HttpDownloadSource: filter response by AppType for HasMainUpdate/HasUpgradeUpdate instead of only checking Body.Count > 0, preventing Both scenario misjudgment - ClientStrategy: capture _mainRecordId and _upgradeRecordId separately per AppType, copy RecordId into downloadVersions for IPC, add SafeReportUpdateAppliedAsync in MainOnly scenario, use explicit recordId in UpgradeOnly/Both reports - UpdateStrategy: read RecordId from UpdateVersions instead of hardcoded 0, add _reportType/SetReportType for poll(1) vs push(2) distinction - Add ReportType to ProcessInfo, GlobalConfigInfo, ConfigurationMapper for IPC - Bootstrap: wire ReportType from ProcessInfo to UpdateStrategy.SetReportType() - DiffPipeline: rename DeleteListFileName to generalupdate.delete.json
1 parent b49543b commit b771292

8 files changed

Lines changed: 85 additions & 93 deletions

File tree

src/c#/GeneralUpdate.Core/Bootstrap/GeneralUpdateBootstrap.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ private async Task<GeneralUpdateBootstrap> LaunchWithStrategy(IStrategy roleStra
177177

178178
case UpdateStrategy us:
179179
us.SetDiffPipeline(diffPipeline);
180+
us.SetReportType(_configInfo.ReportType);
180181
break;
181182
}
182183

@@ -369,6 +370,7 @@ private void InitializeFromEnvironment()
369370
DriverDirectory = processInfo.DriverDirectory,
370371
UpdatePath = processInfo.UpdatePath,
371372
LaunchClientAfterUpdate = processInfo.LaunchClientAfterUpdate,
373+
ReportType = processInfo.ReportType,
372374
BlackFiles = processInfo.BlackFiles ?? BlackListDefaults.DefaultBlackFiles,
373375
BlackFormats = processInfo.BlackFileFormats ?? BlackListDefaults.DefaultBlackFormats,
374376
SkipDirectorys = processInfo.SkipDirectorys ?? BlackListDefaults.DefaultSkipDirectories

src/c#/GeneralUpdate.Core/Configuration/ConfigurationMapper.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,15 @@ public static ProcessInfo MapToProcessInfo(
170170
List<VersionInfo> updateVersions,
171171
List<string> blackFileFormats,
172172
List<string> blackFiles,
173-
List<string> skipDirectories)
173+
List<string> skipDirectories,
174+
int reportType = 1)
174175
{
175176
if (source == null)
176177
throw new ArgumentNullException(nameof(source), "GlobalConfigInfo source cannot be null");
177178

178179
// 在单一位置创建 ProcessInfo,包含所有必需参数
179180
// 集中管理 ProcessInfo 的参数映射逻辑
180-
return new ProcessInfo(
181+
var processInfo = new ProcessInfo(
181182
appName: source.MainAppName, // MainAppName 映射到 ProcessInfo.UpdateAppName
182183
installPath: source.InstallPath,
183184
currentVersion: source.ClientVersion, // ClientVersion 映射到 ProcessInfo.CurrentVersion
@@ -201,6 +202,8 @@ public static ProcessInfo MapToProcessInfo(
201202
upgradePath: source.UpdatePath, // 自定义升级目录
202203
launchClient: source.LaunchClientAfterUpdate
203204
);
205+
processInfo.ReportType = reportType;
206+
return processInfo;
204207
}
205208
}
206209
}

src/c#/GeneralUpdate.Core/Configuration/GlobalConfigInfo.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ public class GlobalConfigInfo : BaseConfigInfo
9999
/// </summary>
100100
public bool LaunchClientAfterUpdate { get; set; } = true;
101101

102+
/// <summary>
103+
/// The report type for status reporting: 1 = Upgrade (active poll), 2 = Push (SignalR push).
104+
/// Passed from ClientStrategy through ProcessInfo to UpdateStrategy.
105+
/// </summary>
106+
public int ReportType { get; set; } = 1;
107+
102108
/// <summary>
103109
/// The list of version information objects to be updated.
104110
/// Populated from the update server response based on <see cref="IsUpgradeUpdate" /> and <see cref="IsMainUpdate" />.

src/c#/GeneralUpdate.Core/Configuration/ProcessInfo.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,5 +373,12 @@ public ProcessInfo(string appName
373373
/// </summary>
374374
[JsonPropertyName("LaunchClientAfterUpdate")]
375375
public bool LaunchClientAfterUpdate { get; set; } = true;
376+
377+
/// <summary>
378+
/// The report type for status reporting: 1 = Upgrade (active poll), 2 = Push (SignalR push).
379+
/// Passed from ClientStrategy to UpdateStrategy so it uses the same type when reporting.
380+
/// </summary>
381+
[JsonPropertyName("ReportType")]
382+
public int ReportType { get; set; } = 1;
376383
}
377384
}

src/c#/GeneralUpdate.Core/Download/Sources/HttpDownloadSource.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,11 @@ public async Task<DownloadSourceResult> ListAsync(CancellationToken token = defa
118118
_appSecretKey, _platform, _productId,
119119
_scheme, _token, token);
120120

121-
var hasMainUpdate = mainResp?.Body?.Count > 0;
122-
var hasUpgradeUpdate = upgradeResp?.Body?.Count > 0;
121+
// Check that returned VersionInfo items' AppType matches the requested type,
122+
// rather than just checking Count > 0. The server may return items whose
123+
// AppType doesn't match the request, which would mis-identify the scenario.
124+
var hasMainUpdate = mainResp?.Body?.Any(v => v.AppType == (int)AppType.Client) == true;
125+
var hasUpgradeUpdate = upgradeResp?.Body?.Any(v => v.AppType == (int)AppType.Upgrade) == true;
123126

124127
var assets = new List<DownloadAsset>();
125128

src/c#/GeneralUpdate.Core/Pipeline/DiffPipeline.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public class DiffPipeline
7676
private readonly IProgress<DiffProgress>? _progress;
7777

7878
private const string PatchExtension = ".patch";
79-
private const string DeleteListFileName = "generalupdate_delete_files.json";
79+
private const string DeleteListFileName = "generalupdate.delete.json";
8080

8181
/// <summary>
8282
/// Initializes a new pipeline instance with default options, default binary differ

src/c#/GeneralUpdate.Core/Strategy/ClientStrategy.cs

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ public class ClientStrategy : IStrategy
7272
private Download.Abstractions.IDownloadExecutor? _customDownloadExecutor;
7373
private Func<string?, Download.Abstractions.IDownloadPipeline>? _customDownloadPipelineFactory;
7474
private int _mainRecordId;
75+
private int _upgradeRecordId;
76+
private int _reportType = 1; // 1=Upgrade(active poll), 2=Push(SignalR push)
7577

7678
/// <summary>
7779
/// Update scenario determined by the server validation result, indicating which update targets are needed.
@@ -160,6 +162,16 @@ public ClientStrategy(Download.Abstractions.IDownloadOrchestrator? orchestrator)
160162
/// </remarks>
161163
public void SetOrchestrator(Download.Abstractions.IDownloadOrchestrator? orchestrator) => _orchestrator = orchestrator;
162164

165+
/// <summary>
166+
/// Sets the report type for status reporting. Injected by the bootstrap for push-triggered updates.
167+
/// </summary>
168+
/// <param name="reportType">1 = Upgrade (active poll), 2 = Push (SignalR push). Default is 1.</param>
169+
/// <remarks>
170+
/// When a push notification triggers the update (via SignalR hub), the caller should set this to 2
171+
/// so the server can distinguish push-triggered updates from active poll updates.
172+
/// </remarks>
173+
public void SetReportType(int reportType) => _reportType = reportType;
174+
163175
/// <summary>
164176
/// Sets a custom download retry policy. Registered and injected by the bootstrap via <c>.DownloadPolicy&lt;T&gt;()</c>.
165177
/// </summary>
@@ -427,8 +439,13 @@ private async Task ExecuteStandardWorkflowAsync()
427439

428440
var updateInfoArgs = new UpdateInfoEventArgs(versionResp);
429441

430-
// Capture the first RecordId for status reporting to GeneralSpacestation
431-
_mainRecordId = downloadPlan.Assets.FirstOrDefault().RecordId;
442+
// Capture RecordIds per AppType for status reporting.
443+
// Client packages are reported by UpdateStrategy (Bowl) via IPC; Upgrade packages
444+
// are applied in-place and reported by ClientStrategy.
445+
_mainRecordId = downloadPlan.Assets
446+
.FirstOrDefault(a => (a.AppType ?? (int)AppType.Client) == (int)AppType.Client)?.RecordId ?? 0;
447+
_upgradeRecordId = downloadPlan.Assets
448+
.FirstOrDefault(a => a.AppType == (int)AppType.Upgrade)?.RecordId ?? 0;
432449
EventManager.Instance.Dispatch(this, updateInfoArgs);
433450

434451
var isForcibly = downloadPlan.IsForcibly;
@@ -504,6 +521,7 @@ private async Task ExecuteStandardWorkflowAsync()
504521
// Build VersionInfo list with AppType preserved from server response.
505522
var downloadVersions = downloadPlan.Assets.Select(a => new VersionInfo
506523
{
524+
RecordId = a.RecordId,
507525
Name = a.Name,
508526
Hash = a.SHA256,
509527
Url = a.Url,
@@ -523,24 +541,29 @@ private async Task ExecuteStandardWorkflowAsync()
523541
case UpdateScenario.UpgradeOnly:
524542
await ApplyUpgradePackagesAsync(upgradeVersions).ConfigureAwait(false);
525543
await SafeOnAfterUpdateAsync(hooksCtx).ConfigureAwait(false);
526-
await SafeReportUpdateAppliedAsync(hooksCtx).ConfigureAwait(false);
544+
await SafeReportUpdateAppliedAsync(hooksCtx, _upgradeRecordId).ConfigureAwait(false);
527545
GeneralTracer.Info("ClientStrategy: Upgrade-only update applied, client continues running.");
528546
break;
529547

530548
case UpdateScenario.MainOnly:
531549
SendProcessIpc(clientVersions);
550+
await SafeOnAfterUpdateAsync(hooksCtx).ConfigureAwait(false);
551+
await SafeReportUpdateAppliedAsync(hooksCtx, _mainRecordId).ConfigureAwait(false);
532552
await SafeOnBeforeStartAppAsync(hooksCtx).ConfigureAwait(false);
533553
await LaunchUpgradeProcessAsync().ConfigureAwait(false);
534554
break;
535555

536556
case UpdateScenario.Both:
537557
await ApplyUpgradePackagesAsync(upgradeVersions).ConfigureAwait(false);
538558
await SafeOnAfterUpdateAsync(hooksCtx).ConfigureAwait(false);
539-
await SafeReportUpdateAppliedAsync(hooksCtx).ConfigureAwait(false);
559+
await SafeReportUpdateAppliedAsync(hooksCtx, _upgradeRecordId).ConfigureAwait(false);
540560
SendProcessIpc(clientVersions);
541561
await SafeOnBeforeStartAppAsync(hooksCtx).ConfigureAwait(false);
542562
await LaunchUpgradeProcessAsync().ConfigureAwait(false);
543563
break;
564+
case UpdateScenario.None:
565+
default:
566+
throw new ArgumentOutOfRangeException();
544567
}
545568
}
546569

@@ -584,7 +607,8 @@ private void SendProcessIpc(List<VersionInfo> clientVersions)
584607
_configInfo!, clientVersions,
585608
_configInfo!.BlackFormats ?? BlackListDefaults.DefaultBlackFormats,
586609
_configInfo.BlackFiles ?? BlackListDefaults.DefaultBlackFiles,
587-
_configInfo.SkipDirectorys ?? BlackListDefaults.DefaultSkipDirectories);
610+
_configInfo.SkipDirectorys ?? BlackListDefaults.DefaultSkipDirectories,
611+
_reportType);
588612

589613
_configInfo.ProcessInfo = JsonSerializer.Serialize(processInfo,
590614
ProcessInfoJsonContext.Default.ProcessInfo);
@@ -883,7 +907,7 @@ private async Task SafeReportUpdateStartedAsync(Hooks.UpdateContext ctx)
883907
{
884908
await Reporter
885909
.ReportAsync(new Download.Reporting.UpdateReport(_mainRecordId,
886-
(int)Download.Reporting.UpdateStatus.Updating, 1)).ConfigureAwait(false);
910+
(int)Download.Reporting.UpdateStatus.Updating, _reportType)).ConfigureAwait(false);
887911
}
888912
catch (Exception ex)
889913
{
@@ -901,7 +925,7 @@ private async Task SafeReportDownloadCompletedAsync(Hooks.UpdateContext ctx)
901925
{
902926
await Reporter
903927
.ReportAsync(new Download.Reporting.UpdateReport(_mainRecordId,
904-
(int)Download.Reporting.UpdateStatus.Updating, 1)).ConfigureAwait(false);
928+
(int)Download.Reporting.UpdateStatus.Updating, _reportType)).ConfigureAwait(false);
905929
}
906930
catch (Exception ex)
907931
{
@@ -920,7 +944,7 @@ private async Task SafeReportUpdateFailedAsync(Hooks.UpdateContext ctx, Exceptio
920944
{
921945
await Reporter
922946
.ReportAsync(new Download.Reporting.UpdateReport(_mainRecordId,
923-
(int)Download.Reporting.UpdateStatus.Failure, 1)).ConfigureAwait(false);
947+
(int)Download.Reporting.UpdateStatus.Failure, _reportType)).ConfigureAwait(false);
924948
}
925949
catch (Exception ex)
926950
{
@@ -932,13 +956,13 @@ await Reporter
932956
/// Safely reports the update applied success status. If the report fails, logs a warning.
933957
/// </summary>
934958
/// <param name="ctx">The update context.</param>
935-
private async Task SafeReportUpdateAppliedAsync(Hooks.UpdateContext ctx)
959+
private async Task SafeReportUpdateAppliedAsync(Hooks.UpdateContext ctx, int recordId)
936960
{
937961
try
938962
{
939963
await Reporter
940-
.ReportAsync(new Download.Reporting.UpdateReport(_mainRecordId,
941-
(int)Download.Reporting.UpdateStatus.Success, 1)).ConfigureAwait(false);
964+
.ReportAsync(new Download.Reporting.UpdateReport(recordId,
965+
(int)Download.Reporting.UpdateStatus.Success, _reportType)).ConfigureAwait(false);
942966
}
943967
catch (Exception ex)
944968
{

0 commit comments

Comments
 (0)