Resolve concurrency with watcher trigger service (#39164)

The watcher trigger service could attempt to modify the perWatchStats
map simultaneously from multiple threads. This would cause the
internal state to become inconsistent, in particular the count()
method may return an incorrect value for the number of watches.

This changes replaces the implementation of the map with a
ConcurrentHashMap so that its internal state remains consistent even
when accessed from mutiple threads.

Backport of: #39092
This commit is contained in:
Tim Vernum 2019-02-20 19:18:00 +11:00 committed by GitHub
parent ec2b64af63
commit 4aa50ed348
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 4 additions and 2 deletions

View File

@ -19,6 +19,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
@ -29,7 +30,7 @@ public class TriggerService {
private final GroupedConsumer consumer = new GroupedConsumer();
private final Map<String, TriggerEngine> engines;
private final Map<String, TriggerWatchStats> perWatchStats = new HashMap<>();
private final Map<String, TriggerWatchStats> perWatchStats = new ConcurrentHashMap<>();
public TriggerService(Set<TriggerEngine> engines) {
Map<String, TriggerEngine> builder = new HashMap<>();

View File

@ -231,8 +231,10 @@ public class WatcherServiceTests extends ESTestCase {
Trigger trigger = mock(Trigger.class);
when(trigger.type()).thenReturn(engineType);
final String id = randomAlphaOfLengthBetween(3, 12);
Watch watch = mock(Watch.class);
when(watch.trigger()).thenReturn(trigger);
when(watch.id()).thenReturn(id);
when(watch.condition()).thenReturn(InternalAlwaysCondition.INSTANCE);
ExecutableNoneInput noneInput = new ExecutableNoneInput();
when(watch.input()).thenReturn(noneInput);

View File

@ -141,7 +141,6 @@ public class BootStrapTests extends AbstractWatcherIntegrationTestCase {
});
}
@AwaitsFix(bugUrl = "Supposedly fixed; https://github.com/elastic/x-pack-elasticsearch/issues/1915")
public void testLoadExistingWatchesUponStartup() throws Exception {
stopWatcher();