Skip to content

Commit 3fa049c

Browse files
committed
fix race condition that allows duplicate slot
1 parent 6af1895 commit 3fa049c

File tree

1 file changed

+14
-15
lines changed

1 file changed

+14
-15
lines changed

apps/hermes/server/src/state/aggregate.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -351,28 +351,27 @@ where
351351
// Update the aggregate state
352352
let mut aggregate_state = self.into().data.write().await;
353353

354-
// Send update event to subscribers. We are purposefully ignoring the result
355-
// because there might be no subscribers.
356-
let _ = match aggregate_state.latest_completed_slot {
354+
// Atomic check and update
355+
let event = match aggregate_state.latest_completed_slot {
357356
None => {
358-
aggregate_state.latest_completed_slot.replace(slot);
359-
self.into()
360-
.api_update_tx
361-
.send(AggregationEvent::New { slot })
357+
aggregate_state.latest_completed_slot = Some(slot);
358+
AggregationEvent::New { slot }
362359
}
363360
Some(latest) if slot > latest => {
364361
self.prune_removed_keys(message_state_keys).await;
365-
aggregate_state.latest_completed_slot.replace(slot);
366-
self.into()
367-
.api_update_tx
368-
.send(AggregationEvent::New { slot })
362+
aggregate_state.latest_completed_slot = Some(slot);
363+
AggregationEvent::New { slot }
369364
}
370-
_ => self
371-
.into()
372-
.api_update_tx
373-
.send(AggregationEvent::OutOfOrder { slot }),
365+
Some(latest) if slot == latest => {
366+
// Don't send duplicate events for the same slot
367+
return Ok(());
368+
}
369+
_ => AggregationEvent::OutOfOrder { slot },
374370
};
375371

372+
// Only send the event after the state has been updated
373+
let _ = self.into().api_update_tx.send(event);
374+
376375
aggregate_state.latest_completed_slot = aggregate_state
377376
.latest_completed_slot
378377
.map(|latest| latest.max(slot))

0 commit comments

Comments
 (0)