Skip to content

Fix dedup race condition for multi-replica safety #4

@dcadenas

Description

@dcadenas

Problem

The current dedup logic uses a two-step check-then-mark pattern (SISMEMBER then SADD) in redis_store.rs. With multiple replicas subscribing to the same relay, both can check before either marks, causing duplicate push notifications.

Fix

1. Atomic check-and-mark

Use SADD atomically as both check and mark — it returns 1 if newly added, 0 if existed:

// Instead of:
let exists = redis.sismember("PROCESSED_EVENTS_SET", event_id).await?;
if exists { return; }
redis.sadd("PROCESSED_EVENTS_SET", event_id).await?;

// Use:
let added = redis.sadd("PROCESSED_EVENTS_SET", event_id).await?;
if added == 0 { return; } // already processed

2. Per-event TTL

EXPIRE is currently set on the entire PROCESSED_EVENTS_SET, not per-event. Every new event resets the TTL for all events.

Consider using per-event keys with individual TTLs instead:

// Instead of a set with global TTL:
let added = redis.set_nx(format!("dedup:{}", event_id), "1").await?;
redis.expire(format!("dedup:{}", event_id), DEDUP_TTL).await?;

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions