/** * Returns a new {@link GlobalSequenceTrackingToken} instance that is the sum of this token's sequence number and * the given {@code offset}. * * @param offset the offset between this token's sequence number of that of the returned instance * @return a new tracking token with global sequence increased with the given offset */ public GlobalSequenceTrackingToken offsetBy(int offset) { return new GlobalSequenceTrackingToken(globalIndex + offset); }
private Object readResolve() { return new org.axonframework.eventhandling.GlobalSequenceTrackingToken(globalIndex); } }
/** * Returns the tracking token to use for the next event to be stored. * * @return the tracking token for the next event */ protected GlobalSequenceTrackingToken nextTrackingToken() { return events.isEmpty() ? new GlobalSequenceTrackingToken(0) : ((GlobalSequenceTrackingToken) events.lastKey()).next(); }
@Override public TrackingToken createTailToken() { if (events.size() == 0) { return null; } GlobalSequenceTrackingToken firstToken = (GlobalSequenceTrackingToken) events.firstKey(); return new GlobalSequenceTrackingToken(firstToken.getGlobalIndex() - 1); }
@Override public TrackingToken createTokenAt(Instant dateTime) { return events.values() .stream() .filter(event -> event.getTimestamp().equals(dateTime) || event.getTimestamp().isAfter(dateTime)) .min(Comparator.comparingLong(e -> ((GlobalSequenceTrackingToken) e.trackingToken()) .getGlobalIndex())) .map(TrackedEventMessage::trackingToken) .map(tt -> (GlobalSequenceTrackingToken) tt) .map(tt -> new GlobalSequenceTrackingToken(tt.getGlobalIndex() - 1)) .orElse(null); }
@Override public TrackingToken createHeadToken() { try { io.axoniq.axonserver.grpc.event.TrackingToken token = eventStoreClient.getLastToken().get(); return new GlobalSequenceTrackingToken(token.getToken()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new EventStoreException(e.getMessage(), e); } catch (ExecutionException e) { throw new EventStoreException(e.getMessage(), e); } }
@Override public TrackingToken createTailToken() { try { io.axoniq.axonserver.grpc.event.TrackingToken token = eventStoreClient.getFirstToken().get(); if (token.getToken() < 0) { return null; } return new GlobalSequenceTrackingToken(token.getToken() - 1); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new EventStoreException(e.getMessage(), e); } catch (ExecutionException e) { throw new EventStoreException(e.getMessage(), e); } }
@Override public TrackingToken createTokenAt(Instant instant) { try { io.axoniq.axonserver.grpc.event.TrackingToken token = eventStoreClient.getTokenAt(instant).get(); if (token.getToken() < 0) { return null; } return new GlobalSequenceTrackingToken(token.getToken() - 1); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new EventStoreException(e.getMessage(), e); } catch (ExecutionException e) { throw new EventStoreException(e.getMessage(), e); } }
public boolean push(EventWithToken event) { if( closed) { logger.debug("Received event while closed: {}", event.getToken()); return false; } try { TrackingToken trackingToken = new GlobalSequenceTrackingToken(event.getToken()); events.put(new TrackedDomainEventData<>(trackingToken, new GrpcBackedDomainEventData(event.getEvent()))); } catch (InterruptedException e) { Thread.currentThread().interrupt(); closeCallback.accept(this); return false; } return true; }
@Test public void testBlacklistingSegmentWillHaveProcessorClaimAnotherOne() { tokenStore.storeToken(new GlobalSequenceTrackingToken(1L), "test", 0); tokenStore.storeToken(new GlobalSequenceTrackingToken(2L), "test", 1); tokenStore.storeToken(new GlobalSequenceTrackingToken(2L), "test", 2); testSubject.start(); assertWithin(1, SECONDS, () -> assertEquals(0, testSubject.availableProcessorThreads())); assertEquals(new HashSet<>(asList(0, 1)), testSubject.processingStatus().keySet()); testSubject.releaseSegment(0); assertWithin(5, SECONDS, () -> assertTrue(testSubject.processingStatus().containsKey(2))); assertEquals(new HashSet<>(asList(2, 1)), testSubject.processingStatus().keySet()); assertWithin(2, SECONDS, () -> assertEquals(0, testSubject.availableProcessorThreads())); }
@Test public void testProcessorWorkerCountWithMultipleSegmentsWithOneThread() throws InterruptedException { tokenStore.storeToken(new GlobalSequenceTrackingToken(1L), "test", 0); tokenStore.storeToken(new GlobalSequenceTrackingToken(2L), "test", 1); configureProcessor(TrackingEventProcessorConfiguration.forSingleThreadedProcessing()); testSubject.start(); // give it some time to split segments from the store and submit to executor service. Thread.sleep(200); assertThat(testSubject.activeProcessorThreads(), is(1)); }
@Test public void testProcessorWorkerCountWithMultipleSegments() { tokenStore.storeToken(new GlobalSequenceTrackingToken(1L), "test", 0); tokenStore.storeToken(new GlobalSequenceTrackingToken(2L), "test", 1); testSubject.start(); assertWithin(20, SECONDS, () -> assertThat(testSubject.activeProcessorThreads(), is(2))); assertThat(testSubject.processingStatus().size(), is(2)); assertTrue(testSubject.processingStatus().containsKey(0)); assertTrue(testSubject.processingStatus().containsKey(1)); assertWithin( 10, MILLISECONDS, () -> assertEquals(new GlobalSequenceTrackingToken(1L), testSubject.processingStatus().get(0).getTrackingToken()) ); assertWithin( 10, MILLISECONDS, () -> assertEquals(new GlobalSequenceTrackingToken(2L), testSubject.processingStatus().get(1).getTrackingToken()) ); }
/** * This processor won't be able to handle any segments, as claiming a segment will fail. */ @Test public void testProcessorWorkerCountWithMultipleSegmentsClaimFails() throws InterruptedException { tokenStore.storeToken(new GlobalSequenceTrackingToken(1L), "test", 0); tokenStore.storeToken(new GlobalSequenceTrackingToken(2L), "test", 1); // Will skip segments. doThrow(new UnableToClaimTokenException("Failed")).when(tokenStore).extendClaim("test", 0); doThrow(new UnableToClaimTokenException("Failed")).when(tokenStore).fetchToken("test", 0); doThrow(new UnableToClaimTokenException("Failed")).when(tokenStore).extendClaim("test", 1); doThrow(new UnableToClaimTokenException("Failed")).when(tokenStore).fetchToken("test", 1); testSubject.start(); // give it some time to split segments from the store and submit to executor service. Thread.sleep(200); assertWithin(1, SECONDS, () -> assertThat(testSubject.activeProcessorThreads(), is(0))); }
@Test public void testResetToPositionCausesCertainEventsToBeReplayed() throws Exception { when(mockHandler.supportsReset()).thenReturn(true); final List<String> handled = new CopyOnWriteArrayList<>(); final List<String> handledInRedelivery = new CopyOnWriteArrayList<>(); //noinspection Duplicates doAnswer(i -> { EventMessage message = i.getArgument(0); handled.add(message.getIdentifier()); if (ReplayToken.isReplay(message)) { handledInRedelivery.add(message.getIdentifier()); } return null; }).when(mockHandler).handle(any()); eventBus.publish(createEvents(4)); testSubject.start(); assertWithin(1, TimeUnit.SECONDS, () -> assertEquals(4, handled.size())); testSubject.shutDown(); testSubject.resetTokens(source -> new GlobalSequenceTrackingToken(1L)); testSubject.start(); assertWithin(1, TimeUnit.SECONDS, () -> assertEquals(6, handled.size())); assertFalse(handledInRedelivery.contains(handled.get(0))); assertFalse(handledInRedelivery.contains(handled.get(1))); assertEquals(handled.subList(2, 4), handled.subList(4, 6)); assertEquals(handled.subList(4, 6), handledInRedelivery); assertTrue(testSubject.processingStatus().get(0).isReplaying()); eventBus.publish(createEvents(1)); assertWithin(1, TimeUnit.SECONDS, () -> assertFalse(testSubject.processingStatus().get(0).isReplaying())); }
() -> assertEquals(new GlobalSequenceTrackingToken(1), tokenStore.fetchToken("test", 0)) ); assertWithin( 1, SECONDS, () -> assertEquals(new GlobalSequenceTrackingToken(1), tokenStore.fetchToken("test", 1)) ); () -> assertEquals(new GlobalSequenceTrackingToken(3), tokenStore.fetchToken("test", 0)) ); assertWithin( 1, SECONDS, () -> assertEquals(new GlobalSequenceTrackingToken(3), tokenStore.fetchToken("test", 1)) );
@Test public void testProcessorExtendsClaimOnSegment() throws InterruptedException { tokenStore.storeToken(new GlobalSequenceTrackingToken(1L), "test", 0); tokenStore.storeToken(new GlobalSequenceTrackingToken(2L), "test", 1); testSubject.start(); // give it some time to split segments from the store and submit to executor service. Thread.sleep(200); eventBus.publish(createEvents(10)); assertWithin(200, MILLISECONDS, () -> verify(tokenStore, atLeast(1)).extendClaim("test", 0)); assertWithin(200, MILLISECONDS, () -> verify(tokenStore, atLeast(1)).extendClaim("test", 1)); assertWithin(1, SECONDS, () -> assertThat(testSubject.activeProcessorThreads(), is(2))); }
TrackingToken trackingToken = new GlobalSequenceTrackingToken(0); List<TrackedEventMessage<?>> events = createEvents(2).stream().map(event -> asTrackedEventMessage(event, trackingToken)).collect(toList());
TrackingEventProcessorConfiguration config = TrackingEventProcessorConfiguration.forSingleThreadedProcessing() .andInitialTrackingToken(ms -> new GlobalSequenceTrackingToken(1L)); TrackingEventProcessor.Builder eventProcessorBuilder = TrackingEventProcessor.builder()
@Override public TrackingToken createTailToken() { if (events.size() == 0) { return null; } GlobalSequenceTrackingToken firstToken = (GlobalSequenceTrackingToken) events.firstKey(); return new GlobalSequenceTrackingToken(firstToken.getGlobalIndex() - 1); }
@Override public TrackingToken createTokenAt(Instant dateTime) { return events.values() .stream() .filter(event -> event.getTimestamp().equals(dateTime) || event.getTimestamp().isAfter(dateTime)) .min(Comparator.comparingLong(e -> ((GlobalSequenceTrackingToken) e.trackingToken()) .getGlobalIndex())) .map(TrackedEventMessage::trackingToken) .map(tt -> (GlobalSequenceTrackingToken) tt) .map(tt -> new GlobalSequenceTrackingToken(tt.getGlobalIndex() - 1)) .orElse(null); }