Skip to content

Algoritma: Dedup & İdempotency

I₂ invariant'ı: Aynı messageId (veya idempotencyKey) ile gelen olay yalnızca bir kez işlenir.


Akış Şeması (Gateway)


Sıra Diyagramı


Pseudocode: Dedup Kontrolü

FUNCTION onPublish(ws, topic, messageId, payload):
  clientId = ws.userId
  key = "dedup:" + clientId

  IF stateStore.sismember(key, messageId) THEN
    RETURN { status: "duplicate" }   // İşleme, sadece ACK dönebilirsin
  END IF

  stateStore.sadd(key, messageId)
  stateStore.expire(key, DEDUP_TTL_SECONDS)   // Örn. 3600

  publishToBackbone(topic, { messageId, payload, seqNo: nextSeq(topic) })
  RETURN { status: "ok" }

Depolama Seçenekleri

YöntemAvantajDezavantaj
Redis SetHızlı, dağıtık, TTLRedis bağımlılığı
In-memory Map<clientId, Set<messageId>>Çok hızlıGateway restart'ta kayıp; tek gateway
DB tablo (processed_ids)KalıcıGecikme, yük

Fintech'te genelde Redis Set + TTL (örn. 1 saat) kullanılır; aynı messageId ile tekrar denemeler engellenir.


Node.js Örneği (Redis ile)

javascript
const redis = require('redis');
const client = redis.createClient({ url: process.env.REDIS_URL });

async function ensureDedup(clientId, messageId, ttlSeconds = 3600) {
  const key = `dedup:${clientId}`;
  const added = await client.sAdd(key, messageId);
  if (added === 0) return { duplicate: true }; // Zaten vardı
  await client.expire(key, ttlSeconds);
  return { duplicate: false };
}

// PUBLISH handler içinde:
const { duplicate } = await ensureDedup(ws.userId, msg.messageId);
if (duplicate) {
  ws.send(JSON.stringify({ type: 'ack', messageId: msg.messageId, status: 'duplicate' }));
  return;
}
// ... omurgaya yayınla ve ACK(ok) gönder

Tam gateway örneği: Gateway: ACL + Dedup.

Star the repo on GitHub if this documentation is useful — link in the navbar above.