refactor: replace string-based emitter with type-safe generic event system #28

Merged
mvhutz merged 2 commits from feat/better-emitter into main 2026-01-14 00:30:21 +00:00
Owner

Description

This PR refactors the event emitter system from a string-based message passing approach to a type-safe generic implementation using typed events.
The previous system relied on string message names which were error-prone and lacked compile-time safety.
This refactoring introduces a generic BaseEmitter[E comparable] that provides type safety while consolidating the various tracker packages into a unified plugins architecture.

Key changes:

  • Replace Emitter with generic BaseEmitter[E comparable] for type-safe event handling.
  • Add Event type enumeration with StartEvent, StepEvent, and StopEvent constants.
  • Create Listener[E] interface with BaseListener implementation for better abstraction.
  • Consolidate explanation, performance, and statistics packages into unified internal/plugins package.
  • Simplify CLI initialization by using plugin constructors that handle their own event subscriptions.
  • Add Items() iterator method to Set for idiomatic Go 1.23+ range loops over sets.

Decisions

Use generics for type-safe event handling.
This provides compile-time guarantees that event types match their handlers while maintaining flexibility for future event types.

Consolidate trackers into plugins architecture.
Previously separate packages (explanation, performance, statistics) now live under internal/plugins, making the plugin pattern explicit and easier to extend.

Plugin constructors self-register with engine.
Each plugin's New* constructor now handles its own event subscriptions, reducing boilerplate in the main CLI.

Benefits

Type safety prevents runtime errors from typos in event names.
The compiler now catches mismatched event types at compile time rather than failing silently at runtime.

Cleaner plugin architecture makes adding new features easier.
New plugins follow a consistent pattern and live in a single location.

Reduced boilerplate in main CLI.
Plugin initialization is now a single function call rather than manual event registration.

Better testability through interface-based design.
The Listener[E] interface allows for easier mocking and testing of event handlers.

Checklist

  • Code follows conventional commit format.
  • Branch follows naming convention (<type>/<description>).
  • Tests pass (if applicable).
  • Documentation updated (if applicable).
## Description This PR refactors the event emitter system from a string-based message passing approach to a type-safe generic implementation using typed events. The previous system relied on string message names which were error-prone and lacked compile-time safety. This refactoring introduces a generic `BaseEmitter[E comparable]` that provides type safety while consolidating the various tracker packages into a unified plugins architecture. Key changes: - Replace `Emitter` with generic `BaseEmitter[E comparable]` for type-safe event handling. - Add `Event` type enumeration with `StartEvent`, `StepEvent`, and `StopEvent` constants. - Create `Listener[E]` interface with `BaseListener` implementation for better abstraction. - Consolidate `explanation`, `performance`, and `statistics` packages into unified `internal/plugins` package. - Simplify CLI initialization by using plugin constructors that handle their own event subscriptions. - Add `Items()` iterator method to `Set` for idiomatic Go 1.23+ range loops over sets. ### Decisions Use generics for type-safe event handling. This provides compile-time guarantees that event types match their handlers while maintaining flexibility for future event types. Consolidate trackers into plugins architecture. Previously separate packages (`explanation`, `performance`, `statistics`) now live under `internal/plugins`, making the plugin pattern explicit and easier to extend. Plugin constructors self-register with engine. Each plugin's `New*` constructor now handles its own event subscriptions, reducing boilerplate in the main CLI. ## Benefits Type safety prevents runtime errors from typos in event names. The compiler now catches mismatched event types at compile time rather than failing silently at runtime. Cleaner plugin architecture makes adding new features easier. New plugins follow a consistent pattern and live in a single location. Reduced boilerplate in main CLI. Plugin initialization is now a single function call rather than manual event registration. Better testability through interface-based design. The `Listener[E]` interface allows for easier mocking and testing of event handlers. ## Checklist - [x] Code follows conventional commit format. - [x] Branch follows naming convention (`<type>/<description>`). - [x] Tests pass (if applicable). - [x] Documentation updated (if applicable).
mvhutz added 1 commit 2026-01-14 00:28:16 +00:00
Refactors the event emitter system from string-based messages to a
type-safe generic implementation using typed events. Consolidates
separate tracker packages into a unified plugins architecture.

Changes:
- Replace Emitter with BaseEmitter[E comparable] using generics
- Add Event type with StartEvent, StepEvent, and StopEvent constants
- Create Listener[E] interface with BaseListener implementation
- Consolidate explanation, performance, and statistics trackers into
  internal/plugins package
- Simplify main CLI by using plugin constructors instead of manual
  event subscription
- Add Items() iterator method to Set for idiomatic range loops
mvhutz added 1 commit 2026-01-14 00:29:10 +00:00
The Engine struct embeds BaseEmitter but wasn't initializing it,
causing a nil map panic when emitting events. Now properly
initializes the BaseEmitter using emitter.New[Event]().
mvhutz merged commit 307b7ffd1e into main 2026-01-14 00:30:21 +00:00
mvhutz deleted branch feat/better-emitter 2026-01-14 00:30:22 +00:00
Sign in to join this conversation.