// Package userlifecyclestub provides an in-process // ports.UserLifecycleConsumer used by worker-level tests that do not // need a real Redis stream. Production code never wires this stub. package userlifecyclestub import ( "context" "errors" "sync" "galaxy/lobby/internal/ports" ) // Consumer is an in-memory ports.UserLifecycleConsumer. Tests publish // events synchronously through Deliver and observe handler errors via // the returned value. type Consumer struct { mu sync.Mutex handler ports.UserLifecycleHandler } // NewConsumer constructs an empty Consumer. func NewConsumer() *Consumer { return &Consumer{} } // OnEvent installs handler as the dispatch target. A second call // replaces the previous handler. func (consumer *Consumer) OnEvent(handler ports.UserLifecycleHandler) { if consumer == nil { return } consumer.mu.Lock() consumer.handler = handler consumer.mu.Unlock() } // Run blocks until ctx is cancelled. The stub does not pull events from // any backend; test code drives delivery via Deliver. func (consumer *Consumer) Run(ctx context.Context) error { if consumer == nil { return errors.New("run user lifecycle stub: nil consumer") } if ctx == nil { return errors.New("run user lifecycle stub: nil context") } <-ctx.Done() return ctx.Err() } // Shutdown is a no-op. func (consumer *Consumer) Shutdown(ctx context.Context) error { if ctx == nil { return errors.New("shutdown user lifecycle stub: nil context") } return nil } // Deliver dispatches event to the registered handler synchronously and // returns the handler's error. It is the test-only entry point used by // worker_test fixtures. func (consumer *Consumer) Deliver(ctx context.Context, event ports.UserLifecycleEvent) error { if consumer == nil { return errors.New("deliver user lifecycle stub: nil consumer") } if ctx == nil { return errors.New("deliver user lifecycle stub: nil context") } consumer.mu.Lock() handler := consumer.handler consumer.mu.Unlock() if handler == nil { return errors.New("deliver user lifecycle stub: no handler registered") } return handler(ctx, event) } // Compile-time assertion: Consumer satisfies the port interface. var _ ports.UserLifecycleConsumer = (*Consumer)(nil)