Skip to content

Latest commit

 

History

History
95 lines (84 loc) · 5.67 KB

PartitionStorageStartup.md

File metadata and controls

95 lines (84 loc) · 5.67 KB

partition-storage partial startup and retained healthy ownership

This case covers ADR-136 and ADR-125 connection ownership. Its source uses the production ServerConfiguration.BuildAsync, Orleans localhost membership, and the shared RequestCqrsHostedProfile. One silo and one persisted copy are configured. The same frozen arguments, physical root and identities are reused for each cold application.

PartitionStorageGrainService.Init initiates physical opening. A test-owned lifecycle participant runs at ApplicationServices after RuntimeGrainServices. It awaits the published original opening, borrows the actual host, then attempts a real FileStream acquisition of that host's held node.owner.lock. The original IOException comes from that second acquisition; the storage opening itself must succeed.

The participant retains the actual opening, callback and refused constructor exception. Complete bounded canonical records, full identity and physical position are captured before and after the refusal under the actual storage read gate. Every byte is compared without exposing private identity or record values in diagnostics. Failed startup must contain the same original exception.

The trial joins actual node request work, observes the original WebApplication.StopAsync task, then observes the retained PartitionStorageLifecycle.StopAsync and physical-owner Closing tasks. The deliberately failed ApplicationServices callback leaves the silo in Starting, so hosted Stop refuses before its lifecycle drain. Only that exact outer stop refusal can be consumed after the full refusal and release proof. The two storage close tasks must succeed and retain their original task identities. Actual generic application disposal must also succeed. A separate exclusive owner-lock acquisition proves file release before a healthy application opens the same root. Unknown release or any independent cleanup failure retains the root and fails the case.

The healthy application submits ManagedCode commands for ConfigureResource and Batch through the actual coordinator. One literal document produces an independently specified complete ProcessDurable receipt with one persisted copy and empty private CompositionReferences. A real connection-grain CQRS minimum-token Document read returns the full literal document. Replay preserves the original complete receipt, prepared command and raw persisted StoredOutcome bytes without advancing either the canonical sequence or physical position. Two actual cold applications repeat the complete identity, receipt, outcome, minimum-read and release oracles on the same files.

sequenceDiagram
    participant GS as GrainService.Init
    participant Owner as Silo-local physical owner
    participant Trial as ApplicationServices participant
    participant App as Production WebApplication
    GS->>Owner: OpenAsync once
    Trial->>Owner: WaitForOpenAsync / retained Opening
    Trial->>Owner: Second node.owner.lock acquisition
    Owner-->>Trial: Original IOException
    Trial->>App: Original StopAsync and DisposeAsync
    App->>Owner: Join retained storage close tasks
    Trial->>Owner: Verify exclusive file release
    App->>Owner: Fresh same-root startup
    App->>Owner: Write / minimum read / replay
    App->>Owner: Two same-root cold continuations
Loading

The existing mandatory case is PartitionStorageTests.ActualStoragePublicationThenLockFailureJoinsAndSameRootsRetainCanonicalReceiptThroughTwoColdStarts. This source adaptation has not yet been compiled or run. The single-silo lifecycle and cold-file case does not qualify Aspire cluster operations, public .NET SDK/official MCP interoperability, abrupt process recovery, power loss or a storage-init failure after partial file acquisition. Those gates remain open. Existing configured startup timing, resource limits and cancellation are retained.

Original partial-stop error boundary

REQ-PHOST-PARTIAL-STOP-001 / AC-PHOST-PARTIAL-STOP-001: prove the actual callback and full Before/After cut before consuming an expected stop error. The original application Stop task must be faulted with at least one exact execution partial-stop leaf. Every consumed leaf must have exact System.InvalidOperationException type, the complete source-defined Starting-stop message and null InnerException. Aggregate wrappers are inspected without dropping empty aggregates. A different failure cannot be accepted through a substring, exception assignability or cancellation.

The original lower-close and owner Closing tasks must complete successfully. Repeated access must return those same retained tasks. Their errors cannot be consumed as the outer stop refusal. Actual CanReleaseRoot, joined request work, successful application disposal and the exclusive owner-lock probe prove release. This does not imply silo termination. If either refusal or release proof fails, original faults remain alongside proof and independent cleanup errors. The healthy continuation and both cold applications remain mandatory.

The source boundary is pinned Silo.StopAsync, SiloHostedService, and .NET 10.0.10 Host attempted-start/stop. The original task/error assertions define this case's required behavior; they are not evidence of a verified upstream defect or an executed runtime result.