80 lines
2.0 KiB
Go
80 lines
2.0 KiB
Go
// Package intentpubstub provides an in-process
|
|
// ports.IntentPublisher implementation for service-level tests. The
|
|
// stub records every Publish call and lets tests inject failures to
|
|
// verify that publication errors do not roll back already-committed
|
|
// business state.
|
|
package intentpubstub
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strconv"
|
|
"sync"
|
|
|
|
"galaxy/lobby/internal/ports"
|
|
"galaxy/notificationintent"
|
|
)
|
|
|
|
// Publisher is a concurrency-safe in-memory implementation of
|
|
// ports.IntentPublisher. The zero value is not usable; call NewPublisher
|
|
// to construct.
|
|
type Publisher struct {
|
|
mu sync.Mutex
|
|
published []notificationintent.Intent
|
|
nextID int
|
|
err error
|
|
}
|
|
|
|
// NewPublisher constructs an empty Publisher ready for use.
|
|
func NewPublisher() *Publisher {
|
|
return &Publisher{}
|
|
}
|
|
|
|
// SetError preloads err to be returned by every Publish call. Pass nil
|
|
// to reset.
|
|
func (publisher *Publisher) SetError(err error) {
|
|
if publisher == nil {
|
|
return
|
|
}
|
|
publisher.mu.Lock()
|
|
defer publisher.mu.Unlock()
|
|
publisher.err = err
|
|
}
|
|
|
|
// Publish records intent and returns a synthetic stream entry id.
|
|
func (publisher *Publisher) Publish(ctx context.Context, intent notificationintent.Intent) (string, error) {
|
|
if publisher == nil {
|
|
return "", errors.New("publish notification intent: nil publisher")
|
|
}
|
|
if ctx == nil {
|
|
return "", errors.New("publish notification intent: nil context")
|
|
}
|
|
|
|
publisher.mu.Lock()
|
|
defer publisher.mu.Unlock()
|
|
|
|
if publisher.err != nil {
|
|
return "", publisher.err
|
|
}
|
|
|
|
publisher.nextID++
|
|
publisher.published = append(publisher.published, intent)
|
|
return strconv.Itoa(publisher.nextID), nil
|
|
}
|
|
|
|
// Published returns a snapshot of every Publish-accepted intent in the
|
|
// order it was received.
|
|
func (publisher *Publisher) Published() []notificationintent.Intent {
|
|
if publisher == nil {
|
|
return nil
|
|
}
|
|
publisher.mu.Lock()
|
|
defer publisher.mu.Unlock()
|
|
out := make([]notificationintent.Intent, len(publisher.published))
|
|
copy(out, publisher.published)
|
|
return out
|
|
}
|
|
|
|
// Compile-time interface assertion.
|
|
var _ ports.IntentPublisher = (*Publisher)(nil)
|