Skip to content

Commit 4613eed

Browse files
authored
chore: Change the FutureEventBuffer to an internal data structure (#19060)
Signed-off-by: Kelly Greco <[email protected]>
1 parent 3647439 commit 4613eed

File tree

20 files changed

+603
-314
lines changed

20 files changed

+603
-314
lines changed

platform-sdk/consensus-event-creator-impl/src/main/java/org/hiero/consensus/event/creator/impl/DefaultEventCreationManager.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
import java.util.ArrayList;
1616
import java.util.List;
1717
import java.util.Objects;
18+
import org.hiero.consensus.config.EventConfig;
19+
import org.hiero.consensus.event.FutureEventBuffer;
1820
import org.hiero.consensus.event.creator.impl.config.EventCreationConfig;
1921
import org.hiero.consensus.event.creator.impl.pool.TransactionPoolNexus;
2022
import org.hiero.consensus.event.creator.impl.rules.AggregateEventCreationRules;
2123
import org.hiero.consensus.event.creator.impl.rules.EventCreationRule;
2224
import org.hiero.consensus.event.creator.impl.rules.MaximumRateRule;
2325
import org.hiero.consensus.event.creator.impl.rules.PlatformHealthRule;
2426
import org.hiero.consensus.event.creator.impl.rules.PlatformStatusRule;
27+
import org.hiero.consensus.model.event.AncientMode;
2528
import org.hiero.consensus.model.event.PlatformEvent;
2629
import org.hiero.consensus.model.hashgraph.EventWindow;
2730
import org.hiero.consensus.model.status.PlatformStatus;
@@ -56,6 +59,9 @@ public class DefaultEventCreationManager implements EventCreationManager {
5659
*/
5760
private Duration unhealthyDuration = Duration.ZERO;
5861

62+
private final AncientMode ancientMode;
63+
private final FutureEventBuffer futureEventBuffer;
64+
5965
/**
6066
* Constructor.
6167
*
@@ -77,7 +83,12 @@ public DefaultEventCreationManager(
7783
rules.add(new PlatformStatusRule(this::getPlatformStatus, transactionPoolNexus));
7884
rules.add(new PlatformHealthRule(config.maximumPermissibleUnhealthyDuration(), this::getUnhealthyDuration));
7985

80-
this.eventCreationRules = AggregateEventCreationRules.of(rules);
86+
ancientMode = platformContext
87+
.getConfiguration()
88+
.getConfigData(EventConfig.class)
89+
.getAncientMode();
90+
eventCreationRules = AggregateEventCreationRules.of(rules);
91+
futureEventBuffer = new FutureEventBuffer(platformContext.getConfiguration(), platformContext.getMetrics());
8192

8293
phase = new PhaseTimerBuilder<>(
8394
platformContext, platformContext.getTime(), "platform", EventCreationStatus.class)
@@ -113,12 +124,16 @@ public PlatformEvent maybeCreateEvent() {
113124

114125
return newEvent;
115126
}
127+
116128
/**
117129
* {@inheritDoc}
118130
*/
119131
@Override
120132
public void registerEvent(@NonNull final PlatformEvent event) {
121-
creator.registerEvent(event);
133+
final PlatformEvent nonFutureEvent = futureEventBuffer.addEvent(event);
134+
if (nonFutureEvent != null) {
135+
creator.registerEvent(event);
136+
}
122137
}
123138

124139
/**
@@ -127,6 +142,7 @@ public void registerEvent(@NonNull final PlatformEvent event) {
127142
@Override
128143
public void setEventWindow(@NonNull final EventWindow eventWindow) {
129144
creator.setEventWindow(eventWindow);
145+
futureEventBuffer.updateEventWindow(eventWindow).forEach(creator::registerEvent);
130146
}
131147

132148
/**
@@ -136,6 +152,9 @@ public void setEventWindow(@NonNull final EventWindow eventWindow) {
136152
public void clear() {
137153
creator.clear();
138154
phase.activatePhase(IDLE);
155+
futureEventBuffer.clear();
156+
final EventWindow eventWindow = EventWindow.getGenesisEventWindow(ancientMode);
157+
futureEventBuffer.updateEventWindow(eventWindow);
139158
}
140159

141160
/**

platform-sdk/consensus-event-creator-impl/src/main/java/org/hiero/consensus/event/creator/impl/tipset/TipsetEventCreator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ public TipsetEventCreator(
141141
zeroAdvancementWeightLogger = new RateLimitedLogger(logger, time, Duration.ofMinutes(1));
142142
noParentFoundLogger = new RateLimitedLogger(logger, time, Duration.ofMinutes(1));
143143

144-
this.eventWindow = EventWindow.getGenesisEventWindow(ancientMode);
145-
this.eventHasher = new PbjStreamHasher();
144+
eventWindow = EventWindow.getGenesisEventWindow(ancientMode);
145+
eventHasher = new PbjStreamHasher();
146146
}
147147

148148
/**

platform-sdk/consensus-event-creator-impl/src/test/java/org/hiero/consensus/event/creator/impl/EventCreationManagerTests.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static org.junit.jupiter.api.Assertions.assertNotNull;
55
import static org.junit.jupiter.api.Assertions.assertNull;
66
import static org.junit.jupiter.api.Assertions.assertSame;
7+
import static org.mockito.ArgumentMatchers.any;
78
import static org.mockito.Mockito.mock;
89
import static org.mockito.Mockito.times;
910
import static org.mockito.Mockito.verify;
@@ -16,7 +17,9 @@
1617
import java.time.Duration;
1718
import java.util.List;
1819
import org.hiero.consensus.event.creator.impl.pool.TransactionPoolNexus;
20+
import org.hiero.consensus.model.event.AncientMode;
1921
import org.hiero.consensus.model.event.PlatformEvent;
22+
import org.hiero.consensus.model.hashgraph.EventWindow;
2023
import org.hiero.consensus.model.status.PlatformStatus;
2124
import org.junit.jupiter.api.BeforeEach;
2225
import org.junit.jupiter.api.Test;
@@ -136,4 +139,83 @@ void unhealthyNodePreventsCreation() {
136139
verify(creator, times(2)).maybeCreateEvent();
137140
assertSame(eventsToCreate.get(1), e1);
138141
}
142+
143+
@Test
144+
void nonFutureEventsAreNotBuffered() {
145+
manager.setEventWindow(createEventWindow(1));
146+
final PlatformEvent e2 = eventWithBirthRound(2);
147+
manager.registerEvent(e2);
148+
verify(creator, times(1)).registerEvent(e2);
149+
150+
manager.setEventWindow(createEventWindow(2));
151+
final PlatformEvent e1 = eventWithBirthRound(1);
152+
final PlatformEvent e3 = eventWithBirthRound(3);
153+
manager.registerEvent(e1);
154+
manager.registerEvent(e3);
155+
verify(creator, times(1)).registerEvent(e1);
156+
verify(creator, times(1)).registerEvent(e3);
157+
}
158+
159+
@Test
160+
void futureEventsAreBuffered() {
161+
manager.setEventWindow(createEventWindow(1));
162+
163+
final PlatformEvent e3 = eventWithBirthRound(3);
164+
final PlatformEvent e4 = eventWithBirthRound(4);
165+
final PlatformEvent e5 = eventWithBirthRound(5);
166+
167+
// Future events should be buffered
168+
manager.registerEvent(e3);
169+
manager.registerEvent(e4);
170+
manager.registerEvent(e5);
171+
verify(creator, times(0)).registerEvent(any(PlatformEvent.class));
172+
173+
manager.setEventWindow(createEventWindow(2));
174+
verify(creator, times(1)).registerEvent(e3);
175+
176+
manager.setEventWindow(createEventWindow(3));
177+
verify(creator, times(1)).registerEvent(e4);
178+
179+
manager.setEventWindow(createEventWindow(4));
180+
verify(creator, times(1)).registerEvent(e5);
181+
}
182+
183+
@Test
184+
void ancientEventsAreIgnored() {
185+
manager.setEventWindow(createEventWindow(20, 10));
186+
manager.registerEvent(eventWithBirthRound(9));
187+
verify(creator, times(0)).registerEvent(any(PlatformEvent.class));
188+
}
189+
190+
@Test
191+
void testClear() {
192+
manager.setEventWindow(createEventWindow(1));
193+
194+
final PlatformEvent e3 = eventWithBirthRound(3);
195+
final PlatformEvent e4 = eventWithBirthRound(4);
196+
final PlatformEvent e5 = eventWithBirthRound(5);
197+
198+
// Future events should be buffered
199+
manager.registerEvent(e3);
200+
manager.registerEvent(e4);
201+
manager.registerEvent(e5);
202+
203+
manager.clear();
204+
manager.setEventWindow(createEventWindow(4));
205+
verify(creator, times(0)).registerEvent(any(PlatformEvent.class));
206+
}
207+
208+
private PlatformEvent eventWithBirthRound(final long birthRound) {
209+
final PlatformEvent mockEvent = mock(PlatformEvent.class);
210+
when(mockEvent.getBirthRound()).thenReturn(birthRound);
211+
return mockEvent;
212+
}
213+
214+
private EventWindow createEventWindow(final long latestConsensusRound) {
215+
return new EventWindow(latestConsensusRound, 1, 1, AncientMode.BIRTH_ROUND_THRESHOLD);
216+
}
217+
218+
private EventWindow createEventWindow(final long latestConsensusRound, final long ancientThreshold) {
219+
return new EventWindow(latestConsensusRound, ancientThreshold, 1, AncientMode.BIRTH_ROUND_THRESHOLD);
220+
}
139221
}

platform-sdk/consensus-event-creator-impl/src/test/java/org/hiero/consensus/event/creator/impl/tipset/TipsetEventCreatorTestUtils.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.swirlds.base.time.Time;
1919
import com.swirlds.common.context.PlatformContext;
2020
import com.swirlds.common.test.fixtures.platform.TestPlatformContextBuilder;
21+
import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder;
2122
import com.swirlds.platform.event.orphan.DefaultOrphanBuffer;
2223
import com.swirlds.platform.event.orphan.OrphanBuffer;
2324
import com.swirlds.platform.gossip.IntakeEventCounter;
@@ -38,6 +39,7 @@
3839
import org.hiero.consensus.model.event.EventDescriptorWrapper;
3940
import org.hiero.consensus.model.event.NonDeterministicGeneration;
4041
import org.hiero.consensus.model.event.PlatformEvent;
42+
import org.hiero.consensus.model.hashgraph.EventWindow;
4143
import org.hiero.consensus.model.node.NodeId;
4244
import org.hiero.consensus.model.test.fixtures.event.TestingEventBuilder;
4345
import org.hiero.consensus.model.transaction.TransactionWrapper;
@@ -54,10 +56,16 @@ public static EventCreator buildEventCreator(
5456
@NonNull final Time time,
5557
@NonNull final Roster roster,
5658
@NonNull final NodeId nodeId,
57-
@NonNull final TransactionSupplier transactionSupplier) {
59+
@NonNull final TransactionSupplier transactionSupplier,
60+
@NonNull final AncientMode ancientMode) {
5861

59-
final PlatformContext platformContext =
60-
TestPlatformContextBuilder.create().withTime(time).build();
62+
final PlatformContext platformContext = TestPlatformContextBuilder.create()
63+
.withTime(time)
64+
.withConfiguration(new TestConfigBuilder()
65+
.withValue(
66+
"event.useBirthRoundAncientThreshold", AncientMode.BIRTH_ROUND_THRESHOLD == ancientMode)
67+
.getOrCreateConfig())
68+
.build();
6169

6270
final HashSigner signer = mock(HashSigner.class);
6371
when(signer.sign(any())).thenAnswer(invocation -> randomSignature(random));
@@ -87,7 +95,12 @@ public static Map<NodeId, SimulatedNode> buildSimulatedNodes(
8795
for (final RosterEntry address : roster.rosterEntries()) {
8896

8997
final NodeId selfId = NodeId.of(address.nodeId());
90-
final EventCreator eventCreator = buildEventCreator(random, time, roster, selfId, transactionSupplier);
98+
final EventCreator eventCreator =
99+
buildEventCreator(random, time, roster, selfId, transactionSupplier, ancientMode);
100+
101+
// Set a wide event window so that no events get stuck in the Future Event Buffer
102+
eventCreator.setEventWindow(EventWindow.getGenesisEventWindow(ancientMode));
103+
91104
final TipsetTracker tipsetTracker = new TipsetTracker(time, selfId, roster, ancientMode);
92105

93106
final ChildlessEventTracker childlessEventTracker = new ChildlessEventTracker();
@@ -248,14 +261,15 @@ public static List<Bytes> generateRandomTransactions(@NonNull final Random rando
248261

249262
@NonNull
250263
public static PlatformEvent createTestEvent(
251-
@NonNull final Random random, @NonNull final NodeId creator, final long nGen) {
264+
@NonNull final Random random, @NonNull final NodeId creator, final long nGen, final long birthRound) {
252265

253266
final PlatformEvent selfParent =
254267
new TestingEventBuilder(random).setCreatorId(creator).build();
255268

256269
return new TestingEventBuilder(random)
257270
.setCreatorId(creator)
258271
.setNGen(nGen)
272+
.setBirthRound(birthRound)
259273
.setSelfParent(selfParent)
260274
.build();
261275
}

0 commit comments

Comments
 (0)