Skip to content

refactor: extract shared helpers for duplication consolidation#686

Merged
Aaronontheweb merged 8 commits intodevfrom
feature/extract-shared-helpers
Apr 20, 2026
Merged

refactor: extract shared helpers for duplication consolidation#686
Aaronontheweb merged 8 commits intodevfrom
feature/extract-shared-helpers

Conversation

@Aaronontheweb
Copy link
Copy Markdown
Collaborator

Summary

New types

Type Assembly Purpose
SessionPipelineHandle Netclaw.Actors Composition helper for pipeline lifecycle (init/reinit/dispose) — replaces ~340 lines of copy-pasted code across 4 actors
ExecutionOutputAccumulator Netclaw.Actors Output buffering + notification tracking — replaces ~207 lines of identical code in Reminder/Webhook actors
OperationalAlert.Create() Netclaw.Configuration Factory method normalizing alert construction — will replace 16 call sites
IdGen Netclaw.Configuration Centralized ID generation with semantic method names
CrashLogHelper Netclaw.Cli Shared crash-log parsing for 2 doctor checks
DoctorJsonConfigReader.ReadBool/ReadStringArray Netclaw.Cli Shared JSON helpers for 4 doctor checks

Test infrastructure

  • ScriptedSessionPipeline and FailingSessionPipeline extracted to TestHelpers/ for reuse
  • 22 new unit tests covering all extracted helpers

Test plan

  • dotnet build — 0 warnings, 0 errors
  • dotnet test — all 2,482 tests pass (0 failures)
  • No existing tests modified or removed

…agnostics

Additive-only extraction of shared helpers to eliminate duplicated code across
pipeline actors, alert emission sites, and doctor checks. No existing behavior
changes — all helpers are new code with new tests.

New types:
- SessionPipelineHandle: composition helper for pipeline lifecycle (init, reinit, dispose)
- ExecutionOutputAccumulator: output buffering + notification tracking for execution actors
- OperationalAlert.Create(): factory method normalizing alert construction (replaces 16 sites)
- IdGen: centralized ID generation (AlertId, ShortId, Suffix, Full)
- CrashLogHelper: shared crash-log parsing for doctor checks
- DoctorJsonConfigReader.ReadBool/ReadStringArray: shared JSON helpers

Test infrastructure:
- ScriptedSessionPipeline and FailingSessionPipeline extracted to shared TestHelpers
- 22 new unit tests covering all extracted helpers

Refs #306
Replace 16 OperationalAlert constructions with OperationalAlert.Create(),
remove 4 duplicate ReadBool copies, 2 duplicate crash-log helpers,
and 7 Guid truncation sites with IdGen calls.

Net: -124 lines across 22 files.
…cutionOutputAccumulator

Replace duplicated pipeline lifecycle and output accumulation code across:
- WebhookExecutionActor (240→155 lines)
- ReminderExecutionActor (465→390 lines, Mode B path preserved)
- SignalRSessionActor (385→285 lines)
- SlackThreadBindingActor (1452→1350 lines)

Deleted: duplicated materializer/stream wiring, reinit logic, PostStop cleanup,
HandleOutput switch, TrackNotificationResult, BuildNotifyFailureMessage.

All 2,482 tests pass. Slopwatch clean.
@Aaronontheweb
Copy link
Copy Markdown
Collaborator Author

Updated: Full consolidation complete

This PR now includes the complete consolidation — helpers + wiring + deletion of all duplicated code.

Production code impact: -361 net lines (362 added, 723 removed in existing files)

4 pipeline actors rewired to SessionPipelineHandle:

  • WebhookExecutionActor 240→155 lines | ReminderExecutionActor 465→390 | SignalRSessionActor 385→285 | SlackThreadBindingActor 1452→1350

2 execution actors rewired to ExecutionOutputAccumulator — eliminated HandleOutput, TrackNotificationResult, BuildNotifyFailureMessage, 6 duplicated fields

16 alert construction sitesOperationalAlert.Create() (fixed BinaryUpdateCheckService AlertId bug)

6 doctor check files — removed 4 ReadBool copies, 2 crash-log helper copies

7 IdGen sitesGuid.NewGuid().ToString("N")[..N]IdGen.ShortId()/IdGen.Suffix()

Closes #306

Verification

  • dotnet build — 0 warnings, 0 errors
  • dotnet test — all 2,482 tests pass
  • dotnet slopwatch analyze — 0 issues
  • ✅ All 13 ReminderExecutionActorTests pass unchanged
  • ✅ 22 new unit tests for extracted helpers

- SessionPipelineHandle: store init params so ReinitializeAsync takes
  only (reason, onFailed) instead of 7 params. Drop IAsyncDisposable
  in favor of synchronous Dispose() since all callers are in PostStop.
- ExecutionOutputAccumulator: add optional notification tracking callback
  to restore lost diagnostic logging in ReminderExecutionActor.
- SlackThreadBindingActor: make _handle non-nullable (eager init in ctor).
- Delete trivial IdGenTests (violates CLAUDE.md testing guidelines).
Add AlertSeverity enum (Info, Warning, Critical) and change
OperationalAlert.Severity from string to AlertSeverity. Wire format
preserved via ToString().ToLowerInvariant() at the single serialization
point in WebhookNotificationService.
Comment thread src/Netclaw.Actors/Channels/ExecutionOutputAccumulator.cs Outdated
Replace hardcoded "send_slack_message" constant with a ToolName
constructor parameter. Callers supply the notification tool they
care about — the accumulator has no channel knowledge.
…rCorrelation tests

SlackActorHierarchyTests: raise TestKit default-timeout from 3s to 5s
to match the pattern already used by SlackProactiveThreadActorTests.
Under CI with parallel test classes, ThreadPool contention can delay
in-memory message delivery past the 3s default.

ErrorCorrelationTests: remove Task.Yield() from FailingChatClient so
the exception propagates synchronously. The yield deferred the exception
to the ThreadPool, making LlmCallFailed delivery timing dependent on
thread scheduling rather than deterministic actor mailbox ordering.
@Aaronontheweb Aaronontheweb merged commit 401f2d4 into dev Apr 20, 2026
4 checks passed
@Aaronontheweb Aaronontheweb deleted the feature/extract-shared-helpers branch April 20, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant