@@ -50,6 +50,7 @@ type pendingMsg struct {
5050type divergenceEvent struct {
5151 channel string
5252 payload string
53+ pattern string // non-empty for PSUBSCRIBE/pmessage deliveries
5354 kind DivergenceKind
5455 isPattern bool // true if this originated from a PSUBSCRIBE
5556}
@@ -233,7 +234,7 @@ func (sp *shadowPubSub) matchSecondary(msg *redis.Message) {
233234 now := sp .nowFunc ()
234235 if entries , ok := sp .pending [key ]; ok && len (entries ) > 0 {
235236 oldest := entries [0 ]
236- if now .Sub (oldest .timestamp ) < sp .window {
237+ if now .Sub (oldest .timestamp ) <= sp .window {
237238 // Match found within window — remove the oldest pending primary message.
238239 if len (entries ) == 1 {
239240 delete (sp .pending , key )
@@ -308,7 +309,7 @@ func (sp *shadowPubSub) reconcilePrimaries(now time.Time, secBuf map[msgKey][]se
308309 if now .Sub (e .timestamp ) >= sp .window {
309310 // Primary has expired — report as divergence regardless of any buffered
310311 // secondaries. A late secondary must not suppress a window violation.
311- out = append (out , divergenceEvent {channel : e .channel , payload : e .payload , kind : DivDataMismatch , isPattern : e .pattern != "" })
312+ out = append (out , divergenceEvent {channel : e .channel , payload : e .payload , pattern : e . pattern , kind : DivDataMismatch , isPattern : e .pattern != "" })
312313 continue
313314 }
314315 if secs := secBuf [key ]; len (secs ) > 0 {
@@ -337,7 +338,7 @@ func sweepExpiredSecondaries(now time.Time, window time.Duration, secBuf map[msg
337338 var remaining []secondaryPending
338339 for _ , sec := range secs {
339340 if now .Sub (sec .timestamp ) >= window {
340- out = append (out , divergenceEvent {channel : sec .channel , payload : sec .payload , kind : DivExtraData , isPattern : key .Pattern != "" })
341+ out = append (out , divergenceEvent {channel : sec .channel , payload : sec .payload , pattern : key . Pattern , kind : DivExtraData , isPattern : key .Pattern != "" })
341342 } else {
342343 remaining = append (remaining , sec )
343344 }
@@ -362,6 +363,7 @@ func (sp *shadowPubSub) sweepAll() {
362363 divergences = append (divergences , divergenceEvent {
363364 channel : e .channel ,
364365 payload : e .payload ,
366+ pattern : e .pattern ,
365367 kind : DivDataMismatch ,
366368 isPattern : e .pattern != "" ,
367369 })
@@ -378,6 +380,7 @@ func (sp *shadowPubSub) sweepAll() {
378380 divergences = append (divergences , divergenceEvent {
379381 channel : sec .channel ,
380382 payload : sec .payload ,
383+ pattern : key .Pattern ,
381384 kind : DivExtraData ,
382385 isPattern : key .Pattern != "" ,
383386 })
@@ -395,11 +398,15 @@ func (sp *shadowPubSub) sweepAll() {
395398
396399func (sp * shadowPubSub ) reportDivergence (d divergenceEvent ) {
397400 sp .metrics .PubSubShadowDivergences .WithLabelValues (d .kind .String ()).Inc ()
398- sp . logger . Warn ( "pubsub shadow divergence" ,
401+ logAttrs := [] any {
399402 "channel" , truncateValue (d .channel ),
400403 "payload" , truncateValue (d .payload ),
401404 "kind" , d .kind .String (),
402- )
405+ }
406+ if d .pattern != "" {
407+ logAttrs = append (logAttrs , "pattern" , truncateValue (d .pattern ))
408+ }
409+ sp .logger .Warn ("pubsub shadow divergence" , logAttrs ... )
403410
404411 cmd := "SUBSCRIBE"
405412 if d .isPattern {
@@ -418,6 +425,7 @@ func (sp *shadowPubSub) reportDivergence(d divergenceEvent) {
418425 sp .sentry .CaptureDivergence (Divergence {
419426 Command : cmd ,
420427 Key : d .channel ,
428+ Pattern : d .pattern ,
421429 Kind : d .kind ,
422430 Primary : primary ,
423431 Secondary : secondary ,
0 commit comments