Skip to content

Commit 340e78c

Browse files
committed
Let native DI own functional test logging
Register the native file logger before host Build and keep its lifetime with the service provider. Preserve the six initial log identities and cold-reopen behavior, and move routing creation into the existing host factory. Validation: strict Release build of Unit, Integration and Recovery with all real dependencies and unchanged analyzers; 0 warnings, 0 errors. Current operation tests and exact-head Linux qualification remain open.
1 parent c7c5ed4 commit 340e78c

9 files changed

Lines changed: 67 additions & 66 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ The earlier resource-lifetime and analytics-root repair checkpoint passed its st
9898

9999
Поточний foundation-пакет пройшов strict Release збірку Recovery та його залежностей (**R720: 0 warnings / 0 errors за 83,76 с**) і весь пов’язаний набір **R722: 21/21 process-recovery тестів за 56,53 с**, native parallelism 50, без coverage collector. Код і DLL цього прогону незмінні; сторонні benchmark-зміни зафіксовані окремо. Попередній Unit-прогін R700 на `ad39b50` дав **103/124 PASS, 21 FAIL**; виправлення потребують актуального Unit та public ONE/RF3/cold виконання. Повна solution-збірка й Linux qualification залишаються OPEN. Raw coverage 27,30% належить старому невдалому focused-прогону лише 7 production modules і не є повним поточним покриттям.
100100

101-
Linux CI на `abc0a1dbd` зупинився перед тестами на восьми compiler/analyzer помилках у нових Unit-тестах. Поточний source-checkpoint виправляє їх у шести файлах зі збереженням повних operation/assertion сценаріїв; актуальна збірка й повторне виконання ще потрібні. Окремий benchmark-пакет переходить до 22 shared sessions (11 баз × 1/3 вузли), починаючи із семи document-сценаріїв та вимірюваного початкового завантаження 1 млн записів без warmup/reseed. Це source-реалізація: повна model/client matrix та Linux benchmark qualification залишаються OPEN.
101+
Linux CI на `c7c5ed489` зупинився перед тестами на CA2000 у тестовому файловому logger. Поточний пакет передає його lifetime штатному DI та переносить routing creation до наявної factory. **R738: Unit, Integration і Recovery разом із реальними залежностями зібралися з 0 warnings / 0 errors за 169,70 с, source drift 0.** Поточні Unit70, Recovery21 та розширені public ONE/RF3/cold/file сценарії ще потребують виконання; попередній Recovery PASS зберігає свій початковий source scope. Повна solution-збірка та повторна Linux qualification залишаються OPEN. Окремий benchmark-пакет переходить до 22 shared sessions (11 баз × 1/3 вузли), починаючи із семи document-сценаріїв та вимірюваного початкового завантаження 1 млн записів без warmup/reseed. Це source-реалізація: повна model/client matrix та Linux benchmark qualification залишаються OPEN.
102102

103103
The separate [all-model cold-reopen pair](docs/Features/DatabaseComposition/FunctionalDatabaseColdReopen.md) also passed on `57cea624`: **one node in 104.61 seconds, then RF3 in 118.73 seconds**. After all original nodes restarted through Aspire, both clients replayed the original SQL, mixed-model and blob-stage commands with complete receipt/value checks, then verified persisted grant revocation, repair and a healthy write. These tests keep the same physical roots and credentials. They use three cold-only identities and do not claim the normal gate's eight-user concurrency.
104104

‎docs/implementation/status.json‎

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"NATIVE-FOUNDATION-REPAIR-20261017": {
33
"status": "in_progress",
4-
"implementation": "The follow-up118-source native foundation repair is integrated: real provider-owned discard-only composition preparation, genuine native Server connection fixtures, corrected source/target lifetime authorities and original creation-derived full result oracles. Strict Recovery plus its actual project closure passed R720 with zero warnings/errors; all related21 native process-recovery cases passed R722 without coverage collector. Current Unit70 and expanded public ONE/RF3/cold/file qualification remain open. Original105 acceptance states remain20 done/85 in_progress.",
4+
"implementation": "The follow-up118-source native foundation repair is integrated. The current seven-file native test-host repair transfers the logger lifetime to native DI and moves routing creation to the existing factory, preserving initial-only logging and cold/cleanup flows. R738 strict Unit, Integration and Recovery projects plus their real dependency graph passed with zero warnings/errors and zero source drift. Related current Unit70, Recovery21 and expanded public ONE/RF3/cold/file execution remain open; old R722 Recovery21 PASS retains its original source scope. Original105 acceptance states remain20 done/85 in_progress.",
55
"sourceIdentity": {
66
"evidence": "TestResults/stage61-native-join/root-r720-native118-current-source.original.json",
77
"sha256": "d2a3f345efe45c7982811817d1597f17214737e6e107a3800c403f076f05fca1",
@@ -19,8 +19,8 @@
1919
"sourceRepairFiles": 6,
2020
"sourceRepairEvidence": "TestResults/stage61-native-join/root-r728-main-ci6-source.original.json",
2121
"sourceRepairSha256": "daaab72358b90b57eb1cee14ecb0bb7c4b22ff3cf3189765266d7c3ea7b0b28b",
22-
"sourceRepairStatus": "Integrated and independently source-reviewed; existing API imports/constants, target-reference assertion responsibility and native logging-provider ownership are preserved. Current Unit/public runtime and repeated Linux qualification remain OPEN.",
23-
"localIntegrationCompiler": "R728 joined after16.940249874955043 seconds with zero warnings and one CA2025 error in the separately owned benchmark Session library; whole-source drift0. Unit/Integration compilation was blocked by that real dependency, not qualified as passing."
22+
"sourceRepairStatus": "Original six-file fixes are checkpointed at c7c5ed489. Linux c7 stopped before tests on the remaining CA2000 logger ownership diagnostic. The current seven-file native DI/creation-factory follow-up passed local strict R738; fresh exact-head Linux/runtime qualification remains OPEN.",
23+
"localIntegrationCompiler": "R738 native solution filter compiled Unit, Integration and Recovery together with all actual ProjectReferences/analyzers: zero warnings/errors in169.70172954094596 seconds, source drift0. Full solution and Linux qualification remain separate OPEN gates."
2424
},
2525
"strictRecoveryCompiler": {
2626
"label": "root-r720-foundation-recovery-release",
@@ -139,6 +139,27 @@
139139
"total": 105,
140140
"done": 20,
141141
"in_progress": 85
142+
},
143+
"currentFoundationCompiler": {
144+
"label": "root-r738-foundation-client-filter-release",
145+
"result": "passed",
146+
"warnings": 0,
147+
"errors": 0,
148+
"elapsedSeconds": 169.70172954094596,
149+
"scope": "Unit, Integration and Recovery projects in one native solution filter, with actual dependencies and unchanged analyzers; not full solution or benchmark-stage verification",
150+
"sourceDrift": [],
151+
"expectedCompiledImageUpdates": 52,
152+
"stdout": "TestResults/stage61-native-join/root-r738-foundation-client-filter-release.stdout.original.txt",
153+
"stdoutSha256": "3146caddff9b6d9e0f9525b389623b1606af3e152b49e1be2f7b536cfed335dd",
154+
"completion": "TestResults/stage61-native-join/root-r738-foundation-client-filter-release.completion.original.json",
155+
"completionSha256": "c9ceeb092a8f2c57e605b0ca32a65a3bf9be47335d049152ac485b909cc3ba63"
156+
},
157+
"nativeDiLoggerRepair": {
158+
"sourceFiles": 7,
159+
"sourceManifest": "TestResults/stage61-native-join/root-r738-main-native-di7-source.prepared.json",
160+
"sourceManifestSha256": "0c8d2e524b224409ffc61e479bc009626f76e0bd9378fc31127c1674a707930f",
161+
"contract": "Factory-created singleton ILoggerProvider is owned by native DI before host Build; initial six log identities and assertions remain, cold reopen does not replay that callback. Existing creation factory owns routing creation; no cap raise or suppression. Arbitrary native Build-failure cleanup is not claimed from source inspection.",
162+
"qualification": "Strict local compiler PASS only. Fresh Unit, Recovery and public ONE/RF3/cold/file runtime and exact-head Linux qualification OPEN."
142163
}
143164
},
144165
"BENCHMARK-SOURCE-REDESIGN-20261017": {

‎src/KeyLoad.Server/Features/ClientApi/Hosting/ServerConfiguration.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ internal static async Task<WebApplication> BuildAsync(string[] args, IGrainParti
2020
IPartitionMovementNativeObserver? partitionMovementNativeObserver = null,
2121
Func<IServiceProvider, ILifecycleParticipant<ISiloLifecycle>>? lifecycleParticipantFactory = null,
2222
IGrainRequestPhaseObserver? phaseObserver = null, IGrainRequestPurposeObserver? purposeObserver = null,
23+
Action<IServiceCollection, NodeOptions>? configureServices = null,
2324
CancellationToken startupCancellation = default)
2425
{
2526
startupCancellation.ThrowIfCancellationRequested();
@@ -42,6 +43,7 @@ internal static async Task<WebApplication> BuildAsync(string[] args, IGrainParti
4243
}
4344
DatabaseAuthenticationComposition.Register(builder.Services);
4445
McpServerComposition.Register(builder);
46+
configureServices?.Invoke(builder.Services, node.Value);
4547
var app = builder.Build();
4648
try
4749
{

‎tests/KeyLoad.CrashHost/Features/ClusterRouting/Fixtures/ControlledPartitionMovementNativeApplicationFactory.cs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using KeyLoad.Clustering;
22
using KeyLoad.Server;
3+
using Microsoft.Extensions.DependencyInjection;
34

45
namespace KeyLoad.CrashHost.Features.ClusterRouting;
56

@@ -11,13 +12,14 @@ internal static async Task<ControlledPartitionMovementNativeHost> CreateAsync(st
1112
IDatabaseAuthenticationExecutionObserver? authenticationObserver,
1213
Func<IServiceProvider, ILifecycleParticipant<ISiloLifecycle>>? lifecycleParticipantFactory,
1314
IGrainRequestPhaseObserver? phaseObserver, IGrainRequestPurposeObserver? purposeObserver,
14-
CancellationToken startupCancellation)
15+
Action<IServiceCollection, NodeOptions>? configureServices, CancellationToken startupCancellation)
1516
{
1617
var nativeObservation = new ControlledPartitionMovementNativeObservationWitness();
1718
var application = await ServerConfiguration.BuildAsync(arguments, sealedObserver: sealedObserver,
1819
localhostClustering: localhostClustering, authenticationExecutionObserver: authenticationObserver,
1920
partitionMovementNativeObserver: nativeObservation, lifecycleParticipantFactory: lifecycleParticipantFactory,
20-
phaseObserver: phaseObserver, purposeObserver: purposeObserver, startupCancellation: startupCancellation).ConfigureAwait(false);
21+
phaseObserver: phaseObserver, purposeObserver: purposeObserver, configureServices: configureServices,
22+
startupCancellation: startupCancellation).ConfigureAwait(false);
2123
try
2224
{
2325
return new(application, nativeObservation);

‎tests/KeyLoad.CrashHost/Features/ClusterRouting/Fixtures/ControlledPartitionMovementNativeHost.cs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ internal static Task<ControlledPartitionMovementNativeHost> CreateAsync(string[]
4848
IDatabaseAuthenticationExecutionObserver? authenticationObserver = null,
4949
Func<IServiceProvider, ILifecycleParticipant<ISiloLifecycle>>? lifecycleParticipantFactory = null,
5050
IGrainRequestPhaseObserver? phaseObserver = null, IGrainRequestPurposeObserver? purposeObserver = null,
51+
Action<IServiceCollection, NodeOptions>? configureServices = null,
5152
CancellationToken startupCancellation = default)
5253
=> ControlledPartitionMovementNativeApplicationFactory.CreateAsync(arguments, localhostClustering,
53-
sealedObserver, authenticationObserver, lifecycleParticipantFactory, phaseObserver, purposeObserver, startupCancellation);
54+
sealedObserver, authenticationObserver, lifecycleParticipantFactory, phaseObserver, purposeObserver, configureServices, startupCancellation);
5455

5556
internal WebApplication Application
5657
{

‎tests/KeyLoad.CrashHost/Features/ClusterRouting/Fixtures/ControlledPartitionMovementNativeHostFactory.cs‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using KeyLoad.Clustering;
22
using KeyLoad.Server;
3+
using Microsoft.Extensions.DependencyInjection;
34
using Microsoft.Extensions.Options;
45

56
namespace KeyLoad.CrashHost.Features.ClusterRouting;
@@ -9,13 +10,26 @@ internal static class ControlledPartitionMovementNativeHostFactory
910
private const int FirstOwner = 0;
1011
internal static Task<ControlledPartitionMovementNativeHosts> CreateAsync(
1112
Func<int, IGrainPartitionMovementSealedOperationObserver>? observerFactory, CancellationToken cancellationToken)
12-
=> CreateAsync(observerFactory, null, null, null, null, null, null, cancellationToken);
13+
=> CreateAsync(observerFactory, null, null, null, null, null, null, null, cancellationToken);
14+
15+
internal static Task<ControlledPartitionMovementNativeHosts> CreateWithRoutingAsync(
16+
IOptions<GrainRoutingOptions> routingOptions, Func<int, IGrainRequestPhaseObserver> observerFactory,
17+
IGrainRequestPurposeObserver? purposeObserver,
18+
Action<int, IServiceCollection, NodeOptions>? configureServices,
19+
Action<int, ControlledPartitionMovementNativeHost>? beforeStart, CancellationToken cancellationToken)
20+
{
21+
ArgumentNullException.ThrowIfNull(routingOptions);
22+
ArgumentNullException.ThrowIfNull(observerFactory);
23+
return CreateAsync(null, null, observerFactory,
24+
null, routingOptions, purposeObserver, configureServices, beforeStart, cancellationToken);
25+
}
1326

1427
internal static async Task<ControlledPartitionMovementNativeHosts> CreateAsync(
1528
Func<int, IGrainPartitionMovementSealedOperationObserver>? observerFactory,
1629
Func<int, IDatabaseAuthenticationExecutionObserver>? authenticationObserverFactory,
1730
Func<int, IGrainRequestPhaseObserver>? phaseObserverFactory, int? maximumBatchBytes,
1831
IOptions<GrainRoutingOptions>? routingOptions, IGrainRequestPurposeObserver? purposeObserver,
32+
Action<int, IServiceCollection, NodeOptions>? configureServices,
1933
Action<int, ControlledPartitionMovementNativeHost>? beforeStart, CancellationToken cancellationToken)
2034
{
2135
using var endpoints = new ControlledPartitionMovementNativeHostEndpoints();
@@ -26,7 +40,7 @@ internal static async Task<ControlledPartitionMovementNativeHosts> CreateAsync(
2640
try
2741
{
2842
owner = new ControlledPartitionMovementNativeHosts(settings, new(endpoints.Primary), observerFactory, authenticationObserverFactory, phaseObserverFactory, purposeObserver);
29-
await owner.CreateNodesAsync(cancellationToken).ConfigureAwait(false);
43+
await owner.CreateNodesAsync(configureServices, cancellationToken).ConfigureAwait(false);
3044
if (beforeStart is not null)
3145
{
3246
for (var index = FirstOwner; index < owner.Nodes.Count; index++)

‎tests/KeyLoad.CrashHost/Features/ClusterRouting/Fixtures/ControlledPartitionMovementNativeHosts.cs‎

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using KeyLoad.Clustering;
22
using KeyLoad.Server;
3-
using Microsoft.Extensions.Options;
3+
using Microsoft.Extensions.DependencyInjection;
44

55
namespace KeyLoad.CrashHost.Features.ClusterRouting;
66

@@ -52,42 +52,38 @@ internal static Task<ControlledPartitionMovementNativeHosts> CreateWithAuthentic
5252
Func<int, IDatabaseAuthenticationExecutionObserver> observerFactory, CancellationToken cancellationToken)
5353
{
5454
ArgumentNullException.ThrowIfNull(observerFactory);
55-
return ControlledPartitionMovementNativeHostFactory.CreateAsync(null, observerFactory, null, null, null, null, null, cancellationToken);
55+
return ControlledPartitionMovementNativeHostFactory.CreateAsync(null, observerFactory, null, null, null, null, null, null, cancellationToken);
5656
}
5757

5858
internal static Task<ControlledPartitionMovementNativeHosts> CreateWithPhaseObserverAsync(
5959
Func<int, IGrainRequestPhaseObserver> observerFactory, CancellationToken cancellationToken)
6060
{
6161
ArgumentNullException.ThrowIfNull(observerFactory);
62-
return ControlledPartitionMovementNativeHostFactory.CreateAsync(null, null, observerFactory, null, null, null, null, cancellationToken);
62+
return ControlledPartitionMovementNativeHostFactory.CreateAsync(null, null, observerFactory, null, null, null, null, null, cancellationToken);
6363
}
6464

6565
internal static Task<ControlledPartitionMovementNativeHosts> CreateWithMaximumBatchBytesAsync(
6666
int maximumBatchBytes, CancellationToken cancellationToken)
6767
{
68-
return ControlledPartitionMovementNativeHostFactory.CreateAsync(null, null, null, maximumBatchBytes, null, null, null, cancellationToken);
69-
}
70-
71-
internal static Task<ControlledPartitionMovementNativeHosts> CreateWithRoutingAsync(
72-
IOptions<GrainRoutingOptions> routingOptions, Func<int, IGrainRequestPhaseObserver> observerFactory,
73-
IGrainRequestPurposeObserver? purposeObserver,
74-
Action<int, ControlledPartitionMovementNativeHost>? beforeStart, CancellationToken cancellationToken)
75-
{
76-
ArgumentNullException.ThrowIfNull(routingOptions);
77-
ArgumentNullException.ThrowIfNull(observerFactory);
78-
return ControlledPartitionMovementNativeHostFactory.CreateAsync(null, null, observerFactory,
79-
null, routingOptions, purposeObserver, beforeStart, cancellationToken);
68+
return ControlledPartitionMovementNativeHostFactory.CreateAsync(null, null, null, maximumBatchBytes, null, null, null, null, cancellationToken);
8069
}
8170

8271
internal void RetainCreationFailure(Exception original) => creationFailure = original;
8372

84-
internal async Task CreateNodesAsync(CancellationToken startupCancellation)
73+
internal Task CreateNodesAsync(CancellationToken startupCancellation)
74+
=> CreateNodesAsync(null, startupCancellation);
75+
76+
internal async Task CreateNodesAsync(Action<int, IServiceCollection, NodeOptions>? configureServices,
77+
CancellationToken startupCancellation)
8578
{
8679
observers.Prepare();
80+
var configureNode = configureServices;
8781
for (var index = SourceIndex; index < ControlledPartitionMovementNativeHostEndpoints.OwnerCount; index++)
8882
{
83+
var nodeIndex = index;
8984
nodes.Add(await ControlledPartitionMovementNativeHost.CreateAsync(settings.Arguments(index), localhost,
9085
observers.Sealed(index), observers.Authentication(index), phaseObserver: observers.Phase(index), purposeObserver: observers.Purpose,
86+
configureServices: configureNode is null ? null : (services, node) => configureNode(nodeIndex, services, node),
9187
startupCancellation: startupCancellation).ConfigureAwait(false));
9288
}
9389
}

0 commit comments

Comments
 (0)