Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ public Event processEvent(@NonNull final Event event) {
throw new IllegalArgumentException("Cannot evaluate null event.");
}

// If the initial rule set hasn't been received yet, cache the event for later processing
// once the rules are available
if (!initialRulesReceived && handleCaching(event)) {
return event;
}

final List<LaunchRule> matchedRules =
ruleRulesEngine.evaluate(new LaunchTokenFinder(event, extensionApi));

// if initial rule set has not been received, cache the event to be processed
// when rules are set
if (!initialRulesReceived) {
handleCaching(event);
}
return launchRulesConsequence.process(event, matchedRules);
}

Expand Down Expand Up @@ -152,15 +152,28 @@ private void reprocessCachedEvents() {
initialRulesReceived = true;
}

private void handleCaching(final Event event) {
/**
* Handles caching of events when the initial set of rules has not yet been received.
*
* <p>If the supplied event is a reset request for this LaunchRulesEngine, it will trigger
* processing of all cached events. Otherwise, the event is added to the cache to be processed
* later when rules are available.
*
* @param event the {@link Event} to be evaluated or cached
* @return {@code true} if the event was added to the cache, {@code false} if it triggered
* processing of cached events
*/
private boolean handleCaching(final Event event) {
// If this is an event to start processing of cachedEvents reprocess cached events
// otherwise, add the event to cachedEvents till rules are set
if (EventType.RULES_ENGINE.equals(event.getType())
&& EventSource.REQUEST_RESET.equals(event.getSource())
&& name.equals(DataReader.optString(event.getEventData(), RULES_ENGINE_NAME, ""))) {
reprocessCachedEvents();
return false;
} else {
cachedEvents.add(event);
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,70 @@ class LaunchRulesEngineModuleTests {
assertEquals(0, launchRulesEngine.cachedEventCount)
}

@Test
fun `Do not reprocess cached events multiple times`() {
val mockRulesEngine: RulesEngine<LaunchRule> = mock(RulesEngine::class.java) as RulesEngine<LaunchRule>
val mockLaunchRulesConsequence = mock(LaunchRulesConsequence::class.java)
val launchRulesEngine = LaunchRulesEngine(
"TestLaunchRulesEngine",
extensionApi,
mockRulesEngine,
mockLaunchRulesConsequence
)

// Dispatch events before replaceRules is called for the first time.
for (i in 0 until 5) {
launchRulesEngine.processEvent(
Event.Builder("event-$i", "type", "source").build()
)
}
assertEquals(5, launchRulesEngine.cachedEventCount)

Mockito.reset(mockLaunchRulesConsequence)

// Replace the rules
launchRulesEngine.replaceRules(listOf())

val resetEventCaptor: KArgumentCaptor<Event> = argumentCaptor()
verify(extensionApi, Mockito.times(1)).dispatch(resetEventCaptor.capture())
val capturedResetRulesEvent = resetEventCaptor.firstValue
assertNotNull(capturedResetRulesEvent)
assertEquals(EventType.RULES_ENGINE, capturedResetRulesEvent.type)
assertEquals(EventSource.REQUEST_RESET, capturedResetRulesEvent.source)
assertEquals(
"TestLaunchRulesEngine",
DataReader.optString(capturedResetRulesEvent.eventData, LaunchRulesEngine.RULES_ENGINE_NAME, "")
)

// Dispatch more events before RulesEngine:RequestReset event is processed by this rules engine
for (i in 5 until 10) {
launchRulesEngine.processEvent(
Event.Builder("event-$i", "type", "source").build()
)
}

assertEquals(10, launchRulesEngine.cachedEventCount)

// The rules engine receives RequestReset event
launchRulesEngine.processEvent(capturedResetRulesEvent)

// Verify cached events are only processed once
val processedEventCaptor: KArgumentCaptor<Event> = argumentCaptor()
verify(mockLaunchRulesConsequence, Mockito.times(11))
.process(processedEventCaptor.capture(), org.mockito.kotlin.any())
assertEquals(11, processedEventCaptor.allValues.size)

// 0 - 10 events to be processed are cached events in order
for (index in 0 until processedEventCaptor.allValues.size - 1) {
assertEquals("event-$index", processedEventCaptor.allValues[index].name)
}
// final 11 th event to be processed is the reset event
assertEquals(capturedResetRulesEvent, processedEventCaptor.allValues[10])

// verify that all cached events are cleared
assertEquals(0, launchRulesEngine.cachedEventCount)
}

@Test
fun `Test evaluateConsequence when consequences are present`() {
val json = readTestResources("rules_module_tests/rules_testEvaluateConsequenceWithValidConsequences.json")
Expand Down
Loading