Implement HookEvent data model and LifecycleHooks registry with on/once/off/emit API #83
Labels
No labels
Blocked
Duplicate
MoSCoW/Could Have
MoSCoW/Must Have
MoSCoW/Should Have
Points/1
Points/13
Points/2
Points/21
Points/3
Points/5
Points/8
Priority/Backlog
Priority/Critical
Priority/High
Priority/Low
Priority/Medium
State/Completed
State/In progress
State/In review
State/Paused
State/Unverified
State/Verified
State/Wont Do
Type/Bug
Type/Epic
Type/Feature
Type/Legendary
Type/Task
Type/Testing
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
#82 Epic: Lifecycle Hook System
aethyr/Aethyr
Reference: aethyr/Aethyr#83
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Metadata
feat(lifecycle): add HookEvent and LifecycleHooks registryfeature/m1-lifecycle-hooksBackground and Context
The specification describes a
HookEventdata model carryingtype,source,data,and
cancelledfields, and aLifecycleHookssingleton registry withon,once,off, andemitmethods. This is the foundation for all lifecycle hook functionality.Expected Behavior
HookEventis an immutable data object withtype(Symbol),source(Object),data(Hash), andcancelled(Boolean) fieldsLifecycleHooks.on(hook_name, &block)registers a persistent callbackLifecycleHooks.once(hook_name, &block)registers a one-shot callbackLifecycleHooks.off(hook_name, &block)removes a callbackLifecycleHooks.emit(hook_name, source:, data: {})fires all registered callbacksAcceptance Criteria
HookEventclass inlib/aethyr/core/components/lifecycle/hook_event.rbLifecycleHooksmodule inlib/aethyr/core/components/lifecycle/lifecycle_hooks.rbon/once/off/emitmethods work correctlySubtasks
HookEventdata classLifecycleHooksregistry moduleon,once,off,emitmethodsDefinition of Done
This issue is complete when:
Commit Message in Metadata exactly.
master, reviewed, and merged.Implementation Notes
Design Decisions
HookEvent as frozen value object: The
HookEventclass freezes both itself and itsdatahash on initialization, ensuring immutability. This prevents handlers from accidentally mutating shared event state.LifecycleHooks as module with class-level methods: Using
class << selfon a module gives us singleton behavior without requiring explicit instantiation. Thereset!method supports test isolation.Mutex-based thread safety: All callback storage mutations are protected by a
Mutex. Theemitmethod takes a snapshot (.dup) of the callback list before iteration to avoid holding the lock during callback execution, which prevents deadlocks if a callback registers/removes other callbacks.Block-identity-based
off: Theoffmethod matches callbacks by block object identity (==), consistent with the issue requirements. Callers must retain a reference to the original block to remove it.Extracted private methods for Rubocop compliance: The
emitmethod was refactored to delegate argument validation (validate_emit_args!), callback dispatch (dispatch_callbacks), and one-shot cleanup (remove_once_entry) to private methods, satisfying Metrics/AbcSize and Metrics/MethodLength constraints.Files Created
lib/aethyr/core/components/lifecycle/hook_event.rblib/aethyr/core/components/lifecycle/lifecycle_hooks.rbtests/unit/lifecycle_hooks.featuretests/unit/step_definitions/lifecycle_hooks_steps.rb:symbolParameterTypeTest Results
Custom ParameterType
Added a
symbolParameterType to Cucumber for matching Ruby symbol literals (:on_boot,:on_tick, etc.) in Gherkin steps. This enables natural-language step definitions likeGiven a persistent callback is registered for the :on_boot hook.