@Override public void configureModule(Configurer configurer) { configurer.registerComponent(AxonServerConfiguration.class, c -> new AxonServerConfiguration()); configurer.registerComponent(AxonServerConnectionManager.class, c -> buildAxonServerConnectionManager(c)); configurer.configureEventStore(this::buildEventStore); configurer.configureCommandBus(this::buildCommandBus); configurer.configureQueryBus(this::buildQueryBus); configurer.registerModule(new EventProcessorInfoConfiguration()); configurer.registerComponent(TokenStore.class, c -> { logger.warn("BEWARE! Falling back to an in-memory token store. It is highly recommended to configure a " + "persistent implementation, based on the activity of the handler."); return new InMemoryTokenStore(); }); }
@Test @DirtiesContext public void testProcessorGoesToRetryModeWhenOpenStreamFails() throws Exception { eventBus = spy(eventBus); tokenStore = new InMemoryTokenStore(); eventBus.publish(createEvents(5)); when(eventBus.openStream(any())).thenThrow(new MockException()).thenCallRealMethod(); List<EventMessage<?>> ackedEvents = new ArrayList<>(); CountDownLatch countDownLatch = new CountDownLatch(5); doAnswer(invocation -> { ackedEvents.add((EventMessage<?>) invocation.getArguments()[0]); countDownLatch.countDown(); return null; }).when(mockHandler).handle(any()); testSubject = TrackingEventProcessor.builder() .name("test") .eventHandlerInvoker(eventHandlerInvoker) .messageSource(eventBus) .tokenStore(tokenStore) .transactionManager(NoTransactionManager.INSTANCE) .build(); testSubject.start(); // give it a bit of time to start Thread.sleep(200); assertTrue("Expected 5 invocations on Event Handler by now", countDownLatch.await(10, TimeUnit.SECONDS)); assertEquals(5, ackedEvents.size()); verify(eventBus, times(2)).openStream(any()); }
@Before public void setUp() { tokenStore = spy(new InMemoryTokenStore()); mockHandler = mock(EventMessageHandler.class); when(mockHandler.canHandle(any())).thenReturn(true);
@Test public void testMultiThreadProcessorGoesToRetryModeWhenOpenStreamFails() throws Exception { eventBus = spy(eventBus); tokenStore = new InMemoryTokenStore(); eventBus.publish(createEvents(5)); when(eventBus.openStream(any())).thenThrow(new MockException()).thenCallRealMethod(); final AcknowledgeByThread acknowledgeByThread = new AcknowledgeByThread(); CountDownLatch countDownLatch = new CountDownLatch(5); doAnswer(invocation -> { acknowledgeByThread.addMessage(Thread.currentThread(), (EventMessage<?>) invocation.getArguments()[0]); countDownLatch.countDown(); return null; }).when(mockHandler).handle(any()); testSubject = TrackingEventProcessor.builder() .name("test") .eventHandlerInvoker(eventHandlerInvoker) .messageSource(eventBus) .tokenStore(tokenStore) .transactionManager(NoTransactionManager.INSTANCE) .build(); testSubject.start(); assertTrue("Expected 5 invocations on Event Handler by now", countDownLatch.await(10, SECONDS)); acknowledgeByThread.assertEventsAddUpTo(5); verify(eventBus, times(2)).openStream(any()); }
@Test public void testMultiThreadContinueFromPreviousToken() throws Exception { tokenStore = spy(new InMemoryTokenStore()); eventBus.publish(createEvents(10)); TrackedEventMessage<?> firstEvent = eventBus.openStream(null).nextAvailable(); tokenStore.storeToken(firstEvent.trackingToken(), testSubject.getName(), 0); assertEquals(firstEvent.trackingToken(), tokenStore.fetchToken(testSubject.getName(), 0)); final AcknowledgeByThread acknowledgeByThread = new AcknowledgeByThread(); CountDownLatch countDownLatch = new CountDownLatch(9); doAnswer(invocation -> { acknowledgeByThread.addMessage(Thread.currentThread(), (EventMessage<?>) invocation.getArguments()[0]); countDownLatch.countDown(); return null; }).when(mockHandler).handle(any()); configureProcessor(TrackingEventProcessorConfiguration.forParallelProcessing(2)); testSubject.start(); assertTrue("Expected 9 invocations on Event Handler by now, missing " + countDownLatch.getCount(), countDownLatch.await(60, SECONDS)); acknowledgeByThread.assertEventsAckedByMultipleThreads(); acknowledgeByThread.assertEventsAddUpTo(9); }
@Before public void setUp() { tokenStore = spy(new InMemoryTokenStore()); mockHandler = mock(EventMessageHandler.class); when(mockHandler.canHandle(any())).thenReturn(true); eventHandlerInvoker = SimpleEventHandlerInvoker.builder() .eventHandlers(singletonList(mockHandler)) .sequencingPolicy(event -> { if (event instanceof DomainEventMessage) { return ((DomainEventMessage) event) .getSequenceNumber(); } return event.getIdentifier(); }) .build(); eventBus = EmbeddedEventStore.builder().storageEngine(new InMemoryEventStorageEngine()).build(); // A processor config, with a policy which guarantees segmenting by using the sequence number. configureProcessor(TrackingEventProcessorConfiguration.forParallelProcessing(2)); }
@Test @DirtiesContext public void testContinueFromPreviousToken() throws Exception { tokenStore = new InMemoryTokenStore(); eventBus.publish(createEvents(10)); TrackedEventMessage<?> firstEvent = eventBus.openStream(null).nextAvailable(); tokenStore.storeToken(firstEvent.trackingToken(), testSubject.getName(), 0); assertEquals(firstEvent.trackingToken(), tokenStore.fetchToken(testSubject.getName(), 0)); List<EventMessage<?>> ackedEvents = new ArrayList<>(); CountDownLatch countDownLatch = new CountDownLatch(9); doAnswer(invocation -> { ackedEvents.add((EventMessage<?>) invocation.getArguments()[0]); countDownLatch.countDown(); return null; }).when(mockHandler).handle(any()); testSubject = TrackingEventProcessor.builder() .name("test") .eventHandlerInvoker(eventHandlerInvoker) .messageSource(eventBus) .tokenStore(tokenStore) .transactionManager(NoTransactionManager.INSTANCE) .build(); testSubject.start(); // give it a bit of time to start Thread.sleep(200); assertTrue("Expected 9 invocations on Event Handler by now", countDownLatch.await(5, TimeUnit.SECONDS)); assertEquals(9, ackedEvents.size()); }
.eventHandlerInvoker(eventHandlerInvoker) .messageSource(eventStore) .tokenStore(new InMemoryTokenStore()) .transactionManager(NoTransactionManager.INSTANCE) .build();
@Bean public TokenStore tokenStore(EventStorageEngine engine) { if (engine instanceof KafkaEventStoreEngine) { log.info("Configuring Kafka token store."); return new KafkaTokenStore(((KafkaEventStoreEngine) engine).getConsumer(), eventStorageTopic); } return new InMemoryTokenStore(); }
@Override public void configureModule(Configurer configurer) { configurer.registerComponent(AxonServerConfiguration.class, c -> new AxonServerConfiguration()); configurer.registerComponent(AxonServerConnectionManager.class, c -> buildAxonServerConnectionManager(c)); configurer.configureEventStore(this::buildEventStore); configurer.configureCommandBus(this::buildCommandBus); configurer.configureQueryBus(this::buildQueryBus); configurer.registerModule(new EventProcessorInfoConfiguration()); configurer.registerComponent(TokenStore.class, c -> { logger.warn("BEWARE! Falling back to an in-memory token store. It is highly recommended to configure a " + "persistent implementation, based on the activity of the handler."); return new InMemoryTokenStore(); }); }