Skip to content

Commit 06c888b

Browse files
authored
Merge pull request #454 from GeneralLibrary/feature/refactor-update-flow
refactor: update flow architecture improvements
2 parents fb5ab6e + bb61051 commit 06c888b

75 files changed

Lines changed: 1398 additions & 1201 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/c#/DifferentialTest/Pipeline/DiffPipelineOptionsTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace DifferentialTest.Pipeline
44
{
55
/// <summary>
66
/// 分支覆盖点:
7-
/// 1. MaxDegreeOfParallelism — 默认 = Environment.ProcessorCount
7+
/// 1. MaxDegreeOfParallelism — 默认 = 2
88
/// 2. StopOnFirstError — 默认 = false
99
/// 3. DeletePatchAfterApply — 默认 = true
1010
/// 4. 属性 set/get — 修改后正确返回
@@ -15,12 +15,12 @@ namespace DifferentialTest.Pipeline
1515
/// </summary>
1616
public class DiffPipelineOptionsTests
1717
{
18-
[Fact(DisplayName = "默认构造_MaxDegreeOfParallelism为Environment.ProcessorCount")]
19-
public void DefaultConstructor_MaxDegreeOfParallelism_EqualsProcessorCount()
18+
[Fact(DisplayName = "默认构造_MaxDegreeOfParallelism为2")]
19+
public void DefaultConstructor_MaxDegreeOfParallelism_Equals2()
2020
{
2121
var options = new DiffPipelineOptions();
2222

23-
Assert.Equal(Environment.ProcessorCount, options.MaxDegreeOfParallelism);
23+
Assert.Equal(2, options.MaxDegreeOfParallelism);
2424
}
2525

2626
[Fact(DisplayName = "默认构造_StopOnFirstError为false")]

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

Lines changed: 57 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public void Cancel()
6565
public override async Task<GeneralUpdateBootstrap> LaunchAsync()
6666
{
6767
var appType = GetOption(UpdateOptions.AppType);
68+
_configInfo.AppType = appType;
6869

6970
// Silent mode: start background poll and return immediately
7071
if (appType == AppType.Client && GetOption(UpdateOptions.Silent))
@@ -75,9 +76,9 @@ public override async Task<GeneralUpdateBootstrap> LaunchAsync()
7576

7677
return appType switch
7778
{
78-
AppType.Client => await LaunchWithStrategy(new ClientUpdateStrategy()),
79+
AppType.Client => await LaunchWithStrategy(new ClientUpdateStrategy()),
7980
AppType.Upgrade => await LaunchWithStrategy(new UpgradeUpdateStrategy()),
80-
AppType.OSSClient => await LaunchWithStrategy(new OSSUpdateStrategy(AppType.OSSClient)),
81+
AppType.OSSClient => await LaunchWithStrategy(new OSSUpdateStrategy(AppType.OSSClient)),
8182
AppType.OSSUpgrade => await LaunchWithStrategy(new OSSUpdateStrategy(AppType.OSSUpgrade)),
8283
_ => await LaunchWithStrategy(new ClientUpdateStrategy())
8384
};
@@ -94,68 +95,40 @@ private async Task<GeneralUpdateBootstrap> LaunchWithStrategy(IStrategy roleStra
9495

9596
// Resolve hooks and reporter from extensions
9697
var hooks = ResolveExtension<Hooks.IUpdateHooks>() ?? new Hooks.NoOpUpdateHooks();
97-
var reporter = ResolveExtension<Download.Reporting.IUpdateReporter>() ?? new Download.Reporting.NoOpUpdateReporter();
98+
var reporter = ResolveExtension<Download.Reporting.IUpdateReporter>() ??
99+
new Download.Reporting.NoOpUpdateReporter();
98100

99-
// Configure client-specific callbacks
100-
if (roleStrategy is ClientUpdateStrategy clientStrat)
101-
{
102-
clientStrat.Hooks = hooks;
103-
clientStrat.Reporter = reporter;
104-
// Resolve DownloadSource from extension registry (Hub, custom, etc.)
105-
var resolvedSource = ResolveExtension<Download.Abstractions.IDownloadSource>();
106-
107-
// Inject SignalR Hub download source if configured
108-
if (resolvedSource == null)
109-
{
110-
var hubConfig = GetOption(UpdateOptions.Hub);
111-
if (hubConfig != null && !string.IsNullOrEmpty(hubConfig.Url))
112-
{
113-
var hubSource = new Download.Sources.HubDownloadSource(
114-
hubConfig.Url, _configInfo.Token, _configInfo.AppSecretKey);
115-
await hubSource.StartAsync().ConfigureAwait(false);
116-
resolvedSource = hubSource;
117-
GeneralTracer.Info("GeneralUpdateBootstrap: HubDownloadSource started from HubConfig.");
118-
}
119-
}
120-
clientStrat.DownloadSource = resolvedSource;
121-
if (_updatePrecheck != null)
122-
clientStrat.UseUpdatePrecheck(_updatePrecheck);
123-
await CallSmallBowlHomeAsync(_configInfo.Bowl).ConfigureAwait(false);
124-
}
125-
else if (roleStrategy is UpgradeUpdateStrategy upgradeStrat)
126-
{
127-
upgradeStrat.Hooks = hooks;
128-
upgradeStrat.Reporter = reporter;
129-
}
130-
else if (roleStrategy is OSSUpdateStrategy ossStrat)
131-
{
132-
ossStrat.Hooks = hooks;
133-
ossStrat.Reporter = reporter;
134-
}
101+
// ── Phase 1: inject all dependencies before Create ──
102+
roleStrategy.Hooks = hooks;
103+
roleStrategy.Reporter = reporter;
135104

136-
roleStrategy.Create(_configInfo);
137-
138105
var binaryDiffer = ResolveExtension<IBinaryDiffer>();
139106
var dirtyStrategy = ResolveExtension<IDirtyStrategy>();
107+
var diffPipeline = BuildDiffPipeline();
140108

141-
if (roleStrategy is ClientUpdateStrategy cs2)
142-
{
143-
if (binaryDiffer != null) cs2.SetBinaryDiffer(binaryDiffer);
144-
if (dirtyStrategy != null) cs2.SetDirtyStrategy(dirtyStrategy);
145-
}
146-
else if (roleStrategy is UpgradeUpdateStrategy us2)
109+
switch (roleStrategy)
147110
{
148-
if (binaryDiffer != null) us2.SetBinaryDiffer(binaryDiffer);
149-
if (dirtyStrategy != null) us2.SetDirtyStrategy(dirtyStrategy);
111+
case ClientUpdateStrategy cs:
112+
cs.DownloadSource = ResolveExtension<Download.Abstractions.IDownloadSource>();
113+
114+
if (_updatePrecheck != null)
115+
cs.UseUpdatePrecheck(_updatePrecheck);
116+
117+
await CallSmallBowlHomeAsync(_configInfo.Bowl).ConfigureAwait(false);
118+
119+
if (binaryDiffer != null) cs.SetBinaryDiffer(binaryDiffer);
120+
if (dirtyStrategy != null) cs.SetDirtyStrategy(dirtyStrategy);
121+
cs.SetDiffPipeline(diffPipeline);
122+
break;
123+
124+
case UpgradeUpdateStrategy us:
125+
if (binaryDiffer != null) us.SetBinaryDiffer(binaryDiffer);
126+
if (dirtyStrategy != null) us.SetDirtyStrategy(dirtyStrategy);
127+
us.SetDiffPipeline(diffPipeline);
128+
break;
150129
}
151130

152-
// Build DiffPipeline — user‑configured or default with BsdiffDiffer,
153-
// parallelism=2, and progress reporter wired to AddListenerProgress.
154-
var diffPipeline = BuildDiffPipeline();
155-
if (roleStrategy is ClientUpdateStrategy cs3)
156-
cs3.SetDiffPipeline(diffPipeline);
157-
else if (roleStrategy is UpgradeUpdateStrategy us3)
158-
us3.SetDiffPipeline(diffPipeline);
131+
roleStrategy.Create(_configInfo);
159132

160133
// Check custom skip condition before executing update
161134
if (_customSkipOption?.Invoke() == true)
@@ -173,24 +146,21 @@ private async Task<GeneralUpdateBootstrap> LaunchWithStrategy(IStrategy roleStra
173146
}
174147
finally
175148
{
176-
// Dispose HubDownloadSource if it was started
177-
if (roleStrategy is ClientUpdateStrategy cs && cs.DownloadSource is IAsyncDisposable ad)
178-
await ad.DisposeAsync();
179149
_cts?.Dispose();
180150
_cts = null;
181151
}
152+
182153
return this;
183154
}
184-
185-
155+
186156
// ════════════════════════════════════════════════════════════════
187157
// Configuration
188158
// ════════════════════════════════════════════════════════════════
189159

190160
public GeneralUpdateBootstrap SetConfig(Configinfo configInfo)
191-
{
192-
configInfo.Validate();
193-
_configInfo = ConfigurationMapper.MapToGlobalConfigInfo(configInfo);
161+
{
162+
configInfo.Validate();
163+
_configInfo = ConfigurationMapper.MapToGlobalConfigInfo(configInfo);
194164

195165
var appType = GetOption(UpdateOptions.AppType);
196166
if (appType != AppType.Upgrade)
@@ -223,7 +193,7 @@ public GeneralUpdateBootstrap SetConfig(string filePath)
223193

224194
// Resolve filename-only paths to current directory
225195
var hasPathChar = filePath.Contains(Path.DirectorySeparatorChar)
226-
|| filePath.Contains(Path.AltDirectorySeparatorChar);
196+
|| filePath.Contains(Path.AltDirectorySeparatorChar);
227197
var fullPath = hasPathChar
228198
? Path.GetFullPath(filePath)
229199
: Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filePath);
@@ -277,16 +247,18 @@ private void InitializeFromEnvironment()
277247
LastVersion = processInfo.LastVersion,
278248
UpdateLogUrl = processInfo.UpdateLogUrl,
279249
Encoding = Encoding.GetEncoding(processInfo.CompressEncoding),
280-
Format = processInfo.CompressFormat,
250+
Format = ParseFormat(processInfo.CompressFormat),
281251
DownloadTimeOut = processInfo.DownloadTimeOut,
282252
AppSecretKey = processInfo.AppSecretKey,
283253
UpdateVersions = processInfo.UpdateVersions,
284-
TempPath = StorageManager.GetTempDirectory("upgrade_temp"),
254+
TempPath = processInfo.TempPath,
285255
ReportUrl = processInfo.ReportUrl,
286256
BackupDirectory = processInfo.BackupDirectory,
287257
Scheme = processInfo.Scheme,
288258
Token = processInfo.Token,
289259
DriverDirectory = processInfo.DriverDirectory,
260+
UpdatePath = processInfo.UpdatePath,
261+
LaunchClientAfterUpdate = processInfo.LaunchClientAfterUpdate,
290262
BlackFiles = processInfo.BlackFiles ?? BlackListDefaults.DefaultBlackFiles,
291263
BlackFormats = processInfo.BlackFileFormats ?? BlackListDefaults.DefaultBlackFormats,
292264
SkipDirectorys = processInfo.SkipDirectorys ?? BlackListDefaults.DefaultSkipDirectories
@@ -306,11 +278,7 @@ private void ApplyRuntimeOptions()
306278
{
307279
// Preserve Upgrade path values set by InitializeFromEnvironment()
308280
_configInfo.Encoding ??= GetOption(UpdateOptions.Encoding);
309-
_configInfo.Format ??= GetOption(UpdateOptions.Format);
310-
// Normalize legacy "ZIP" default (UpdateOptions) to Format.ZIP (".zip")
311-
// so the pipeline constructs correct paths and CompressProvider matches its switch.
312-
if (_configInfo.Format == "ZIP")
313-
_configInfo.Format = Format.ZIP;
281+
_configInfo.Format = GetOption(UpdateOptions.Format);
314282
if (_configInfo.DownloadTimeOut <= 0)
315283
_configInfo.DownloadTimeOut = GetOption(UpdateOptions.DownloadTimeout) ?? 60;
316284

@@ -338,16 +306,15 @@ private async Task LaunchSilentAsync()
338306
GeneralTracer.Info("GeneralUpdateBootstrap: starting silent update mode.");
339307

340308
var pollMinutes = GetOption(UpdateOptions.SilentPollIntervalMinutes);
341-
var autoInstall = GetOption(UpdateOptions.SilentAutoInstall);
342309

343310
var silentOptions = new Silent.SilentOptions
344311
{
345-
PollInterval = TimeSpan.FromMinutes(pollMinutes),
346-
AutoInstall = autoInstall
312+
PollInterval = TimeSpan.FromMinutes(pollMinutes)
347313
};
348314

349315
var hooks = ResolveExtension<Hooks.IUpdateHooks>() ?? new Hooks.NoOpUpdateHooks();
350-
var reporter = ResolveExtension<Download.Reporting.IUpdateReporter>() ?? new Download.Reporting.NoOpUpdateReporter();
316+
var reporter = ResolveExtension<Download.Reporting.IUpdateReporter>() ??
317+
new Download.Reporting.NoOpUpdateReporter();
351318

352319
var orchestrator = new Silent.SilentPollOrchestrator(_configInfo, silentOptions)
353320
.WithHooks(hooks)
@@ -371,14 +338,26 @@ private DiffPipeline BuildDiffPipeline()
371338
.Build();
372339
}
373340

341+
private static Format ParseFormat(string? compressFormat)
342+
{
343+
if (string.IsNullOrWhiteSpace(compressFormat)) return Format.Zip;
344+
return compressFormat switch
345+
{
346+
".zip" => Format.Zip,
347+
_ => Format.Zip
348+
};
349+
}
350+
374351
private void InitBlackList()
375352
{
376353
// Build blacklist matcher from GlobalConfigInfo and set on StorageManager.
377354
// The matcher combines user config with system defaults.
378355
var effectiveConfig = new BlackListConfig(
379356
_configInfo.BlackFiles?.Count > 0 ? _configInfo.BlackFiles : BlackListDefaults.DefaultBlackFiles,
380357
_configInfo.BlackFormats?.Count > 0 ? _configInfo.BlackFormats : BlackListDefaults.DefaultBlackFormats,
381-
_configInfo.SkipDirectorys?.Count > 0 ? _configInfo.SkipDirectorys : BlackListDefaults.DefaultSkipDirectories
358+
_configInfo.SkipDirectorys?.Count > 0
359+
? _configInfo.SkipDirectorys
360+
: BlackListDefaults.DefaultSkipDirectories
382361
);
383362
StorageManager.BlackListMatcher = new DefaultBlackListMatcher(effectiveConfig);
384363
}
@@ -449,4 +428,4 @@ public GeneralUpdateBootstrap AddListenerProgress(
449428
AddListener<ProgressEventArgs>((s, e) => listener.OnProgress(e));
450429
return this;
451430
}
452-
}
431+
}

src/c#/GeneralUpdate.Core/Compress/CompressProvider.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@ public class CompressProvider
88
{
99
private CompressProvider() { }
1010

11-
public static void Compress(string compressType, string sourcePath, string destinationPath, bool includeRootDirectory, Encoding encoding)
11+
public static void Compress(Format compressType, string sourcePath, string destinationPath, bool includeRootDirectory, Encoding encoding)
1212
{
1313
var strategy = GetCompressionStrategy(compressType);
1414
strategy.Compress(sourcePath, destinationPath, includeRootDirectory, encoding);
1515
}
1616

17-
public static void Decompress(string compressType, string archivePath, string destinationPath, Encoding encoding)
17+
public static void Decompress(Format compressType, string archivePath, string destinationPath, Encoding encoding)
1818
{
1919
var strategy = GetCompressionStrategy(compressType);
2020
strategy.Decompress(archivePath, destinationPath, encoding);
2121
}
2222

23-
private static ICompressionStrategy GetCompressionStrategy(string compressType) => compressType switch
23+
private static ICompressionStrategy GetCompressionStrategy(Format compressType) => compressType switch
2424
{
25-
Format.ZIP => new ZipCompressionStrategy(),
25+
Format.Zip => new ZipCompressionStrategy(),
2626
_ => throw new ArgumentException("Compression format is not supported!")
2727
};
2828
}

0 commit comments

Comments
 (0)