package bus import ( "context" "testing" "time" "git.sendico.io/tech/sxchnge/notifications/model" "git.sendico.io/tech/sxchnge/shared/database/record" merrors "git.sendico.io/tech/sxchnge/shared/errors" "git.sendico.io/tech/sxchnge/shared/messaging/reliable" "go.mongodb.org/mongo-driver/v2/bson" ) type outbox struct{ jobs []model.Notification } func (o *outbox) Due(context.Context, time.Time) ([]model.Notification, error) { return o.jobs, nil } func (o *outbox) Recover(context.Context, time.Time) error { return nil } type publisher struct { reliable.Transport fail bool records []reliable.Record } func (p *publisher) Publish(_ context.Context, r reliable.Record) error { if p.fail { return merrors.ServiceUnavailable("offline") } p.records = append(p.records, r) return nil } func TestOutboxSurvivesPublishFailure(t *testing.T) { id := bson.NewObjectID() out := &outbox{jobs: []model.Notification{{Base: storable.Base{ID: id}, Email: model.Email{Address: "private@example.com", Text: "private"}}}} transport := &publisher{fail: true} b := &Bus{outbox: out, transport: transport} if err := b.PublishDue(context.Background()); err == nil { t.Fatal("publication failure hidden") } transport.fail = false if err := b.PublishDue(context.Background()); err != nil { t.Fatal(err) } if len(transport.records) != 1 || string(transport.records[0].Payload) != id.Hex() || transport.records[0].MessageID != id.Hex()+"-0" { t.Fatal(transport.records) } out.jobs[0].Attempts = 1 if err := b.PublishDue(context.Background()); err != nil { t.Fatal(err) } if transport.records[1].MessageID == transport.records[0].MessageID { t.Fatal("retry shares transport deduplication identity") } }