Search in sources :

Example 1 with ServerError

use of com.yahoo.pulsar.common.api.proto.PulsarApi.ServerError in project pulsar by yahoo.

the class ServerCnx method handleSubscribe.

@Override
protected void handleSubscribe(final CommandSubscribe subscribe) {
    checkArgument(state == State.Connected);
    CompletableFuture<Boolean> authorizationFuture;
    if (service.isAuthorizationEnabled()) {
        authorizationFuture = service.getAuthorizationManager().canConsumeAsync(DestinationName.get(subscribe.getTopic()), authRole);
    } else {
        authorizationFuture = CompletableFuture.completedFuture(true);
    }
    final String topicName = subscribe.getTopic();
    final String subscriptionName = subscribe.getSubscription();
    final long requestId = subscribe.getRequestId();
    final long consumerId = subscribe.getConsumerId();
    final SubType subType = subscribe.getSubType();
    final String consumerName = subscribe.getConsumerName();
    final int priorityLevel = subscribe.hasPriorityLevel() ? subscribe.getPriorityLevel() : 0;
    authorizationFuture.thenApply(isAuthorized -> {
        if (isAuthorized) {
            if (log.isDebugEnabled()) {
                log.debug("[{}] Client is authorized to subscribe with role {}", remoteAddress, authRole);
            }
            log.info("[{}] Subscribing on topic {} / {}", remoteAddress, topicName, subscriptionName);
            CompletableFuture<Consumer> consumerFuture = new CompletableFuture<>();
            CompletableFuture<Consumer> existingConsumerFuture = consumers.putIfAbsent(consumerId, consumerFuture);
            if (existingConsumerFuture != null) {
                if (existingConsumerFuture.isDone() && !existingConsumerFuture.isCompletedExceptionally()) {
                    Consumer consumer = existingConsumerFuture.getNow(null);
                    log.info("[{}] Consumer with the same id is already created: {}", remoteAddress, consumer);
                    ctx.writeAndFlush(Commands.newSuccess(requestId));
                    return null;
                } else {
                    log.warn("[{}][{}][{}] Consumer is already present on the connection", remoteAddress, topicName, subscriptionName);
                    ServerError error = !existingConsumerFuture.isDone() ? ServerError.ServiceNotReady : getErrorCode(existingConsumerFuture);
                    ;
                    ctx.writeAndFlush(Commands.newError(requestId, error, "Consumer is already present on the connection"));
                    return null;
                }
            }
            service.getTopic(topicName).thenCompose(topic -> topic.subscribe(ServerCnx.this, subscriptionName, consumerId, subType, priorityLevel, consumerName)).thenAccept(consumer -> {
                if (consumerFuture.complete(consumer)) {
                    log.info("[{}] Created subscription on topic {} / {}", remoteAddress, topicName, subscriptionName);
                    ctx.writeAndFlush(Commands.newSuccess(requestId), ctx.voidPromise());
                } else {
                    try {
                        consumer.close();
                        log.info("[{}] Cleared consumer created after timeout on client side {}", remoteAddress, consumer);
                    } catch (BrokerServiceException e) {
                        log.warn("[{}] Error closing consumer created after timeout on client side {}: {}", remoteAddress, consumer, e.getMessage());
                    }
                    consumers.remove(consumerId, consumerFuture);
                }
            }).exceptionally(exception -> {
                log.warn("[{}][{}][{}] Failed to create consumer: {}", remoteAddress, topicName, subscriptionName, exception.getCause().getMessage());
                if (consumerFuture.completeExceptionally(exception)) {
                    ctx.writeAndFlush(Commands.newError(requestId, BrokerServiceException.getClientErrorCode(exception.getCause()), exception.getCause().getMessage()));
                }
                consumers.remove(consumerId, consumerFuture);
                return null;
            });
        } else {
            String msg = "Client is not authorized to subscribe";
            log.warn("[{}] {} with role {}", remoteAddress, msg, authRole);
            ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, msg));
        }
        return null;
    });
}
Also used : SubType(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe.SubType) CommandProducer(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandProducer) ServerError(com.yahoo.pulsar.common.api.proto.PulsarApi.ServerError) ProtocolVersion.v5(com.yahoo.pulsar.common.api.proto.PulsarApi.ProtocolVersion.v5) SocketAddress(java.net.SocketAddress) ChannelOption(io.netty.channel.ChannelOption) ConsumerStats(com.yahoo.pulsar.common.policies.data.ConsumerStats) LoggerFactory(org.slf4j.LoggerFactory) CompletableFuture(java.util.concurrent.CompletableFuture) CommandConsumerStats(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandConsumerStats) AuthenticationException(javax.naming.AuthenticationException) CommandUnsubscribe(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandUnsubscribe) BacklogQuota(com.yahoo.pulsar.common.policies.data.BacklogQuota) PersistentTopics.getPartitionedTopicMetadata(com.yahoo.pulsar.broker.admin.PersistentTopics.getPartitionedTopicMetadata) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) SSLSession(javax.net.ssl.SSLSession) CommandCloseProducer(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandCloseProducer) ByteBuf(io.netty.buffer.ByteBuf) Commands(com.yahoo.pulsar.common.api.Commands) DestinationName(com.yahoo.pulsar.common.naming.DestinationName) AuthenticationDataCommand(com.yahoo.pulsar.broker.authentication.AuthenticationDataCommand) CommandRedeliverUnacknowledgedMessages(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandRedeliverUnacknowledgedMessages) Logger(org.slf4j.Logger) PersistentSubscription(com.yahoo.pulsar.broker.service.persistent.PersistentSubscription) CommandSend(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSend) Commands.newLookupResponse(com.yahoo.pulsar.common.api.Commands.newLookupResponse) PulsarHandler(com.yahoo.pulsar.common.api.PulsarHandler) DestinationLookup.lookupDestinationAsync(com.yahoo.pulsar.broker.lookup.DestinationLookup.lookupDestinationAsync) ServiceUnitNotReadyException(com.yahoo.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException) TimeUnit(java.util.concurrent.TimeUnit) CommandAck(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandAck) ProtocolVersion(com.yahoo.pulsar.common.api.proto.PulsarApi.ProtocolVersion) CommandPartitionedTopicMetadata(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandPartitionedTopicMetadata) MessageMetadata(com.yahoo.pulsar.common.api.proto.PulsarApi.MessageMetadata) SslHandler(io.netty.handler.ssl.SslHandler) CommandFlow(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandFlow) ConcurrentLongHashMap(com.yahoo.pulsar.common.util.collections.ConcurrentLongHashMap) PersistentTopic(com.yahoo.pulsar.broker.service.persistent.PersistentTopic) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException) CommandConnect(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandConnect) CommandLookupTopic(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandLookupTopic) CommandSubscribe(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe) ChannelHandler(io.netty.channel.ChannelHandler) CommandCloseConsumer(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandCloseConsumer) CommandConsumerStatsResponse(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandConsumerStatsResponse) CompletableFuture(java.util.concurrent.CompletableFuture) SubType(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe.SubType) CommandCloseConsumer(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandCloseConsumer) ServerError(com.yahoo.pulsar.common.api.proto.PulsarApi.ServerError)

Example 2 with ServerError

use of com.yahoo.pulsar.common.api.proto.PulsarApi.ServerError in project pulsar by yahoo.

the class ServerCnx method handleProducer.

@Override
protected void handleProducer(final CommandProducer cmdProducer) {
    checkArgument(state == State.Connected);
    CompletableFuture<Boolean> authorizationFuture;
    if (service.isAuthorizationEnabled()) {
        authorizationFuture = service.getAuthorizationManager().canProduceAsync(DestinationName.get(cmdProducer.getTopic().toString()), authRole);
    } else {
        authorizationFuture = CompletableFuture.completedFuture(true);
    }
    // Use producer name provided by client if present
    final String producerName = cmdProducer.hasProducerName() ? cmdProducer.getProducerName() : service.generateUniqueProducerName();
    final String topicName = cmdProducer.getTopic();
    final long producerId = cmdProducer.getProducerId();
    final long requestId = cmdProducer.getRequestId();
    authorizationFuture.thenApply(isAuthorized -> {
        if (isAuthorized) {
            if (log.isDebugEnabled()) {
                log.debug("[{}] Client is authorized to Produce with role {}", remoteAddress, authRole);
            }
            CompletableFuture<Producer> producerFuture = new CompletableFuture<>();
            CompletableFuture<Producer> existingProducerFuture = producers.putIfAbsent(producerId, producerFuture);
            if (existingProducerFuture != null) {
                if (existingProducerFuture.isDone() && !existingProducerFuture.isCompletedExceptionally()) {
                    Producer producer = existingProducerFuture.getNow(null);
                    log.info("[{}] Producer with the same id is already created: {}", remoteAddress, producer);
                    ctx.writeAndFlush(Commands.newProducerSuccess(requestId, producer.getProducerName()));
                    return null;
                } else {
                    ServerError error = !existingProducerFuture.isDone() ? ServerError.ServiceNotReady : getErrorCode(existingProducerFuture);
                    log.warn("[{}][{}] Producer is already present on the connection", remoteAddress, topicName);
                    ctx.writeAndFlush(Commands.newError(requestId, error, "Producer is already present on the connection"));
                    return null;
                }
            }
            log.info("[{}][{}] Creating producer. producerId={}", remoteAddress, topicName, producerId);
            service.getTopic(topicName).thenAccept((Topic topic) -> {
                if (topic.isBacklogQuotaExceeded(producerName)) {
                    IllegalStateException illegalStateException = new IllegalStateException("Cannot create producer on topic with backlog quota exceeded");
                    BacklogQuota.RetentionPolicy retentionPolicy = topic.getBacklogQuota().getPolicy();
                    if (retentionPolicy == BacklogQuota.RetentionPolicy.producer_request_hold) {
                        ctx.writeAndFlush(Commands.newError(requestId, ServerError.ProducerBlockedQuotaExceededError, illegalStateException.getMessage()));
                    } else if (retentionPolicy == BacklogQuota.RetentionPolicy.producer_exception) {
                        ctx.writeAndFlush(Commands.newError(requestId, ServerError.ProducerBlockedQuotaExceededException, illegalStateException.getMessage()));
                    }
                    producerFuture.completeExceptionally(illegalStateException);
                    producers.remove(producerId, producerFuture);
                    return;
                }
                disableTcpNoDelayIfNeeded(topicName, producerName);
                Producer producer = new Producer(topic, ServerCnx.this, producerId, producerName, authRole);
                try {
                    topic.addProducer(producer);
                    if (isActive()) {
                        if (producerFuture.complete(producer)) {
                            log.info("[{}] Created new producer: {}", remoteAddress, producer);
                            ctx.writeAndFlush(Commands.newProducerSuccess(requestId, producerName));
                            return;
                        } else {
                            producer.closeNow();
                            log.info("[{}] Cleared producer created after timeout on client side {}", remoteAddress, producer);
                        }
                    } else {
                        producer.closeNow();
                        log.info("[{}] Cleared producer created after connection was closed: {}", remoteAddress, producer);
                        producerFuture.completeExceptionally(new IllegalStateException("Producer created after connection was closed"));
                    }
                } catch (BrokerServiceException ise) {
                    log.error("[{}] Failed to add producer to topic {}: {}", remoteAddress, topicName, ise.getMessage());
                    ctx.writeAndFlush(Commands.newError(requestId, BrokerServiceException.getClientErrorCode(ise), ise.getMessage()));
                    producerFuture.completeExceptionally(ise);
                }
                producers.remove(producerId, producerFuture);
            }).exceptionally(exception -> {
                Throwable cause = exception.getCause();
                if (!(cause instanceof ServiceUnitNotReadyException)) {
                    log.error("[{}] Failed to create topic {}", remoteAddress, topicName, exception);
                }
                if (producerFuture.completeExceptionally(exception)) {
                    ctx.writeAndFlush(Commands.newError(requestId, BrokerServiceException.getClientErrorCode(cause), cause.getMessage()));
                }
                producers.remove(producerId, producerFuture);
                return null;
            });
        } else {
            String msg = "Client is not authorized to Produce";
            log.warn("[{}] {} with role {}", remoteAddress, msg, authRole);
            ctx.writeAndFlush(Commands.newError(requestId, ServerError.AuthorizationError, msg));
        }
        return null;
    });
}
Also used : ServerError(com.yahoo.pulsar.common.api.proto.PulsarApi.ServerError) ServiceUnitNotReadyException(com.yahoo.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException) CompletableFuture(java.util.concurrent.CompletableFuture) CommandProducer(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandProducer) CommandCloseProducer(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandCloseProducer) PersistentTopic(com.yahoo.pulsar.broker.service.persistent.PersistentTopic) CommandLookupTopic(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandLookupTopic)

Aggregations

ServiceUnitNotReadyException (com.yahoo.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException)2 PersistentTopic (com.yahoo.pulsar.broker.service.persistent.PersistentTopic)2 CommandCloseProducer (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandCloseProducer)2 CommandLookupTopic (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandLookupTopic)2 CommandProducer (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandProducer)2 ServerError (com.yahoo.pulsar.common.api.proto.PulsarApi.ServerError)2 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 PersistentTopics.getPartitionedTopicMetadata (com.yahoo.pulsar.broker.admin.PersistentTopics.getPartitionedTopicMetadata)1 AuthenticationDataCommand (com.yahoo.pulsar.broker.authentication.AuthenticationDataCommand)1 DestinationLookup.lookupDestinationAsync (com.yahoo.pulsar.broker.lookup.DestinationLookup.lookupDestinationAsync)1 PersistentSubscription (com.yahoo.pulsar.broker.service.persistent.PersistentSubscription)1 PulsarClientException (com.yahoo.pulsar.client.api.PulsarClientException)1 Commands (com.yahoo.pulsar.common.api.Commands)1 Commands.newLookupResponse (com.yahoo.pulsar.common.api.Commands.newLookupResponse)1 PulsarHandler (com.yahoo.pulsar.common.api.PulsarHandler)1 CommandAck (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandAck)1 CommandCloseConsumer (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandCloseConsumer)1 CommandConnect (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandConnect)1 CommandConsumerStats (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandConsumerStats)1 CommandConsumerStatsResponse (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandConsumerStatsResponse)1