Skip to content

feat(hris): EmployeeOnboarded broadcast / fan-out (Phase 5b)#32

Closed
intech wants to merge 1 commit into
feat/hris-onboarding-sagafrom
feat/hris-onboarding-broadcast
Closed

feat(hris): EmployeeOnboarded broadcast / fan-out (Phase 5b)#32
intech wants to merge 1 commit into
feat/hris-onboarding-sagafrom
feat/hris-onboarding-broadcast

Conversation

@intech

@intech intech commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Draft — stacked on #31 (Phase 5a) and gated on the 1.1.0 release. Base is the Phase 5a branch, so this diff shows only the Phase 5b delta. Rebase onto main and retarget once #31 merges.

What

Adds the multi-subscriber face of the EventBus, completing the hris example's three-mechanism story (ctx.call · EventBus · Temporal saga). The onboarding saga's terminal step broadcasts EmployeeOnboarded ONCE, and three independent reactors consume it:

  • welcome — "sends" a welcome email
  • audit — appends an onboarding record (full message shape)
  • headcount — tallies per-department headcount
saga COMPLETES ─▶ announceOnboarded (publish ONCE) ─▶ EmployeeOnboarded
                                                         ├─▶ welcome    (group hris-welcome)
                                                         ├─▶ audit      (group hris-audit)
                                                         └─▶ headcount  (group hris-headcount)
  • publishes (1.1.0): the publish-only bus lists OnboardingEventHandlers in publishes, so the topic onboarding.employee-onboarded resolves from the proto option with no raw topic hand-passed (a route-less publisher otherwise falls back to the message typeName).
  • Fan-out is four buses, not one: each reactor runs on its own bus with a distinct consumer group (the per-bus duplicate-topic guard forces this), so on a broker every reactor gets every event. Reactors are idempotent (dedupe by employeeId — broker broadcast is at-least-once). Each runs as its own process (node src/reactor.ts, role by REACTOR).
  • Fire-and-forget: the broadcast runs outside the saga's compensation scope; a publish failure is logged, never rolled back — a lost broadcast must never undo a completed onboarding. The worker owns the publish-bus lifecycle and injects it via setPublisherBus.

Scope of verification (honest)

  • Verified dockerless against the 1.1.0-shape (pkg.pr.new @165): typecheck clean, 37/37 tests (was 33 in feat(hris): durable onboarding saga (Temporal) — Phase 5a #31). New/updated: the broadcast fan-out (one publish → three reactors with the full shape), topic-from-proto-option, idempotency, and a broadcast-failure-tolerance workflow test (a failed broadcast still resolves COMPLETED, no compensation).
  • The committed @connectum/* deps stay ^1.0.0 (no pkg.pr.new URLs); the verification override was local-only and is not in this diff.
  • docker-compose.yml (the three reactor services + worker NATS wiring) is config-validated, not run.
  • The existing LeaveApproved e2e is unchanged.

Gating

  1. feat(hris): durable onboarding saga (Temporal) — Phase 5a #31 (Phase 5a) must merge first (this stacks on it).
  2. 1.1.0 must publish — publishes / the broadcast wiring ship in 1.1.0; ^1.0.0 resolves it once on npm. This mirrors the car-sharing Phase 3 broadcast draft (feat(car-sharing): EventBus broadcast / fan-out on trip completion (Phase 3) #29).

🤖 Generated with Claude Code

https://claude.ai/code/session_01MdeH7fExPmiRHRirGuvGk3

Add the multi-subscriber face of the EventBus, completing the hris example's
three-mechanism story. The onboarding saga's terminal step now broadcasts
`EmployeeOnboarded` ONCE, and three INDEPENDENT reactors consume it — welcome
(welcome email), audit (onboarding record), headcount (per-department tally).

- The publish-only bus uses the 1.1.0 `publishes: [OnboardingEventHandlers]`
  option, so the topic `onboarding.employee-onboarded` is resolved from the proto
  option with no raw topic hand-passed (a route-less publisher otherwise falls
  back to the message typeName).
- Fan-out is four buses, not one: each reactor runs on its own bus with a
  DISTINCT consumer group (the per-bus duplicate-topic guard forces this), so on
  a broker every reactor gets every event. Reactors are idempotent (dedupe by
  employeeId — broker broadcast is at-least-once). Each runs as its own process
  (`node src/reactor.ts`, role by REACTOR), mirroring the RPC roles / worker.
- The broadcast is fire-and-forget: it runs OUTSIDE the saga's compensation
  scope and a publish failure is logged, never rolled back — a lost broadcast
  must never undo a completed onboarding. The worker owns the publish bus
  lifecycle and injects it into the activities via setPublisherBus.

Verified dockerless against the 1.1.0-shape (pkg.pr.new @165): typecheck clean,
37/37 tests — the broadcast fan-out (one publish → three reactors with the full
message shape), topic-from-proto-option, idempotency, and the new
broadcast-failure-tolerance workflow test. The LeaveApproved e2e is unchanged.

Requires @connectum/events >= 1.1.0 (publishes/broadcast); the committed ^1.0.0
range resolves 1.1.0 once published. DRAFT until 1.1.0 is on npm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MdeH7fExPmiRHRirGuvGk3
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f79ed594-900b-4387-8f51-23c997576539

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/hris-onboarding-broadcast

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the type:feature New feature or enhancement request label Jun 21, 2026
@intech intech deleted the branch feat/hris-onboarding-saga June 23, 2026 14:06
@intech intech closed this Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:feature New feature or enhancement request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant