use of io.pravega.controller.eventProcessor.CheckpointConfig in project pravega by pravega.
the class EventProcessorTest method testEventProcessorCell.
@Test(timeout = 10000)
@SuppressWarnings("unchecked")
public void testEventProcessorCell() throws CheckpointStoreException, ReinitializationRequiredException {
CheckpointStore checkpointStore = CheckpointStoreFactory.createInMemoryStore();
CheckpointConfig.CheckpointPeriod period = CheckpointConfig.CheckpointPeriod.builder().numEvents(1).numSeconds(1).build();
CheckpointConfig checkpointConfig = CheckpointConfig.builder().type(CheckpointConfig.Type.Periodic).checkpointPeriod(period).build();
EventProcessorGroupConfig config = EventProcessorGroupConfigImpl.builder().eventProcessorCount(1).readerGroupName(READER_GROUP).streamName(STREAM_NAME).checkpointConfig(checkpointConfig).build();
int[] input = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int expectedSum = input.length * (input.length + 1) / 2;
List<MockEventRead<TestEvent>> inputEvents = new ArrayList<>(input.length);
for (int i = 0; i < input.length; i++) {
inputEvents.add(new MockEventRead<>(i, new TestEvent(input[i])));
}
inputEvents.add(new MockEventRead<>(input.length, new TestEvent(-1)));
EventProcessorSystem system = Mockito.mock(EventProcessorSystem.class);
Mockito.when(system.getProcess()).thenReturn(PROCESS);
EventStreamReader<TestEvent> reader = Mockito.mock(EventStreamReader.class);
checkpointStore.addReaderGroup(PROCESS, READER_GROUP);
// Test case 1. Actor does not throw any exception during normal operation.
Mockito.when(reader.readNextEvent(anyLong())).thenAnswer(new SequenceAnswer<>(inputEvents));
EventProcessorConfig<TestEvent> eventProcessorConfig = EventProcessorConfig.<TestEvent>builder().supplier(() -> new TestEventProcessor(false)).serializer(new EventSerializer<>()).decider((Throwable e) -> ExceptionHandler.Directive.Stop).config(config).build();
testEventProcessor(system, eventProcessorConfig, reader, READER_ID, checkpointStore, expectedSum);
// Test case 2. Actor throws an error during normal operation, and Directive is to Resume on error.
Mockito.when(reader.readNextEvent(anyLong())).thenAnswer(new SequenceAnswer<>(inputEvents));
eventProcessorConfig = EventProcessorConfig.<TestEvent>builder().supplier(() -> new TestEventProcessor(true)).serializer(new EventSerializer<>()).decider((Throwable e) -> (e instanceof IllegalArgumentException) ? ExceptionHandler.Directive.Resume : ExceptionHandler.Directive.Stop).config(config).build();
testEventProcessor(system, eventProcessorConfig, reader, READER_ID, checkpointStore, expectedSum);
// Test case 3. Actor throws an error during normal operation, and Directive is to Restart on error.
Mockito.when(reader.readNextEvent(anyLong())).thenAnswer(new SequenceAnswer<>(inputEvents));
eventProcessorConfig = EventProcessorConfig.<TestEvent>builder().supplier(() -> new TestEventProcessor(true)).serializer(new EventSerializer<>()).decider((Throwable e) -> (e instanceof IllegalArgumentException) ? ExceptionHandler.Directive.Restart : ExceptionHandler.Directive.Stop).config(config).build();
testEventProcessor(system, eventProcessorConfig, reader, READER_ID, checkpointStore, 0);
// Test case 3. Actor throws an error during normal operation, and Directive is to Restart on error.
Mockito.when(reader.readNextEvent(anyLong())).thenAnswer(new SequenceAnswer<>(inputEvents));
eventProcessorConfig = EventProcessorConfig.<TestEvent>builder().supplier(() -> new RestartFailingEventProcessor(true)).serializer(new EventSerializer<>()).decider((Throwable e) -> (e instanceof IllegalArgumentException) ? ExceptionHandler.Directive.Restart : ExceptionHandler.Directive.Stop).config(config).build();
testEventProcessor(system, eventProcessorConfig, reader, READER_ID, checkpointStore, 3);
// Test case 5. startup fails for an event processor
eventProcessorConfig = EventProcessorConfig.<TestEvent>builder().supplier(StartFailingEventProcessor::new).serializer(new EventSerializer<>()).decider((Throwable e) -> ExceptionHandler.Directive.Stop).config(config).build();
checkpointStore.addReader(PROCESS, READER_GROUP, READER_ID);
EventProcessorCell<TestEvent> cell = new EventProcessorCell<>(eventProcessorConfig, reader, new EventStreamWriterMock<>(), system.getProcess(), READER_ID, 0, checkpointStore);
cell.startAsync();
cell.awaitTerminated();
checkpointStore.removeReader(PROCESS, READER_GROUP, READER_ID);
// Test case 6. Close event processor cell when reader/checkpoint store throw exceptions.
Mockito.doThrow(new IllegalArgumentException("Failing reader")).when(reader).closeAt(any());
checkpointStore = spy(checkpointStore);
Mockito.doThrow(new IllegalArgumentException("Failing checkpointStore")).when(checkpointStore).removeReader(anyString(), anyString(), anyString());
eventProcessorConfig = EventProcessorConfig.<TestEvent>builder().supplier(StartFailingEventProcessor::new).serializer(new EventSerializer<>()).decider((Throwable e) -> ExceptionHandler.Directive.Stop).config(config).build();
checkpointStore.addReader(PROCESS, READER_GROUP, READER_ID);
cell = new EventProcessorCell<>(eventProcessorConfig, reader, new EventStreamWriterMock<>(), system.getProcess(), READER_ID, 0, checkpointStore);
cell.startAsync();
cell.awaitTerminated();
}
use of io.pravega.controller.eventProcessor.CheckpointConfig in project pravega by pravega.
the class EventProcessorTest method testEventProcessorFailover.
@Test(timeout = 60000)
public void testEventProcessorFailover() throws Exception {
final String scope = "controllerScope2";
final String streamName = "stream2";
final String readerGroup = "readerGroup2";
@Cleanup ConnectionFactory connectionFactory = new SocketConnectionFactoryImpl(ClientConfig.builder().build());
controller.createScope(scope).join();
final StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).build();
controller.createStream(scope, streamName, config).join();
eventSerializer = new EventSerializer<>(new TestSerializer());
@Cleanup ClientFactoryImpl clientFactory = new ClientFactoryImpl(scope, controller, connectionFactory);
@Cleanup EventStreamWriter<TestEvent> producer = clientFactory.createEventWriter(streamName, eventSerializer, EventWriterConfig.builder().build());
TestEvent event1 = new TestEvent(0);
producer.writeEvent("key", event1).join();
TestEvent event2 = new TestEvent(1);
producer.writeEvent("key", event2).join();
producer.flush();
EventProcessorSystem system = new EventProcessorSystemImpl("Controller", host, scope, clientFactory, new ReaderGroupManagerImpl(scope, controller, clientFactory));
CheckpointConfig checkpointConfig = CheckpointConfig.builder().type(CheckpointConfig.Type.None).build();
EventProcessorGroupConfig eventProcessorGroupConfig = EventProcessorGroupConfigImpl.builder().eventProcessorCount(1).readerGroupName(readerGroup).streamName(streamName).checkpointConfig(checkpointConfig).build();
LinkedBlockingQueue<TestEvent> eventsProcessed = new LinkedBlockingQueue<>();
EventProcessorConfig<TestEvent> eventProcessorConfig = EventProcessorConfig.<TestEvent>builder().supplier(() -> new EventProcessor<TestEvent>() {
@Override
protected void process(TestEvent event, Position position) {
try {
eventsProcessed.offer(event);
// keep sending null position
getCheckpointer().store(null);
} catch (CheckpointStoreException e) {
e.printStackTrace();
}
}
}).serializer(eventSerializer).decider((Throwable e) -> ExceptionHandler.Directive.Stop).config(eventProcessorGroupConfig).build();
@Cleanup EventProcessorGroup<TestEvent> eventProcessorGroup = system.createEventProcessorGroup(eventProcessorConfig, CheckpointStoreFactory.createInMemoryStore(), executorService());
eventProcessorGroup.awaitRunning();
// wait until both events are read
assertEquals(event1, eventsProcessed.take());
assertEquals(event2, eventsProcessed.take());
assertTrue(eventsProcessed.isEmpty());
// shutdown event processor
// upon shutdown readerGroup.offline and reader.close should have been called.
eventProcessorGroup.stopAsync();
eventProcessorGroup.awaitTerminated();
@Cleanup ConnectionFactory connectionFactory2 = new SocketConnectionFactoryImpl(ClientConfig.builder().build());
@Cleanup ClientFactoryImpl clientFactory2 = new ClientFactoryImpl(scope, controller, connectionFactory2);
system = new EventProcessorSystemImpl("Controller2", host, scope, clientFactory2, new ReaderGroupManagerImpl(scope, controller, clientFactory2));
EventProcessorConfig<TestEvent> eventProcessorConfig2 = EventProcessorConfig.<TestEvent>builder().supplier(() -> new EventProcessor<TestEvent>() {
@Override
protected void process(TestEvent event, Position position) {
try {
eventsProcessed.offer(event);
getCheckpointer().store(null);
} catch (CheckpointStoreException e) {
e.printStackTrace();
}
}
}).serializer(eventSerializer).decider((Throwable e) -> ExceptionHandler.Directive.Stop).config(eventProcessorGroupConfig).build();
@Cleanup EventProcessorGroup<TestEvent> eventProcessorGroup2 = system.createEventProcessorGroup(eventProcessorConfig2, CheckpointStoreFactory.createInMemoryStore(), executorService());
eventProcessorGroup2.awaitRunning();
// verify that both events are read again
assertEquals(event1, eventsProcessed.take());
assertEquals(event2, eventsProcessed.take());
assertTrue(eventsProcessed.isEmpty());
eventProcessorGroup2.stopAsync();
eventProcessorGroup2.awaitTerminated();
}
use of io.pravega.controller.eventProcessor.CheckpointConfig in project pravega by pravega.
the class EventProcessorTest method testEventProcessorRebalance.
@Test(timeout = 60000)
public void testEventProcessorRebalance() throws Exception {
final String scope = "scope";
final String streamName = "stream";
final String readerGroupName = "readerGroup";
controller.createScope(scope).join();
final StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(4)).build();
controller.createStream(scope, streamName, config).join();
eventSerializer = new EventSerializer<>(new TestSerializer());
@Cleanup ConnectionFactory connectionFactory = new SocketConnectionFactoryImpl(ClientConfig.builder().build());
@Cleanup ClientFactoryImpl clientFactory = new ClientFactoryImpl(scope, controller, connectionFactory);
CheckpointConfig.CheckpointPeriod period = CheckpointConfig.CheckpointPeriod.builder().numEvents(1).numSeconds(1).build();
CheckpointConfig checkpointConfig = CheckpointConfig.builder().type(CheckpointConfig.Type.Periodic).checkpointPeriod(period).build();
EventProcessorGroupConfig eventProcessorGroupConfig = EventProcessorGroupConfigImpl.builder().eventProcessorCount(1).readerGroupName(readerGroupName).streamName(streamName).checkpointConfig(checkpointConfig).build();
LinkedBlockingQueue<Integer> queue1 = new LinkedBlockingQueue<>();
EventProcessorConfig<TestEvent> eventProcessorConfig1 = EventProcessorConfig.<TestEvent>builder().supplier(() -> new TestEventProcessor2(queue1)).serializer(eventSerializer).decider((Throwable e) -> ExceptionHandler.Directive.Stop).config(eventProcessorGroupConfig).minRebalanceIntervalMillis(Duration.ofMillis(100).toMillis()).build();
// create a group and verify that all events can be written and read by readers in this group.
EventProcessorSystem system1 = new EventProcessorSystemImpl("Controller", "process1", scope, clientFactory, new ReaderGroupManagerImpl(scope, controller, clientFactory));
@Cleanup EventProcessorGroup<TestEvent> eventProcessorGroup1 = system1.createEventProcessorGroup(eventProcessorConfig1, CheckpointStoreFactory.createInMemoryStore(), executorService());
eventProcessorGroup1.awaitRunning();
log.info("first event processor started");
@Cleanup EventStreamWriter<TestEvent> writer = clientFactory.createEventWriter(streamName, eventSerializer, EventWriterConfig.builder().build());
// write 10 events and read them back from the queue passed to first event processor's
List<Integer> input = IntStream.range(0, 10).boxed().collect(Collectors.toList());
ConcurrentSkipListSet<Integer> output = new ConcurrentSkipListSet<>();
for (int val : input) {
writer.writeEvent(new TestEvent(val));
}
writer.flush();
// now wait until all the entries are read back.
for (int i = 0; i < 10; i++) {
// read 10 events back
Integer entry = queue1.take();
output.add(entry);
}
assertEquals(10, output.size());
log.info("first event processor read all the messages");
LinkedBlockingQueue<Integer> queue2 = new LinkedBlockingQueue<>();
EventProcessorConfig<TestEvent> eventProcessorConfig2 = EventProcessorConfig.<TestEvent>builder().supplier(() -> new TestEventProcessor2(queue2)).serializer(eventSerializer).decider((Throwable e) -> ExceptionHandler.Directive.Stop).config(eventProcessorGroupConfig).minRebalanceIntervalMillis(Duration.ofMillis(100).toMillis()).build();
// add another system and event processor group (effectively add a new set of readers to the readergroup)
EventProcessorSystem system2 = new EventProcessorSystemImpl("Controller", "process2", scope, clientFactory, new ReaderGroupManagerImpl(scope, controller, clientFactory));
@Cleanup EventProcessorGroup<TestEvent> eventProcessorGroup2 = system2.createEventProcessorGroup(eventProcessorConfig2, CheckpointStoreFactory.createInMemoryStore(), executorService());
eventProcessorGroup2.awaitRunning();
log.info("second event processor started");
AtomicInteger queue1EntriesFound = new AtomicInteger(0);
AtomicInteger queue2EntriesFound = new AtomicInteger(0);
ConcurrentSkipListSet<Integer> output2 = new ConcurrentSkipListSet<>();
// wait until rebalance may have happened.
@Cleanup ReaderGroupManager groupManager = new ReaderGroupManagerImpl(scope, controller, clientFactory);
ReaderGroup readerGroup = groupManager.getReaderGroup(readerGroupName);
AtomicBoolean allAssigned = new AtomicBoolean(false);
Futures.loop(() -> !allAssigned.get(), () -> Futures.delayedFuture(Duration.ofMillis(100), executorService()).thenAccept(v -> {
ReaderSegmentDistribution distribution = readerGroup.getReaderSegmentDistribution();
int numberOfReaders = distribution.getReaderSegmentDistribution().size();
allAssigned.set(numberOfReaders == 2 && distribution.getReaderSegmentDistribution().values().stream().noneMatch(x -> x == 0));
}), executorService()).join();
// write 10 new events
for (int val : input) {
writer.writeEvent(new TestEvent(val));
}
writer.flush();
// wait until at least one event is read from queue2
CompletableFuture.allOf(CompletableFuture.runAsync(() -> {
while (output2.size() < 10) {
Integer entry = queue1.poll();
if (entry != null) {
log.info("entry read from queue 1: {}", entry);
queue1EntriesFound.incrementAndGet();
output2.add(entry);
} else {
Exceptions.handleInterrupted(() -> Thread.sleep(100));
}
}
}), CompletableFuture.runAsync(() -> {
while (output2.size() < 10) {
Integer entry = queue2.poll();
if (entry != null) {
log.info("entry read from queue 2: {}", entry);
queue2EntriesFound.incrementAndGet();
output2.add(entry);
} else {
Exceptions.handleInterrupted(() -> Thread.sleep(100));
}
}
})).join();
assertTrue(queue1EntriesFound.get() > 0);
assertTrue(queue2EntriesFound.get() > 0);
assertEquals(10, output2.size());
}
use of io.pravega.controller.eventProcessor.CheckpointConfig in project pravega by pravega.
the class EventProcessorTest method testEventProcessor.
@Test(timeout = 60000)
public void testEventProcessor() throws Exception {
final String scope = "controllerScope";
final String streamName = "stream1";
final String readerGroup = "readerGroup";
controller.createScope(scope).join();
final StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).build();
controller.createStream(scope, streamName, config).join();
eventSerializer = new EventSerializer<>(new TestSerializer());
@Cleanup ConnectionFactory connectionFactory = new SocketConnectionFactoryImpl(ClientConfig.builder().build());
@Cleanup ClientFactoryImpl clientFactory = new ClientFactoryImpl(scope, controller, connectionFactory);
@Cleanup EventStreamWriter<TestEvent> producer = clientFactory.createEventWriter(streamName, eventSerializer, EventWriterConfig.builder().build());
int[] input = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int expectedSum = input.length * (input.length + 1) / 2;
for (int i = 0; i < input.length; i++) {
producer.writeEvent("key", new TestEvent(input[i]));
}
producer.writeEvent("key", new TestEvent(-1));
producer.flush();
EventProcessorSystem system = new EventProcessorSystemImpl("Controller", host, scope, clientFactory, new ReaderGroupManagerImpl(scope, controller, clientFactory));
CheckpointConfig.CheckpointPeriod period = CheckpointConfig.CheckpointPeriod.builder().numEvents(1).numSeconds(1).build();
CheckpointConfig checkpointConfig = CheckpointConfig.builder().type(CheckpointConfig.Type.Periodic).checkpointPeriod(period).build();
EventProcessorGroupConfig eventProcessorGroupConfig = EventProcessorGroupConfigImpl.builder().eventProcessorCount(1).readerGroupName(readerGroup).streamName(streamName).checkpointConfig(checkpointConfig).build();
CompletableFuture<Long> result = new CompletableFuture<>();
// Test case 1. Actor does not throw any exception during normal operation.
EventProcessorConfig<TestEvent> eventProcessorConfig = EventProcessorConfig.<TestEvent>builder().supplier(() -> new TestEventProcessor(false, result)).serializer(eventSerializer).decider((Throwable e) -> ExceptionHandler.Directive.Stop).config(eventProcessorGroupConfig).build();
@Cleanup EventProcessorGroup<TestEvent> eventProcessorGroup = system.createEventProcessorGroup(eventProcessorConfig, CheckpointStoreFactory.createInMemoryStore(), executorService());
Long value = result.join();
Assert.assertEquals(expectedSum, value.longValue());
log.info("SUCCESS: received expected sum = " + expectedSum);
}
use of io.pravega.controller.eventProcessor.CheckpointConfig in project pravega by pravega.
the class ControllerEventProcessors method initialize.
private void initialize() {
// region Create commit event processor
EventProcessorGroupConfig commitReadersConfig = EventProcessorGroupConfigImpl.builder().streamName(config.getCommitStreamName()).readerGroupName(config.getCommitReaderGroupName()).eventProcessorCount(config.getCommitReaderGroupSize()).checkpointConfig(CheckpointConfig.none()).build();
EventProcessorConfig<CommitEvent> commitConfig = EventProcessorConfig.<CommitEvent>builder().config(commitReadersConfig).decider(ExceptionHandler.DEFAULT_EXCEPTION_HANDLER).serializer(COMMIT_EVENT_SERIALIZER).supplier(() -> new ConcurrentEventProcessor<>(commitRequestHandler, executor)).minRebalanceIntervalMillis(rebalanceIntervalMillis).build();
log.debug("Creating commit event processors");
Retry.indefinitelyWithExpBackoff(DELAY, MULTIPLIER, MAX_DELAY, e -> log.warn("Error creating commit event processor group", e)).run(() -> {
commitEventProcessors = system.createEventProcessorGroup(commitConfig, checkpointStore, rebalanceExecutor);
return null;
});
// endregion
// region Create abort event processor
EventProcessorGroupConfig abortReadersConfig = EventProcessorGroupConfigImpl.builder().streamName(config.getAbortStreamName()).readerGroupName(config.getAbortReaderGroupName()).eventProcessorCount(config.getAbortReaderGroupSize()).checkpointConfig(CheckpointConfig.none()).build();
EventProcessorConfig<AbortEvent> abortConfig = EventProcessorConfig.<AbortEvent>builder().config(abortReadersConfig).decider(ExceptionHandler.DEFAULT_EXCEPTION_HANDLER).serializer(ABORT_EVENT_SERIALIZER).supplier(() -> new ConcurrentEventProcessor<>(abortRequestHandler, executor)).minRebalanceIntervalMillis(rebalanceIntervalMillis).build();
log.debug("Creating abort event processors");
Retry.indefinitelyWithExpBackoff(DELAY, MULTIPLIER, MAX_DELAY, e -> log.warn("Error creating commit event processor group", e)).run(() -> {
abortEventProcessors = system.createEventProcessorGroup(abortConfig, checkpointStore, rebalanceExecutor);
return null;
});
// endregion
// region Create request event processor
EventProcessorGroupConfig requestReadersConfig = EventProcessorGroupConfigImpl.builder().streamName(config.getRequestStreamName()).readerGroupName(config.getRequestReaderGroupName()).eventProcessorCount(1).checkpointConfig(CheckpointConfig.none()).build();
EventProcessorConfig<ControllerEvent> requestConfig = EventProcessorConfig.builder().config(requestReadersConfig).decider(ExceptionHandler.DEFAULT_EXCEPTION_HANDLER).serializer(CONTROLLER_EVENT_SERIALIZER).supplier(() -> new ConcurrentEventProcessor<>(streamRequestHandler, executor)).minRebalanceIntervalMillis(rebalanceIntervalMillis).build();
log.debug("Creating stream request event processors");
Retry.indefinitelyWithExpBackoff(DELAY, MULTIPLIER, MAX_DELAY, e -> log.warn("Error creating request event processor group", e)).run(() -> {
requestEventProcessors = system.createEventProcessorGroup(requestConfig, checkpointStore, rebalanceExecutor);
return null;
});
// endregion
// region Create KVtable event processor
EventProcessorGroupConfig kvtReadersConfig = EventProcessorGroupConfigImpl.builder().streamName(config.getKvtStreamName()).readerGroupName(config.getKvtReaderGroupName()).eventProcessorCount(1).checkpointConfig(CheckpointConfig.none()).build();
EventProcessorConfig<ControllerEvent> kvtRequestConfig = EventProcessorConfig.builder().config(kvtReadersConfig).decider(ExceptionHandler.DEFAULT_EXCEPTION_HANDLER).serializer(CONTROLLER_EVENT_SERIALIZER).supplier(() -> new ConcurrentEventProcessor<>(kvtRequestHandler, executor)).minRebalanceIntervalMillis(rebalanceIntervalMillis).build();
log.debug("Creating kvt request event processors");
Retry.indefinitelyWithExpBackoff(DELAY, MULTIPLIER, MAX_DELAY, e -> log.warn("Error creating request event processor group", e)).run(() -> {
kvtRequestEventProcessors = system.createEventProcessorGroup(kvtRequestConfig, checkpointStore, rebalanceExecutor);
return null;
});
// endregion
log.info("Awaiting start of event processors...");
commitEventProcessors.awaitRunning();
log.info("Commit event processor started.");
abortEventProcessors.awaitRunning();
log.info("Abort event processor started.");
requestEventProcessors.awaitRunning();
log.info("Stream request event processor started.");
kvtRequestEventProcessors.awaitRunning();
log.info("KVT request event processor started.");
}
Aggregations