Details
-
Bug
-
Resolution: Fixed
-
Major
-
13.7
-
Unknown
-
N/A
-
N/A
-
-
org.xwiki.notifications.notifiers.internal.email.live.PrefilteringLiveNotificationEmailDispatcherTest#addEvent
Description
Problem
PrefilteringLiveNotificationEmailDispatcherTest#addEvent still flickers on CI ( https://ci.xwiki.org/job/XWiki/job/xwiki-platform/job/master/8909/testReport/junit/org.xwiki.notifications.notifiers.internal.email.live/PrefilteringLiveNotificationEmailDispatcherTest/Platform_Builds___quality___Build_for_Quality_Step_1___addEvent/ ) , despite XWIKI-18982. Latest occurrence: build 8909 of the master Platform job.
Argument(s) are different! Wanted:
sender.sendMails(
{wiki:XWiki.user = [... with id id], wiki:XWiki.user2 = [... with id id]}
);
Actual invocations have different arguments:
sender.sendMails({wiki:XWiki.user = [... with id id]});
sender.sendMails({wiki:XWiki.user2 = [... with id id]});
Over the last ~6 months of master builds the test recorded 877 passes, 5 failures and 1 flaky run (~0.7% failure rate). All of those bad runs happened after XWIKI-18982 was closed, so that fix reduced but did not remove the race.
Cause
PrefilteringLiveNotificationEmailDispatcher.addEvent() schedules the dispatch with a delay expressed in seconds:
Instant instant = event.getDate().toInstant().plusMillis(this.grace); Duration duration = Duration.between(Instant.now(), instant); this.processingService.schedule(new ExecutionContextRunnable(this::dispatch, this.componentManager), duration.getSeconds(), TimeUnit.SECONDS);
The test forces grace = 100 (ms) so that it does not take a minute, which means duration.getSeconds() truncates to 0 and the dispatch task is runnable immediately. The test therefore relies on the test thread reaching the next addEvent() call before the scheduler thread picks up an already-runnable task – an unsynchronised race with no margin at all. Symptom: the whole test runs in under 0.5s locally, even though it nominally waits 100ms three times.
When the scheduler wins the race (a loaded CI agent), the queue entry for the first event has already been consumed by dispatch(), the following event can no longer be merged into it, and separate sendMails() calls are produced instead of the single grouped call the test expects.
Reproduced locally: with the machine loaded (3x the core count in busy loops), running the test 300 times fails 10 times with exactly the CI message. Unloaded, it always passes.
Fix
Make the test drive the scheduler instead of racing it: replace the dispatcher's processingService with a mock ScheduledExecutorService that captures the scheduled Runnable objects, and run them explicitly once all the events of a step have been added. This removes both the timeout(5000) waits and the resetDispatcher() workaround, and makes the test deterministic.
Validated at 300/300 passes under the same load that made the current test fail 10/300.
Attachments
Issue Links
- relates to
-
XWIKI-18982 PrefilteringLiveNotificationEmailDispatcherTest#addEvent is flickering
-
- Closed
-