Search in sources :

Example 1 with StreamsList

use of io.pravega.controller.server.rest.generated.model.StreamsList in project pravega by pravega.

the class StreamMetaDataAuthFocusedTests method testListStreamsReturnsAllWhenUserHasWildCardAccess.

@Test
public void testListStreamsReturnsAllWhenUserHasWildCardAccess() {
    // Arrange
    String resourceURI = getURI() + "v1/scopes/myscope/streams";
    Map<String, StreamConfiguration> streamsList = ImmutableMap.of("stream1", this.aStreamConfig(), "stream2", this.aStreamConfig(), "stream3", this.aStreamConfig());
    when(mockControllerService.listStreamsInScope(eq("myscope"), anyLong())).thenReturn(CompletableFuture.completedFuture(streamsList));
    // Act
    Response response = this.invocationBuilder(resourceURI, USER_PRIVILEGED, DEFAULT_PASSWORD).buildGet().invoke();
    StreamsList listedStreams = response.readEntity(StreamsList.class);
    // Assert
    assertEquals(HTTP_STATUS_OK, response.getStatus());
    assertEquals(3, listedStreams.getStreams().size());
    response.close();
}
Also used : Response(javax.ws.rs.core.Response) StreamsList(io.pravega.controller.server.rest.generated.model.StreamsList) StreamConfiguration(io.pravega.client.stream.StreamConfiguration) AuthFileUtils.credentialsAndAclAsString(io.pravega.auth.AuthFileUtils.credentialsAndAclAsString) Test(org.junit.Test)

Example 2 with StreamsList

use of io.pravega.controller.server.rest.generated.model.StreamsList in project pravega by pravega.

the class StreamMetaDataAuthFocusedTests method testListStreamsReturnsEmptyListWhenUserHasNoStreamsAssigned.

// endregion
// region Streams listing tests
@Test
public void testListStreamsReturnsEmptyListWhenUserHasNoStreamsAssigned() {
    // Arrange
    String resourceURI = getURI() + "v1/scopes/myscope/streams";
    Map<String, StreamConfiguration> streamsList = ImmutableMap.of("stream1", this.aStreamConfig(), "stream2", this.aStreamConfig());
    when(mockControllerService.listStreamsInScope(eq("myscope"), anyLong())).thenReturn(CompletableFuture.completedFuture(streamsList));
    // Act
    Response response = this.invocationBuilder(resourceURI, USER_ACCESS_TO_SCOPES_BUT_NOSTREAMS, DEFAULT_PASSWORD).buildGet().invoke();
    StreamsList listedStreams = response.readEntity(StreamsList.class);
    // Assert
    assertEquals(HTTP_STATUS_OK, response.getStatus());
    Assert.assertTrue(listedStreams.getStreams().isEmpty());
    response.close();
}
Also used : Response(javax.ws.rs.core.Response) StreamsList(io.pravega.controller.server.rest.generated.model.StreamsList) StreamConfiguration(io.pravega.client.stream.StreamConfiguration) AuthFileUtils.credentialsAndAclAsString(io.pravega.auth.AuthFileUtils.credentialsAndAclAsString) Test(org.junit.Test)

Example 3 with StreamsList

use of io.pravega.controller.server.rest.generated.model.StreamsList in project pravega by pravega.

the class StreamMetaDataAuthFocusedTests method testListStreamsReturnsAllStreamsWhenUserHasWildcardOnScope.

@Test
public void testListStreamsReturnsAllStreamsWhenUserHasWildcardOnScope() {
    // Arrange
    String resourceURI = getURI() + "v1/scopes/myscope/streams";
    Map<String, StreamConfiguration> streamsList = ImmutableMap.of("stream1", this.aStreamConfig(), "stream2", this.aStreamConfig(), "stream3", this.aStreamConfig());
    when(mockControllerService.listStreamsInScope(eq("myscope"), anyLong())).thenReturn(CompletableFuture.completedFuture(streamsList));
    // Act
    Response response = this.invocationBuilder(resourceURI, USER_ACCESS_TO_SCOPES_READ_ALLSTREAMS, DEFAULT_PASSWORD).buildGet().invoke();
    StreamsList listedStreams = response.readEntity(StreamsList.class);
    // Assert
    assertEquals(HTTP_STATUS_OK, response.getStatus());
    assertEquals(3, listedStreams.getStreams().size());
    response.close();
}
Also used : Response(javax.ws.rs.core.Response) StreamsList(io.pravega.controller.server.rest.generated.model.StreamsList) StreamConfiguration(io.pravega.client.stream.StreamConfiguration) AuthFileUtils.credentialsAndAclAsString(io.pravega.auth.AuthFileUtils.credentialsAndAclAsString) Test(org.junit.Test)

Example 4 with StreamsList

use of io.pravega.controller.server.rest.generated.model.StreamsList in project pravega by pravega.

the class StreamMetaDataTests method testListStreams.

/**
 * Test for listStreams REST API.
 *
 * @throws ExecutionException
 * @throws InterruptedException
 */
@Test(timeout = 30000)
public void testListStreams() throws ExecutionException, InterruptedException {
    final String resourceURI = getURI() + "v1/scopes/scope1/streams";
    final StreamConfiguration streamConfiguration1 = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.byEventRate(100, 2, 2)).retentionPolicy(RetentionPolicy.byTime(Duration.ofMillis(123L))).build();
    final StreamConfiguration streamConfiguration2 = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.byEventRate(100, 2, 2)).retentionPolicy(RetentionPolicy.byTime(Duration.ofMillis(123L))).build();
    // Test to list streams.
    Map<String, StreamConfiguration> streamsList = ImmutableMap.of(stream1, streamConfiguration1, stream2, streamConfiguration2);
    when(mockControllerService.listStreamsInScope(eq("scope1"), anyLong())).thenReturn(CompletableFuture.completedFuture(streamsList));
    Response response = addAuthHeaders(client.target(resourceURI).request()).buildGet().invoke();
    assertEquals("List Streams response code", 200, response.getStatus());
    assertTrue(response.bufferEntity());
    final StreamsList streamsList1 = response.readEntity(StreamsList.class);
    assertEquals("List count", streamsList1.getStreams().size(), 2);
    assertEquals("List element", streamsList1.getStreams().get(0).getStreamName(), "stream1");
    assertEquals("List element", streamsList1.getStreams().get(1).getStreamName(), "stream2");
    response.close();
    // Test for list streams for invalid scope.
    final CompletableFuture<Map<String, StreamConfiguration>> completableFuture1 = new CompletableFuture<>();
    completableFuture1.completeExceptionally(StoreException.create(StoreException.Type.DATA_NOT_FOUND, "scope1"));
    when(mockControllerService.listStreamsInScope(eq("scope1"), anyLong())).thenReturn(completableFuture1);
    response = addAuthHeaders(client.target(resourceURI).request()).buildGet().invoke();
    assertEquals("List Streams response code", 404, response.getStatus());
    response.close();
    // Test for list streams failure.
    final CompletableFuture<Map<String, StreamConfiguration>> completableFuture = new CompletableFuture<>();
    completableFuture.completeExceptionally(new Exception());
    when(mockControllerService.listStreamsInScope(eq("scope1"), anyLong())).thenReturn(completableFuture);
    response = addAuthHeaders(client.target(resourceURI).request()).buildGet().invoke();
    assertEquals("List Streams response code", 500, response.getStatus());
    response.close();
    // Test for filtering streams.
    final StreamConfiguration streamConfiguration3 = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).build();
    Map<String, StreamConfiguration> allStreamsList = ImmutableMap.of(stream1, streamConfiguration1, stream2, streamConfiguration2, NameUtils.getInternalNameForStream("stream3"), streamConfiguration3);
    when(mockControllerService.listStreamsInScope(eq("scope1"), anyLong())).thenReturn(CompletableFuture.completedFuture(allStreamsList));
    response = addAuthHeaders(client.target(resourceURI).request()).buildGet().invoke();
    assertEquals("List Streams response code", 200, response.getStatus());
    assertTrue(response.bufferEntity());
    StreamsList streamsListResp = response.readEntity(StreamsList.class);
    assertEquals("List count", 2, streamsListResp.getStreams().size());
    assertEquals("List element", "stream1", streamsListResp.getStreams().get(0).getStreamName());
    assertEquals("List element", "stream2", streamsListResp.getStreams().get(1).getStreamName());
    response.close();
    response = addAuthHeaders(client.target(resourceURI).queryParam("filter_type", "showInternalStreams").request()).buildGet().invoke();
    assertEquals("List Streams response code", 200, response.getStatus());
    assertTrue(response.bufferEntity());
    streamsListResp = response.readEntity(StreamsList.class);
    assertEquals("List count", 1, streamsListResp.getStreams().size());
    assertEquals("List element", NameUtils.getInternalNameForStream("stream3"), streamsListResp.getStreams().get(0).getStreamName());
    response.close();
    // Test for tags
    final StreamConfiguration streamConfigurationForTags = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.byEventRate(100, 2, 2)).retentionPolicy(RetentionPolicy.byTime(Duration.ofMillis(123L))).tag("testTag").build();
    List<String> tagStream = new ArrayList<>();
    tagStream.add("streamForTags");
    ImmutablePair<List<String>, String> tagPair = new ImmutablePair<>(tagStream, "");
    ImmutablePair<List<String>, String> emptyPair = new ImmutablePair<>(Collections.emptyList(), "");
    when(mockControllerService.listStreamsForTag(eq("scope1"), eq("testTag"), anyString(), anyLong())).thenReturn(CompletableFuture.completedFuture(tagPair)).thenReturn(CompletableFuture.completedFuture(emptyPair));
    when(mockControllerService.getStream(eq("scope1"), eq("streamForTags"), anyLong())).thenReturn(CompletableFuture.completedFuture(streamConfigurationForTags));
    response = addAuthHeaders(client.target(resourceURI).queryParam("filter_type", "tag").queryParam("filter_value", "testTag").request()).buildGet().invoke();
    assertEquals("List Streams response code", 200, response.getStatus());
    assertTrue(response.bufferEntity());
    final StreamsList streamsListForTags = response.readEntity(StreamsList.class);
    assertEquals("List count", streamsListForTags.getStreams().size(), 1);
    assertEquals("List element", streamsListForTags.getStreams().get(0).getStreamName(), "streamForTags");
    response.close();
    final CompletableFuture<Pair<List<String>, String>> completableFutureForTag = new CompletableFuture<>();
    completableFutureForTag.completeExceptionally(StoreException.create(StoreException.Type.DATA_NOT_FOUND, "scope1"));
    when(mockControllerService.listStreamsForTag(eq("scope1"), eq("testTag"), anyString(), anyLong())).thenReturn(completableFutureForTag);
    response = addAuthHeaders(client.target(resourceURI).queryParam("filter_type", "tag").queryParam("filter_value", "testTag").request()).buildGet().invoke();
    assertEquals("List Streams response code", 404, response.getStatus());
    response.close();
    final CompletableFuture<Pair<List<String>, String>> completableFutureForTag1 = new CompletableFuture<>();
    completableFutureForTag1.completeExceptionally(new Exception());
    when(mockControllerService.listStreamsForTag(eq("scope1"), eq("testTag"), anyString(), anyLong())).thenReturn(completableFutureForTag1);
    response = addAuthHeaders(client.target(resourceURI).queryParam("filter_type", "tag").queryParam("filter_value", "testTag").request()).buildGet().invoke();
    assertEquals("List Streams response code", 500, response.getStatus());
    response.close();
    // Test to list large number of streams.
    streamsList = new HashMap<>();
    for (int i = 0; i < 50000; i++) {
        streamsList.put("stream" + i, streamConfiguration1);
    }
    when(mockControllerService.listStreamsInScope(eq("scope1"), anyLong())).thenReturn(CompletableFuture.completedFuture(streamsList));
    response = addAuthHeaders(client.target(resourceURI).request()).buildGet().invoke();
    assertEquals("List Streams response code", 200, response.getStatus());
    assertTrue(response.bufferEntity());
    final StreamsList streamsList2 = response.readEntity(StreamsList.class);
    assertEquals("List count", 50000, streamsList2.getStreams().size());
    response.close();
}
Also used : StreamsList(io.pravega.controller.server.rest.generated.model.StreamsList) ArrayList(java.util.ArrayList) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) StoreException(io.pravega.controller.store.stream.StoreException) ExecutionException(java.util.concurrent.ExecutionException) Response(javax.ws.rs.core.Response) CompletableFuture(java.util.concurrent.CompletableFuture) ImmutablePair(org.apache.commons.lang3.tuple.ImmutablePair) StreamConfiguration(io.pravega.client.stream.StreamConfiguration) StreamsList(io.pravega.controller.server.rest.generated.model.StreamsList) List(java.util.List) ScopesList(io.pravega.controller.server.rest.generated.model.ScopesList) ArrayList(java.util.ArrayList) ReaderGroupsList(io.pravega.controller.server.rest.generated.model.ReaderGroupsList) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) Pair(org.apache.commons.lang3.tuple.Pair) ImmutablePair(org.apache.commons.lang3.tuple.ImmutablePair) Test(org.junit.Test)

Example 5 with StreamsList

use of io.pravega.controller.server.rest.generated.model.StreamsList in project pravega by pravega.

the class StreamMetadataResourceImpl method listStreams.

/**
 * Implementation of listStreams REST API.
 *
 * @param scopeName           The scope name of stream.
 * @param securityContext     The security for API access.
 * @param asyncResponse       AsyncResponse provides means for asynchronous server side response processing.
 */
@Override
public void listStreams(final String scopeName, final String filterType, final String filterValue, final SecurityContext securityContext, final AsyncResponse asyncResponse) {
    long traceId = LoggerHelpers.traceEnter(log, "listStreams");
    long requestId = requestIdGenerator.nextLong();
    final Principal principal;
    final List<String> authHeader = getAuthorizationHeader();
    try {
        principal = restAuthHelper.authenticate(authHeader);
        restAuthHelper.authorize(authHeader, authorizationResource.ofStreamsInScope(scopeName), principal, READ);
    } catch (AuthException e) {
        log.warn(requestId, "List streams for {} failed due to authentication failure.", scopeName);
        asyncResponse.resume(Response.status(Status.fromStatusCode(e.getResponseCode())).build());
        LoggerHelpers.traceLeave(log, "listStreams", traceId);
        return;
    }
    boolean showOnlyInternalStreams = filterType != null && filterType.equals("showInternalStreams");
    boolean showStreamsWithTag = filterType != null && filterType.equals("tag");
    String tag;
    if (showStreamsWithTag && filterValue != null) {
        tag = filterValue;
        List<Stream> streams = new ArrayList<>();
        String finalTag = tag;
        localController.listStreamsForTag(scopeName, tag).collectRemaining(streams::add).thenCompose(v -> {
            List<CompletableFuture<ImmutablePair<Stream, StreamConfiguration>>> streamConfigFutureList = streams.stream().filter(stream -> {
                boolean isAuthorized = false;
                try {
                    isAuthorized = restAuthHelper.isAuthorized(authHeader, authorizationResource.ofStreamInScope(scopeName, stream.getStreamName()), principal, READ);
                } catch (AuthException e) {
                    log.warn(requestId, "List Streams with tag {} for scope {} failed due to authentication failure.", finalTag, scopeName);
                // Ignore. This exception occurs under abnormal circumstances and not to determine
                // whether the user is authorized. In case it does occur, we assume that the user
                // is unauthorized.
                }
                return isAuthorized;
            }).map(stream -> localController.getStreamConfiguration(scopeName, stream.getStreamName()).thenApply(config -> new ImmutablePair<>(stream, config))).collect(Collectors.toList());
            return Futures.allOfWithResults(streamConfigFutureList);
        }).thenApply(streamConfigPairs -> {
            StreamsList responseStreams = new StreamsList();
            responseStreams.setStreams(new ArrayList<>());
            streamConfigPairs.forEach(pair -> responseStreams.addStreamsItem(ModelHelper.encodeStreamResponse(pair.left.getScope(), pair.left.getStreamName(), pair.right)));
            log.info(requestId, "Successfully fetched streams for scope: {} with tag: {}", scopeName, finalTag);
            return Response.status(Status.OK).entity(responseStreams).build();
        }).exceptionally(exception -> {
            if (exception.getCause() instanceof StoreException.DataNotFoundException || exception instanceof StoreException.DataNotFoundException) {
                log.warn(requestId, "Scope name: {} not found", scopeName);
                return Response.status(Status.NOT_FOUND).build();
            } else {
                log.warn(requestId, "listStreams for {} with tag {} failed with exception: {}", scopeName, finalTag, exception);
                return Response.status(Status.INTERNAL_SERVER_ERROR).build();
            }
        }).thenApply(asyncResponse::resume).thenAccept(x -> LoggerHelpers.traceLeave(log, "listStreams", traceId));
    } else {
        controllerService.listStreamsInScope(scopeName, requestId).thenApply(streamsList -> {
            StreamsList streams = new StreamsList();
            streams.setStreams(new ArrayList<>());
            streamsList.forEach((stream, config) -> {
                try {
                    if (restAuthHelper.isAuthorized(authHeader, authorizationResource.ofStreamInScope(scopeName, stream), principal, READ)) {
                        // otherwise display the regular user created streams.
                        if (!showOnlyInternalStreams ^ stream.startsWith(INTERNAL_NAME_PREFIX)) {
                            streams.addStreamsItem(ModelHelper.encodeStreamResponse(scopeName, stream, config));
                        }
                    }
                } catch (AuthException e) {
                    log.warn(requestId, "Read internal streams for scope {} failed due to authentication failure.", scopeName);
                // Ignore. This exception occurs under abnormal circumstances and not to determine
                // whether the user is authorized. In case it does occur, we assume that the user
                // is unauthorized.
                }
            });
            log.info(requestId, "Successfully fetched streams for scope: {}", scopeName);
            return Response.status(Status.OK).entity(streams).build();
        }).exceptionally(exception -> {
            if (exception.getCause() instanceof StoreException.DataNotFoundException || exception instanceof StoreException.DataNotFoundException) {
                log.warn(requestId, "Scope name: {} not found", scopeName);
                return Response.status(Status.NOT_FOUND).build();
            } else {
                log.warn(requestId, "listStreams for {} failed with exception: {}", scopeName, exception);
                return Response.status(Status.INTERNAL_SERVER_ERROR).build();
            }
        }).thenApply(asyncResponse::resume).thenAccept(x -> LoggerHelpers.traceLeave(log, "listStreams", traceId));
    }
}
Also used : ApiV1(io.pravega.controller.server.rest.v1.ApiV1) READ(io.pravega.auth.AuthHandler.Permissions.READ) StreamsList(io.pravega.controller.server.rest.generated.model.StreamsList) SecurityContext(javax.ws.rs.core.SecurityContext) LoggerFactory(org.slf4j.LoggerFactory) ReaderGroupManagerImpl(io.pravega.client.admin.impl.ReaderGroupManagerImpl) Random(java.util.Random) ReaderGroup(io.pravega.client.stream.ReaderGroup) StreamConfiguration(io.pravega.client.stream.StreamConfiguration) ReaderGroupNotFoundException(io.pravega.client.stream.ReaderGroupNotFoundException) TagLogger(io.pravega.common.tracing.TagLogger) RESTAuthHelper(io.pravega.shared.rest.security.RESTAuthHelper) LocalController(io.pravega.controller.server.eventProcessor.LocalController) StoreException(io.pravega.controller.store.stream.StoreException) ClientFactoryImpl(io.pravega.client.stream.impl.ClientFactoryImpl) ReaderGroupManager(io.pravega.client.admin.ReaderGroupManager) Stream(io.pravega.client.stream.Stream) ReaderGroupProperty(io.pravega.controller.server.rest.generated.model.ReaderGroupProperty) INTERNAL_NAME_PREFIX(io.pravega.shared.NameUtils.INTERNAL_NAME_PREFIX) DeleteScopeStatus(io.pravega.controller.stream.api.grpc.v1.Controller.DeleteScopeStatus) CreateStreamStatus(io.pravega.controller.stream.api.grpc.v1.Controller.CreateStreamStatus) AuthorizationResource(io.pravega.shared.security.auth.AuthorizationResource) Context(javax.ws.rs.core.Context) AsyncResponse(javax.ws.rs.container.AsyncResponse) CreateScopeRequest(io.pravega.controller.server.rest.generated.model.CreateScopeRequest) Collectors(java.util.stream.Collectors) CreateStreamRequest(io.pravega.controller.server.rest.generated.model.CreateStreamRequest) READER_GROUP_STREAM_PREFIX(io.pravega.shared.NameUtils.READER_GROUP_STREAM_PREFIX) List(java.util.List) Principal(java.security.Principal) HttpHeaders(javax.ws.rs.core.HttpHeaders) StreamState(io.pravega.controller.server.rest.generated.model.StreamState) Response(javax.ws.rs.core.Response) ScopesList(io.pravega.controller.server.rest.generated.model.ScopesList) Futures(io.pravega.common.concurrent.Futures) AuthException(io.pravega.auth.AuthException) CreateScopeStatus(io.pravega.controller.stream.api.grpc.v1.Controller.CreateScopeStatus) ConnectionFactory(io.pravega.client.connection.impl.ConnectionFactory) CompletableFuture(java.util.concurrent.CompletableFuture) UpdateStreamRequest(io.pravega.controller.server.rest.generated.model.UpdateStreamRequest) ArrayList(java.util.ArrayList) READ_UPDATE(io.pravega.auth.AuthHandler.Permissions.READ_UPDATE) ScaleMetadata(io.pravega.controller.store.stream.ScaleMetadata) DeleteStreamStatus(io.pravega.controller.stream.api.grpc.v1.Controller.DeleteStreamStatus) Status(javax.ws.rs.core.Response.Status) AuthorizationResourceImpl(io.pravega.shared.security.auth.AuthorizationResourceImpl) LoggerHelpers(io.pravega.common.LoggerHelpers) ControllerService(io.pravega.controller.server.ControllerService) NameUtils(io.pravega.shared.NameUtils) Iterator(java.util.Iterator) ScopeProperty(io.pravega.controller.server.rest.generated.model.ScopeProperty) ImmutablePair(org.apache.commons.lang3.tuple.ImmutablePair) ModelHelper(io.pravega.controller.server.rest.ModelHelper) ReaderGroupsList(io.pravega.controller.server.rest.generated.model.ReaderGroupsList) AuthHandlerManager(io.pravega.shared.rest.security.AuthHandlerManager) ReaderGroupsListReaderGroups(io.pravega.controller.server.rest.generated.model.ReaderGroupsListReaderGroups) UpdateStreamStatus(io.pravega.controller.stream.api.grpc.v1.Controller.UpdateStreamStatus) ClientConfig(io.pravega.client.ClientConfig) StreamsList(io.pravega.controller.server.rest.generated.model.StreamsList) ArrayList(java.util.ArrayList) AuthException(io.pravega.auth.AuthException) StoreException(io.pravega.controller.store.stream.StoreException) CompletableFuture(java.util.concurrent.CompletableFuture) StreamConfiguration(io.pravega.client.stream.StreamConfiguration) Stream(io.pravega.client.stream.Stream) Principal(java.security.Principal)

Aggregations

StreamConfiguration (io.pravega.client.stream.StreamConfiguration)6 StreamsList (io.pravega.controller.server.rest.generated.model.StreamsList)6 Response (javax.ws.rs.core.Response)6 ReaderGroupsList (io.pravega.controller.server.rest.generated.model.ReaderGroupsList)3 ScopesList (io.pravega.controller.server.rest.generated.model.ScopesList)3 StoreException (io.pravega.controller.store.stream.StoreException)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 ImmutablePair (org.apache.commons.lang3.tuple.ImmutablePair)3 AuthException (io.pravega.auth.AuthException)2 AuthFileUtils.credentialsAndAclAsString (io.pravega.auth.AuthFileUtils.credentialsAndAclAsString)2 READ (io.pravega.auth.AuthHandler.Permissions.READ)2 READ_UPDATE (io.pravega.auth.AuthHandler.Permissions.READ_UPDATE)2 ClientConfig (io.pravega.client.ClientConfig)2 ReaderGroupManager (io.pravega.client.admin.ReaderGroupManager)2 ReaderGroupManagerImpl (io.pravega.client.admin.impl.ReaderGroupManagerImpl)2 ConnectionFactory (io.pravega.client.connection.impl.ConnectionFactory)2 ReaderGroup (io.pravega.client.stream.ReaderGroup)2 ReaderGroupNotFoundException (io.pravega.client.stream.ReaderGroupNotFoundException)2