Skip to content

Use generics to deduplicate internal patterns#437

Open
klowdo wants to merge 2 commits intomainfrom
feat/generics
Open

Use generics to deduplicate internal patterns#437
klowdo wants to merge 2 commits intomainfrom
feat/generics

Conversation

@klowdo
Copy link
Copy Markdown
Collaborator

@klowdo klowdo commented Mar 3, 2026

Description

Use Go generics to deduplicate four near-identical internal patterns while keeping all public API signatures unchanged. Also adds generic registration alternatives for commands and event data.

Affected Components

  • Command registry
  • Event data registry
  • Aggregate registry
  • Snapshot registry
  • Middleware chaining
  • Context value extraction
  • Repo unwrapping (cache, version, tracing)

Related Issues

None

Solution and Design

  • A generic typeRegistry[K, F] replaces four copy-pasted mutex/map/panic registry implementations in command.go, event.go, aggregate.go, and snapshot.go.
  • A generic applyMiddleware[H, M] deduplicates UseCommandHandlerMiddleware and UseEventHandlerMiddleware.
  • A generic fromContext[T] simplifies context value extraction to one-liners.
  • A generic IntoRepo[T] eliminates recursive repo unwrapping duplication across repo/cache, repo/version, and tracing.
  • New RegisterCommandType[T]() and RegisterEventDataType[T](eventType) provide generic alternatives that eliminate factory closures:
    // Before:
    eh.RegisterCommand(func() eh.Command { return &Create{} })
    eh.RegisterEventData(MyEventType, func() eh.EventData { return &MyEventData{} })
    
    // After:
    eh.RegisterCommandType[Create]()
    eh.RegisterEventDataType[MyEventData](MyEventType)
    The existing factory-based functions remain unchanged for backward compatibility. Aggregates still require the factory approach due to UUID-dependent construction.

All internal changes are backward compatible. No exported type signatures changed.

Steps to test and verify

  1. go build ./... — all packages compile
  2. go vet ./... — no new issues
  3. go test ./... — all existing tests pass, new generic registration tests included

Closes #405

klowdo added 2 commits March 3, 2026 17:11
…nd repo patterns

Introduces a generic typeRegistry[K, F] to replace four near-identical
mutex/map/panic implementations across command, event, aggregate, and
snapshot registries. Also adds generic helpers for middleware chaining,
context value extraction, and recursive repo unwrapping. All public API
signatures remain unchanged.
Adds type-parameterized registration functions that eliminate factory
closures at call sites:

  eh.RegisterCommandType[MyCommand]()
  eh.RegisterEventDataType[MyEventData](MyEventType)

The existing factory-based RegisterCommand and RegisterEventData remain
unchanged for backward compatibility. Aggregates still require the
factory approach due to UUID-dependent construction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Generic Go 1.18 Support

2 participants