Skip to content

Commit 190f122

Browse files
authored
Merge pull request #115 from blehnen/phase-4-ci-wiring
shipyard: phase 4 — CI wiring for TaskScheduler integration tests
2 parents 8aeccf5 + b77b988 commit 190f122

185 files changed

Lines changed: 11873 additions & 2205 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.

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,6 @@ jobs:
6363

6464
- name: Unit Tests - Memory
6565
run: dotnet test "Source/DotNetWorkQueue.Transport.Memory.Tests/DotNetWorkQueue.Transport.Memory.Tests.csproj" --no-build -c Debug
66+
67+
- name: Integration Tests - TaskScheduler Distributed
68+
run: dotnet test "Source/DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler.Integration.Tests/DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler.Integration.Tests.csproj" --no-build -c Debug

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,3 +451,6 @@ codcov*.txt
451451
codecov*.txt
452452
NuGetScratchbrian/
453453
Deploy.bat
454+
455+
# Shipyard worktrees (isolated feature branches)
456+
.worktrees/

.shipyard/HISTORY.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,3 +759,37 @@
759759
- **Status:** Phase 5 COMPLETE. All 5 phases of the code-coverage milestone complete. Ready for `/shipyard:ship`.
760760

761761
- [2026-04-13T19:15:16Z] /shipyard:ship: PR #114 opened (https://github.com/blehnen/DotNetWorkQueue/pull/114). 7 commits pushed. Code-coverage milestone shipped. Awaiting review + merge.
762+
- [2026-04-14T14:39:19Z] Phase 1: Project definition and roadmap captured for TaskScheduler lock fix + integration tests (ready)
763+
- [2026-04-14T16:32:39Z] Phase 1: Planning phase 1: context captured, dispatching researcher (planning)
764+
- [2026-04-14T17:39:46Z] Phase 1: Phase 1 planned: 4 plans across 4 waves, ready for build (planned)
765+
- [2026-04-14T17:46:06Z] Phase 1: Building phase 1 wave 1 (PLAN-1.1 NetMQ probe + SetCountMsg) (building)
766+
- [2026-04-14T17:59:27Z] Phase 1: Wave 1 complete (PLAN-1.1 PASS); starting Wave 2 (PLAN-1.2 poller refactor) (building)
767+
- [2026-04-14T18:19:13Z] Phase 1: Wave 2 complete (_lockSocket removed); starting Wave 3 (PLAN-1.3 async Start/Dispose) (building)
768+
- [2026-04-14T18:29:38Z] Phase 1: Wave 3 complete (async Start + bounded Dispose); starting Wave 4 (PLAN-2.1 test suite) (building)
769+
- [2026-04-14T19:27:26Z] Phase 1: Phase 1 verification DONE; audit/simplifier/documenter running (building)
770+
- [2026-04-14T19:27:33Z] Session ended during build (may need /shipyard:resume)
771+
- [2026-04-14T19:28:35Z] Session ended during build (may need /shipyard:resume)
772+
- [2026-04-14T19:29:07Z] Session ended during build (may need /shipyard:resume)
773+
- [2026-04-14T20:00:26Z] Phase 1: Phase 1 build complete: all gates passed, ready for /shipyard:ship or Phase 2 planning (complete)
774+
- [2026-04-14T20:09:11Z] Phase 2: Planning phase 2: NuGet 0.4.0 release (planning)
775+
- [2026-04-14T20:35:36Z] Phase 2: Building phase 2 wave 1 (PLAN-1.1 pre-flight) (building)
776+
- [2026-04-14T21:50:02Z] Phase 2: Phase 2 complete: 0.4.0 shipped to nuget.org via tag v0.4.0 (complete)
777+
- [2026-04-14T22:20:34Z] Phase 3: Planning phase 3: DNQ integration test project (planning)
778+
- [2026-04-14T22:56:02Z] Phase 3: Phase 3 planned: 5 plans across 3 waves, ready for build (planned)
779+
- [2026-04-15T13:01:41Z] Phase 3: Building phase 3 (building)
780+
- [2026-04-15T13:44:01Z] Session ended during build (may need /shipyard:resume)
781+
- [2026-04-15T13:54:45Z] Session ended during build (may need /shipyard:resume)
782+
- [2026-04-15T13:57:34Z] Session ended during build (may need /shipyard:resume)
783+
- [2026-04-15T13:57:50Z] Session ended during build (may need /shipyard:resume)
784+
- [2026-04-15T14:07:06Z] Session ended during build (may need /shipyard:resume)
785+
- [2026-04-15T15:42:08Z] Phase 3: Phase 3 build complete (complete)
786+
- [2026-04-15T15:48:35Z] Phase 4: Planning phase 4 (planning)
787+
- [2026-04-15T16:17:34Z] Phase 4: Phase 4 planned: 2 plans in 1 wave, ready for build (planned)
788+
- [2026-04-15T16:38:52Z] Phase 4: Building phase 4 (in worktree) (building)
789+
- [2026-04-15T16:39:30Z] Phase 4: Building phase 4 (worktree phase-4-ci-wiring) (building)
790+
- [2026-04-15T16:39:42Z] Phase 4: Building phase 4 (worktree phase-4-ci-wiring) (building)
791+
- [2026-04-15T16:39:53Z] Phase 4: Building phase 4 (worktree phase-4-ci-wiring) (building)
792+
- [2026-04-15T16:40:15Z] Phase 4: Building phase 4 (building)
793+
- [2026-04-15T16:40:31Z] Phase 4: Building phase 4 (worktree phase-4-ci-wiring) (building)
794+
- [2026-04-15T16:52:50Z] Phase 4: Phase 4 build complete in worktree; pending CI validation on push (success criteria #1, #2) (complete)
795+
- [2026-04-15T16:53:01Z] Phase 4: Phase 4 build complete in worktree; pending CI validation on push (complete)

.shipyard/ISSUES.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,66 @@
22

33
## Open
44

5+
### ISSUE-030: README usage example uses wrong named argument `udpBroadcastPort:` instead of `broadCastPort:`
6+
- **Severity:** Low (documentation)
7+
- **Source:** Phase 3 (DNQ integration test project) — researcher investigation of 0.4.0 public API
8+
- **Repo:** DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler
9+
- **Status:** Open
10+
- **Files:**
11+
- `README.md` (sibling repo)
12+
- **Description:** The sibling repo's `README.md` shows a `InjectDistributedTaskScheduler` usage example that names the port argument `udpBroadcastPort:`. The actual public API parameter is named `broadCastPort`. Copy-pasting the README example verbatim produces a compile error (CS1739 — no such parameter). Not a runtime bug, but a trap for consumers following the documentation.
13+
- **Remediation:** Update the README install/usage example to use `broadCastPort:` (or drop the named argument and use positional). Land in a follow-up 0.4.1 doc-only release (or amend the README in trunk and mention it in the 0.5.0 changelog).
14+
- **Workaround in Phase 3:** DNQ integration tests pass positional arguments to sidestep the bug.
15+
16+
### ISSUE-029: GitHub Actions workflow uses deprecated Node.js 20 actions
17+
- **Severity:** Low (maintenance)
18+
- **Source:** Phase 2 (TaskScheduler 0.4.0 release) — surfaced during `gh run watch` on the v0.4.0 publish workflow
19+
- **Repo:** DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler
20+
- **Status:** Open
21+
- **Files:**
22+
- `.github/workflows/ci.yml`
23+
- **Description:** The sibling repo's CI workflow uses `actions/checkout@v4` and `actions/setup-dotnet@v4`, both of which run on Node.js 20. GitHub Actions is deprecating Node.js 20 on runners by September 2026 (forced to Node.js 24 by default on June 2, 2026). Non-blocking for 0.4.0 — the advisory was just a warning, the workflow ran green. But unless upgraded, these actions will stop working after the deprecation deadline.
24+
- **Remediation:** Upgrade to newer action versions that support Node.js 24. Check `actions/checkout@v5` / `actions/setup-dotnet@v5` (or whatever the current latest is at remediation time) and bump the workflow file. Verify a workflow run succeeds post-bump before shipping.
25+
- **Not urgent for 0.5.0** — just do it before 2026-06-02 to avoid forced-migration surprises.
26+
27+
### ISSUE-028: Add `<remarks>` XML doc on TaskSchedulerJobCountSync.Start() describing non-blocking semantics
28+
- **Severity:** Minor
29+
- **Source:** Phase 1 (TaskScheduler lock fix) — Documenter review
30+
- **Repo:** DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler
31+
- **Status:** CLOSED (landed in Phase 2 release commit `b904ac3` as part of the 0.4.0 release, 2026-04-14)
32+
- **Description:** After Phase 1 made `Start()` non-blocking (poller runs on a dedicated background thread), the method's XML `<summary>` still just says "Starts this instance". Library consumers who subclass `TaskSchedulerJobCountSync` or wrap `ITaskSchedulerJobCountSync` can't see the behavior change from IDE tooltips.
33+
- **Remediation:** Add a `<remarks>` block to the `Start()` XML doc on both `Source/ITaskSchedulerJobCountSync.cs` and `Source/TaskSchedulerJobCountSync.cs`, describing the synchronous-then-background-poller handoff. ~10 lines across both files.
34+
- **Why deferred from Phase 1:** The ROADMAP.md Phase 1 success criterion #2 requires `ITaskSchedulerJobCountSync.cs` to be byte-identical to master. Strictly interpreted, XML doc comments are part of the file bytes. Adding them would break the literal invariant. Phase 2 (0.4.0 release) can land the doc change alongside the CHANGELOG entry — they both document the same observable behavior change.
35+
36+
### ISSUE-027: Test helper DRY opportunity — XunitLogger / NextPort / BeaconInterface copied across 4 test files
37+
- **Severity:** Medium
38+
- **Source:** Phase 1 (TaskScheduler lock fix) — Simplifier review
39+
- **Repo:** DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler
40+
- **Status:** Open (deferred from Phase 1)
41+
- **Description:** `Source/DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler.Tests/` now has 4 test files (existing `TaskSchedulerJobCountSyncTests` + 3 new from PLAN-2.1) each with a verbatim copy of `private class XunitLogger : ILogger`, a per-file `_nextPort + NextPort()` counter, and a `BeaconInterface` static. About 80 LoC of pure copy-paste.
42+
- **Remediation:** Create `Source/DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler.Tests/NetMqTestSupport.cs` with an `internal sealed class XunitLogger`, an `internal static class TestPorts` with a decade-aware `Next()` that preserves disjoint seeds per caller, and an `internal static class BeaconInterfaces.Default`. Then delete the nested copies in each test file. Net delete ~60 LoC, effort ~20 minutes.
43+
- **Why deferred:** Phase 1 is a concurrency refactor; a test-helper consolidation is out of scope. Worth doing if Phase 2/3 adds more test files to this project.
44+
45+
### ISSUE-026: NetMqQueueApiProbeTests.cs is design-time scaffolding superseded by real handler tests
46+
- **Severity:** Low
47+
- **Source:** Phase 1 (TaskScheduler lock fix) — Simplifier review
48+
- **Repo:** DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler
49+
- **Status:** Open (deferred from Phase 1)
50+
- **Description:** `Source/DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler.Tests/NetMqQueueApiProbeTests.cs` (35 LoC) was created in PLAN-1.1 Task 1 to validate that `NetMQQueue<T>` + `NetMQPoller` + `ReceiveReady` actually compile and run against NetMQ 4.0.2.2. The real handler tests from PLAN-2.1 now exercise the same API paths, making the probe redundant.
51+
- **Remediation:** Delete `NetMqQueueApiProbeTests.cs` entirely. Preserves the probe's historical role via git history.
52+
- **Why deferred:** Low-value cleanup; the file doesn't cost anything at runtime and it documents the original concern.
53+
54+
### ISSUE-025: RunPoller start race on fast Start() → Dispose() cycles
55+
- **Severity:** Low (noisy, not functional)
56+
- **Source:** Phase 1 (TaskScheduler lock fix) — PLAN-1.3 code quality review
57+
- **Repo:** DotNetWorkQueue.TaskScheduling.Distributed.TaskScheduler
58+
- **Status:** Open (deferred from Phase 1)
59+
- **Files:**
60+
- `Source/TaskSchedulerJobCountSync.cs``RunPoller()` method
61+
- **Description:** If `Dispose()` fires between `_pollerThread.Start()` and the `_poller = new NetMQPoller { _actor, _outbound }` assignment inside `RunPoller`, `_poller?.Stop()` no-ops because `_poller` is still null. The poller thread then constructs and runs an orphan poller until the underlying `_actor` is disposed, causing an `ObjectDisposedException` that is caught by the `RunPoller` try/catch but produces a noisy error log on pathological Start→Dispose cycles. Functionally safe — logged and swallowed — but cosmetically ugly.
62+
- **Remediation:** Add a `volatile bool _disposing` flag set by `Dispose(bool)` before `_poller?.Stop()`. `RunPoller` early-returns if `_disposing` is true before constructing `_poller`.
63+
- **Why deferred:** Not a functional bug, only affects error logs in a niche race. Good to fix in a later hardening pass.
64+
565
### ISSUE-019: Missing SUMMARY-1.1.md artifact for Plan 1.1 (LiteDb history tests)
666
- **Severity:** Important
767
- **Source:** Plan 1.1 Review

0 commit comments

Comments
 (0)