Search in sources :

Example 1 with ReaderGroupConfigRejectedException

use of io.pravega.client.control.impl.ReaderGroupConfigRejectedException in project pravega by pravega.

the class ReaderGroupImpl method resetReaderGroup.

@Override
public void resetReaderGroup(ReaderGroupConfig config) {
    log.info("Reset ReaderGroup {} to {}", getGroupName(), config);
    synchronizer.fetchUpdates();
    while (true) {
        val currentConfig = synchronizer.getState().getConfig();
        // We only move into the block if the state transition has happened successfully.
        if (stateTransition(currentConfig, new UpdatingConfig(true))) {
            if (currentConfig.getReaderGroupId() == ReaderGroupConfig.DEFAULT_UUID && currentConfig.getGeneration() == ReaderGroupConfig.DEFAULT_GENERATION) {
                // Migration code path, for moving a ReaderGroup from version < 0.9 to 0.9+
                final ReaderGroupConfig updateConfig = ReaderGroupConfig.cloneConfig(config, UUID.randomUUID(), 0L);
                final long nextGen = Futures.getThrowingException(controller.createReaderGroup(scope, getGroupName(), updateConfig).thenCompose(conf -> {
                    if (!conf.getReaderGroupId().equals(updateConfig.getReaderGroupId())) {
                        return controller.updateReaderGroup(scope, groupName, ReaderGroupConfig.cloneConfig(updateConfig, conf.getReaderGroupId(), conf.getGeneration()));
                    } else {
                        // ReaderGroup IDs matched so our create was updated on Controller
                        return CompletableFuture.completedFuture(conf.getGeneration());
                    }
                }));
                updateConfigInStateSynchronizer(updateConfig, nextGen);
            } else {
                // normal code path
                // Use the latest generation and reader group Id.
                ReaderGroupConfig newConfig = ReaderGroupConfig.cloneConfig(config, currentConfig.getReaderGroupId(), currentConfig.getGeneration());
                long newGen = Futures.exceptionallyExpecting(controller.updateReaderGroup(scope, groupName, newConfig), e -> Exceptions.unwrap(e) instanceof ReaderGroupConfigRejectedException, -1L).join();
                if (newGen == -1) {
                    log.debug("Synchronize reader group with the one present on controller.");
                    synchronizeReaderGroupConfig();
                    continue;
                }
                updateConfigInStateSynchronizer(newConfig, newGen);
            }
            return;
        }
    }
}
Also used : lombok.val(lombok.val) ReaderGroupConfig(io.pravega.client.stream.ReaderGroupConfig) StreamCut(io.pravega.client.stream.StreamCut) ReaderGroupStateInit(io.pravega.client.stream.impl.ReaderGroupState.ReaderGroupStateInit) SneakyThrows(lombok.SneakyThrows) UpdatingConfig(io.pravega.client.stream.impl.ReaderGroupState.UpdatingConfig) ReaderGroup(io.pravega.client.stream.ReaderGroup) ReaderGroupMetrics(io.pravega.client.stream.ReaderGroupMetrics) EndOfDataNotification(io.pravega.client.stream.notifications.EndOfDataNotification) Position(io.pravega.client.stream.Position) Stream(io.pravega.client.stream.Stream) AccessOperation(io.pravega.shared.security.auth.AccessOperation) Duration(java.time.Duration) Map(java.util.Map) Checkpoint(io.pravega.client.stream.Checkpoint) Futures.getThrowingException(io.pravega.common.concurrent.Futures.getThrowingException) ReaderGroupConfig(io.pravega.client.stream.ReaderGroupConfig) ImmutableMap(com.google.common.collect.ImmutableMap) Set(java.util.Set) DelegationTokenProviderFactory(io.pravega.client.security.auth.DelegationTokenProviderFactory) UUID(java.util.UUID) InitialUpdate(io.pravega.client.state.InitialUpdate) Collectors(java.util.stream.Collectors) SegmentMetadataClient(io.pravega.client.segment.impl.SegmentMetadataClient) NotifierFactory(io.pravega.client.stream.notifications.NotifierFactory) Base64(java.util.Base64) List(java.util.List) Slf4j(lombok.extern.slf4j.Slf4j) Observable(io.pravega.client.stream.notifications.Observable) Entry(java.util.Map.Entry) Optional(java.util.Optional) Controller(io.pravega.client.control.impl.Controller) Futures(io.pravega.common.concurrent.Futures) ClearCheckpointsBefore(io.pravega.client.stream.impl.ReaderGroupState.ClearCheckpointsBefore) StateSynchronizer(io.pravega.client.state.StateSynchronizer) Segment(io.pravega.client.segment.impl.Segment) NotificationSystem(io.pravega.client.stream.notifications.NotificationSystem) Exceptions(io.pravega.common.Exceptions) SegmentMetadataClientFactoryImpl(io.pravega.client.segment.impl.SegmentMetadataClientFactoryImpl) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ReaderGroupConfigRejectedException(io.pravega.client.control.impl.ReaderGroupConfigRejectedException) SegmentMetadataClientFactory(io.pravega.client.segment.impl.SegmentMetadataClientFactory) ArrayList(java.util.ArrayList) Update(io.pravega.client.state.Update) SegmentNotification(io.pravega.client.stream.notifications.SegmentNotification) CreateCheckpoint(io.pravega.client.stream.impl.ReaderGroupState.CreateCheckpoint) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) SynchronizerConfig(io.pravega.client.state.SynchronizerConfig) Serializer(io.pravega.client.stream.Serializer) NameUtils(io.pravega.shared.NameUtils) Futures.getAndHandleExceptions(io.pravega.common.concurrent.Futures.getAndHandleExceptions) ConnectionPool(io.pravega.client.connection.impl.ConnectionPool) lombok.val(lombok.val) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Futures.allOfWithResults(io.pravega.common.concurrent.Futures.allOfWithResults) DelegationTokenProvider(io.pravega.client.security.auth.DelegationTokenProvider) SynchronizerClientFactory(io.pravega.client.SynchronizerClientFactory) ReaderSegmentDistribution(io.pravega.client.stream.ReaderSegmentDistribution) Data(lombok.Data) InvalidStreamException(io.pravega.client.stream.InvalidStreamException) Preconditions(com.google.common.base.Preconditions) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) ReaderGroupConfigRejectedException(io.pravega.client.control.impl.ReaderGroupConfigRejectedException) UpdatingConfig(io.pravega.client.stream.impl.ReaderGroupState.UpdatingConfig)

Example 2 with ReaderGroupConfigRejectedException

use of io.pravega.client.control.impl.ReaderGroupConfigRejectedException in project pravega by pravega.

the class ReaderGroupImplTest method laggingResetReaderGroup.

@Test
@SuppressWarnings("unchecked")
public void laggingResetReaderGroup() {
    UUID rgId = UUID.randomUUID();
    ReaderGroupConfig config1 = ReaderGroupConfig.builder().startFromStreamCuts(ImmutableMap.<Stream, StreamCut>builder().put(createStream("s1"), createStreamCut("s1", 2)).put(createStream("s2"), createStreamCut("s2", 3)).build()).build();
    config1 = ReaderGroupConfig.cloneConfig(config1, rgId, 0L);
    ReaderGroupConfig config2 = ReaderGroupConfig.builder().startFromStreamCuts(ImmutableMap.<Stream, StreamCut>builder().put(createStream("s3"), createStreamCut("s3", 2)).put(createStream("s4"), createStreamCut("s4", 3)).build()).build();
    config2 = ReaderGroupConfig.cloneConfig(config2, rgId, 1L);
    when(state.getConfig()).thenReturn(config1, config2);
    when(synchronizer.getState()).thenReturn(state);
    CompletableFuture<Long> badFuture = new CompletableFuture<>();
    badFuture.completeExceptionally(new ReaderGroupConfigRejectedException("handle"));
    // The controller has config2
    when(controller.updateReaderGroup(eq(SCOPE), eq(GROUP_NAME), argThat(new ReaderGroupConfigMatcher(config1)))).thenReturn(badFuture);
    when(controller.updateReaderGroup(eq(SCOPE), eq(GROUP_NAME), argThat(new ReaderGroupConfigMatcher(ReaderGroupConfig.cloneConfig(config1, config1.getReaderGroupId(), config2.getGeneration()))))).thenReturn(CompletableFuture.completedFuture(2L));
    when(controller.getReaderGroupConfig(SCOPE, GROUP_NAME)).thenReturn(CompletableFuture.completedFuture(config2));
    readerGroup.resetReaderGroup(config1);
    verify(synchronizer, times(1)).fetchUpdates();
    verify(controller, times(1)).updateReaderGroup(eq(SCOPE), eq(GROUP_NAME), argThat(new ReaderGroupConfigMatcher(config1)));
    verify(controller, times(1)).updateReaderGroup(eq(SCOPE), eq(GROUP_NAME), argThat(new ReaderGroupConfigMatcher(ReaderGroupConfig.cloneConfig(config1, config1.getReaderGroupId(), config2.getGeneration()))));
    verify(controller, times(1)).getReaderGroupConfig(SCOPE, GROUP_NAME);
    verify(synchronizer, times(4)).updateState(any(StateSynchronizer.UpdateGenerator.class));
}
Also used : ReaderGroupConfig(io.pravega.client.stream.ReaderGroupConfig) CompletableFuture(java.util.concurrent.CompletableFuture) ReaderGroupConfigRejectedException(io.pravega.client.control.impl.ReaderGroupConfigRejectedException) UUID(java.util.UUID) Test(org.junit.Test)

Example 3 with ReaderGroupConfigRejectedException

use of io.pravega.client.control.impl.ReaderGroupConfigRejectedException in project pravega by pravega.

the class ReaderGroupImplTest method testAsyncResetReaderGroup.

@Test(timeout = 10000L)
@SuppressWarnings("unchecked")
public void testAsyncResetReaderGroup() {
    UUID rgId = UUID.randomUUID();
    ReaderGroupConfig config1 = ReaderGroupConfig.builder().startFromStreamCuts(ImmutableMap.<Stream, StreamCut>builder().put(createStream("s1"), createStreamCut("s1", 2)).build()).build();
    config1 = ReaderGroupConfig.cloneConfig(config1, rgId, 0L);
    ReaderGroupConfig config2 = ReaderGroupConfig.builder().startFromStreamCuts(ImmutableMap.<Stream, StreamCut>builder().put(createStream("s2"), createStreamCut("s2", 2)).build()).build();
    config2 = ReaderGroupConfig.cloneConfig(config2, rgId, 0L);
    ReaderGroupConfig config3 = ReaderGroupConfig.builder().startFromStreamCuts(ImmutableMap.<Stream, StreamCut>builder().put(createStream("s3"), createStreamCut("s3", 2)).build()).build();
    config3 = ReaderGroupConfig.cloneConfig(config3, rgId, 0L);
    AtomicInteger x = new AtomicInteger(0);
    CompletableFuture<Void> wait = new CompletableFuture<>();
    CompletableFuture<Void> signal = new CompletableFuture<>();
    // The client's config.
    AtomicReference<ReaderGroupConfig> atomicConfig = new AtomicReference<>(config1);
    // The controller's config.
    AtomicReference<ReaderGroupConfig> atomicConfigController = new AtomicReference<>(config1);
    // return the client's config when calling state.getConfig.
    doAnswer(a -> atomicConfig.get()).when(state).getConfig();
    when(synchronizer.getState()).thenReturn(state);
    // return controllerConfig when calling getReaderGroupConfig.
    doAnswer(a -> CompletableFuture.completedFuture(atomicConfigController.get())).when(controller).getReaderGroupConfig(anyString(), anyString());
    // update the client config to the controller config whenever we update the StateSync.
    doAnswer(a -> {
        atomicConfig.set(atomicConfigController.get());
        return null;
    }).when(synchronizer).updateState(any(StateSynchronizer.UpdateGenerator.class));
    // update the controller config with the incremented generation if the generations match.
    doAnswer(a -> {
        ReaderGroupConfig c = a.getArgument(2);
        // the first one to call needs to wait until the second call has been completed.
        if (x.getAndIncrement() == 0) {
            signal.complete(null);
            wait.join();
        }
        if (c.getGeneration() == atomicConfigController.get().getGeneration()) {
            long incGen = c.getGeneration() + 1;
            atomicConfigController.set(ReaderGroupConfig.cloneConfig(c, c.getReaderGroupId(), incGen));
            return CompletableFuture.completedFuture(incGen);
        } else {
            CompletableFuture<Long> badFuture = new CompletableFuture<>();
            badFuture.completeExceptionally(new ReaderGroupConfigRejectedException("handle"));
            return badFuture;
        }
    }).when(controller).updateReaderGroup(anyString(), anyString(), any(ReaderGroupConfig.class));
    // run the first call async.
    final ReaderGroupConfig newConf = config2;
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> readerGroup.resetReaderGroup(newConf));
    // Once the first call has reached the controller.updateReaderGroup step then signal so he waits.
    signal.join();
    // start the second call.
    readerGroup.resetReaderGroup(config3);
    // Once the second is completed stop the wait so the first call can go ahead.
    wait.complete(null);
    // wait for the first call to complete.
    assertTrue(Futures.await(future));
    // assert the generation was incremented twice due to two updates.
    assertEquals(2L, atomicConfig.get().getGeneration());
    assertEquals(2L, atomicConfigController.get().getGeneration());
    // assert the first call happened last and the streams are s2.
    assertTrue(atomicConfig.get().getStartingStreamCuts().keySet().stream().anyMatch(s -> s.getStreamName().equals("s2")));
    assertTrue(atomicConfigController.get().getStartingStreamCuts().keySet().stream().anyMatch(s -> s.getStreamName().equals("s2")));
}
Also used : ReaderGroupConfig(io.pravega.client.stream.ReaderGroupConfig) ReaderGroupStateInitSerializer(io.pravega.client.admin.impl.ReaderGroupManagerImpl.ReaderGroupStateInitSerializer) Arrays(java.util.Arrays) StreamCut(io.pravega.client.stream.StreamCut) AssertExtensions.assertSuppliedFutureThrows(io.pravega.test.common.AssertExtensions.assertSuppliedFutureThrows) ArgumentMatchers.argThat(org.mockito.ArgumentMatchers.argThat) AssertExtensions(io.pravega.test.common.AssertExtensions) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) Cleanup(lombok.Cleanup) ArgumentMatcher(org.mockito.ArgumentMatcher) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Stream(io.pravega.client.stream.Stream) Map(java.util.Map) Mockito.doAnswer(org.mockito.Mockito.doAnswer) Checkpoint(io.pravega.client.stream.Checkpoint) ReaderGroupConfig(io.pravega.client.stream.ReaderGroupConfig) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Set(java.util.Set) ScheduledThreadPoolExecutor(java.util.concurrent.ScheduledThreadPoolExecutor) UUID(java.util.UUID) InitialUpdate(io.pravega.client.state.InitialUpdate) Collectors(java.util.stream.Collectors) ReaderGroupStateUpdatesSerializer(io.pravega.client.admin.impl.ReaderGroupManagerImpl.ReaderGroupStateUpdatesSerializer) Assert.assertFalse(org.junit.Assert.assertFalse) Optional(java.util.Optional) MockitoJUnitRunner(org.mockito.junit.MockitoJUnitRunner) Controller(io.pravega.client.control.impl.Controller) Futures(io.pravega.common.concurrent.Futures) ClearCheckpointsBefore(io.pravega.client.stream.impl.ReaderGroupState.ClearCheckpointsBefore) Mockito.mock(org.mockito.Mockito.mock) StateSynchronizer(io.pravega.client.state.StateSynchronizer) IntStream(java.util.stream.IntStream) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) Segment(io.pravega.client.segment.impl.Segment) Mock(org.mockito.Mock) RunWith(org.junit.runner.RunWith) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) ReaderGroupConfigRejectedException(io.pravega.client.control.impl.ReaderGroupConfigRejectedException) Update(io.pravega.client.state.Update) HashSet(java.util.HashSet) SynchronizerConfig(io.pravega.client.state.SynchronizerConfig) Before(org.junit.Before) Serializer(io.pravega.client.stream.Serializer) NameUtils(io.pravega.shared.NameUtils) ConnectionPool(io.pravega.client.connection.impl.ConnectionPool) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) Mockito.times(org.mockito.Mockito.times) Mockito.when(org.mockito.Mockito.when) Mockito.verify(org.mockito.Mockito.verify) ExecutionException(java.util.concurrent.ExecutionException) Mockito(org.mockito.Mockito) SynchronizerClientFactory(io.pravega.client.SynchronizerClientFactory) ReaderSegmentDistribution(io.pravega.client.stream.ReaderSegmentDistribution) InlineExecutor(io.pravega.test.common.InlineExecutor) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) StreamCut(io.pravega.client.stream.StreamCut) AtomicReference(java.util.concurrent.atomic.AtomicReference) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ReaderGroupConfigRejectedException(io.pravega.client.control.impl.ReaderGroupConfigRejectedException) Stream(io.pravega.client.stream.Stream) IntStream(java.util.stream.IntStream) UUID(java.util.UUID) Test(org.junit.Test)

Example 4 with ReaderGroupConfigRejectedException

use of io.pravega.client.control.impl.ReaderGroupConfigRejectedException in project pravega by pravega.

the class LocalControllerTest method testUpdateReaderGroup.

@Test(timeout = 10000)
public void testUpdateReaderGroup() throws ExecutionException, InterruptedException {
    final Segment seg0 = new Segment("scope", "stream1", 0L);
    final Segment seg1 = new Segment("scope", "stream1", 1L);
    ImmutableMap<Segment, Long> startStreamCut = ImmutableMap.of(seg0, 10L, seg1, 10L);
    Map<Stream, StreamCut> startSC = ImmutableMap.of(Stream.of("scope", "stream1"), new StreamCutImpl(Stream.of("scope", "stream1"), startStreamCut));
    ImmutableMap<Segment, Long> endStreamCut = ImmutableMap.of(seg0, 200L, seg1, 300L);
    Map<Stream, StreamCut> endSC = ImmutableMap.of(Stream.of("scope", "stream1"), new StreamCutImpl(Stream.of("scope", "stream1"), endStreamCut));
    ReaderGroupConfig rgConfig = ReaderGroupConfig.builder().automaticCheckpointIntervalMillis(30000L).groupRefreshTimeMillis(20000L).maxOutstandingCheckpointRequest(2).retentionType(ReaderGroupConfig.StreamDataRetention.AUTOMATIC_RELEASE_AT_LAST_CHECKPOINT).startingStreamCuts(startSC).endingStreamCuts(endSC).build();
    ReaderGroupConfig config = ReaderGroupConfig.cloneConfig(rgConfig, UUID.randomUUID(), 0L);
    when(this.mockControllerService.updateReaderGroup(anyString(), anyString(), any(), anyLong())).thenReturn(CompletableFuture.completedFuture(Controller.UpdateReaderGroupResponse.newBuilder().setStatus(Controller.UpdateReaderGroupResponse.Status.SUCCESS).setGeneration(1L).build()));
    Assert.assertNotNull(this.testController.updateReaderGroup("scope", "subscriber", config).join());
    when(this.mockControllerService.updateReaderGroup(anyString(), anyString(), any(), anyLong())).thenReturn(CompletableFuture.completedFuture(Controller.UpdateReaderGroupResponse.newBuilder().setStatus(Controller.UpdateReaderGroupResponse.Status.FAILURE).build()));
    assertThrows("Expected ControllerFailureException", () -> this.testController.updateReaderGroup("scope", "subscriber", config).join(), ex -> ex instanceof ControllerFailureException);
    when(this.mockControllerService.updateReaderGroup(anyString(), anyString(), any(), anyLong())).thenReturn(CompletableFuture.completedFuture(Controller.UpdateReaderGroupResponse.newBuilder().setStatus(Controller.UpdateReaderGroupResponse.Status.INVALID_CONFIG).build()));
    assertThrows("Expected ReaderGroupConfigRejectedException", () -> this.testController.updateReaderGroup("scope", "subscriber", config).join(), ex -> ex instanceof ReaderGroupConfigRejectedException);
    when(this.mockControllerService.updateReaderGroup(anyString(), anyString(), any(), anyLong())).thenReturn(CompletableFuture.completedFuture(Controller.UpdateReaderGroupResponse.newBuilder().setStatus(Controller.UpdateReaderGroupResponse.Status.RG_NOT_FOUND).build()));
    assertThrows("Expected IllegalArgumentException", () -> this.testController.updateReaderGroup("scope", "subscriber", config).join(), ex -> ex instanceof IllegalArgumentException);
    when(this.mockControllerService.updateReaderGroup(anyString(), anyString(), any(), anyLong())).thenReturn(CompletableFuture.completedFuture(Controller.UpdateReaderGroupResponse.newBuilder().setStatusValue(-1).build()));
    assertThrows("Expected ControllerFailureException", () -> this.testController.updateReaderGroup("scope", "subscriber", config).join(), ex -> ex instanceof ControllerFailureException);
}
Also used : ReaderGroupConfig(io.pravega.client.stream.ReaderGroupConfig) StreamCut(io.pravega.client.stream.StreamCut) StreamCutImpl(io.pravega.client.stream.impl.StreamCutImpl) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ControllerFailureException(io.pravega.client.control.impl.ControllerFailureException) ReaderGroupConfigRejectedException(io.pravega.client.control.impl.ReaderGroupConfigRejectedException) Stream(io.pravega.client.stream.Stream) Segment(io.pravega.client.segment.impl.Segment) Test(org.junit.Test)

Aggregations

ReaderGroupConfigRejectedException (io.pravega.client.control.impl.ReaderGroupConfigRejectedException)4 ReaderGroupConfig (io.pravega.client.stream.ReaderGroupConfig)4 Segment (io.pravega.client.segment.impl.Segment)3 Stream (io.pravega.client.stream.Stream)3 StreamCut (io.pravega.client.stream.StreamCut)3 UUID (java.util.UUID)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 Test (org.junit.Test)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 SynchronizerClientFactory (io.pravega.client.SynchronizerClientFactory)2 ConnectionPool (io.pravega.client.connection.impl.ConnectionPool)2 Controller (io.pravega.client.control.impl.Controller)2 InitialUpdate (io.pravega.client.state.InitialUpdate)2 StateSynchronizer (io.pravega.client.state.StateSynchronizer)2 SynchronizerConfig (io.pravega.client.state.SynchronizerConfig)2 Update (io.pravega.client.state.Update)2 Checkpoint (io.pravega.client.stream.Checkpoint)2 ReaderSegmentDistribution (io.pravega.client.stream.ReaderSegmentDistribution)2 Serializer (io.pravega.client.stream.Serializer)2 ClearCheckpointsBefore (io.pravega.client.stream.impl.ReaderGroupState.ClearCheckpointsBefore)2