use of com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe 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;
});
}
use of com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe in project pulsar by yahoo.
the class Commands method newSubscribe.
public static ByteBuf newSubscribe(String topic, String subscription, long consumerId, long requestId, SubType subType, int priorityLevel, String consumerName) {
CommandSubscribe.Builder subscribeBuilder = CommandSubscribe.newBuilder();
subscribeBuilder.setTopic(topic);
subscribeBuilder.setSubscription(subscription);
subscribeBuilder.setSubType(subType);
subscribeBuilder.setConsumerId(consumerId);
subscribeBuilder.setConsumerName(consumerName);
subscribeBuilder.setRequestId(requestId);
subscribeBuilder.setPriorityLevel(priorityLevel);
CommandSubscribe subscribe = subscribeBuilder.build();
ByteBuf res = serializeWithSize(BaseCommand.newBuilder().setType(Type.SUBSCRIBE).setSubscribe(subscribe));
subscribeBuilder.recycle();
subscribe.recycle();
return res;
}
use of com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe in project pulsar by yahoo.
the class PersistentTopicTest method testDeleteTopicRaceConditions.
@Test
public void testDeleteTopicRaceConditions() throws Exception {
PersistentTopic topic = (PersistentTopic) brokerService.getTopic(successTopicName).get();
// override ledger deletion callback to slow down deletion
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
Thread.sleep(1000);
((DeleteLedgerCallback) invocationOnMock.getArguments()[0]).deleteLedgerComplete(null);
return null;
}
}).when(ledgerMock).asyncDelete(any(DeleteLedgerCallback.class), anyObject());
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
topic.delete();
return null;
}).get();
try {
String role = "appid1";
Thread.sleep(10);
/* delay to ensure that the delete gets executed first */
Producer producer = new Producer(topic, serverCnx, 1, /* producer id */
"prod-name", role);
topic.addProducer(producer);
fail("Should have failed");
} catch (BrokerServiceException e) {
assertTrue(e instanceof BrokerServiceException.TopicFencedException);
}
CommandSubscribe cmd = CommandSubscribe.newBuilder().setConsumerId(1).setTopic(successTopicName).setSubscription(successSubName).setRequestId(1).setSubType(SubType.Exclusive).build();
Future<Consumer> f = topic.subscribe(serverCnx, cmd.getSubscription(), cmd.getConsumerId(), cmd.getSubType(), 0, cmd.getConsumerName());
try {
f.get();
fail("should have failed");
} catch (ExecutionException ee) {
assertTrue(ee.getCause() instanceof BrokerServiceException.TopicFencedException);
// Expected
}
}
use of com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe in project pulsar by yahoo.
the class PersistentTopicTest method testDeleteTopic.
@Test
public void testDeleteTopic() throws Exception {
// create topic
PersistentTopic topic = (PersistentTopic) brokerService.getTopic(successTopicName).get();
String role = "appid1";
// 1. delete inactive topic
topic.delete().get();
assertNull(brokerService.getTopicReference(successTopicName));
// 2. delete topic with producer
topic = (PersistentTopic) brokerService.getTopic(successTopicName).get();
Producer producer = new Producer(topic, serverCnx, 1, /* producer id */
"prod-name", role);
topic.addProducer(producer);
assertTrue(topic.delete().isCompletedExceptionally());
topic.removeProducer(producer);
// 3. delete topic with subscriber
CommandSubscribe cmd = CommandSubscribe.newBuilder().setConsumerId(1).setTopic(successTopicName).setSubscription(successSubName).setRequestId(1).setSubType(SubType.Exclusive).build();
Future<Consumer> f1 = topic.subscribe(serverCnx, cmd.getSubscription(), cmd.getConsumerId(), cmd.getSubType(), 0, cmd.getConsumerName());
f1.get();
assertTrue(topic.delete().isCompletedExceptionally());
topic.unsubscribe(successSubName);
}
use of com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe in project pulsar by yahoo.
the class PersistentTopicTest method testDeleteAndUnsubscribeTopic.
@Test
public void testDeleteAndUnsubscribeTopic() throws Exception {
// create topic
final PersistentTopic topic = (PersistentTopic) brokerService.getTopic(successTopicName).get();
CommandSubscribe cmd = CommandSubscribe.newBuilder().setConsumerId(1).setTopic(successTopicName).setSubscription(successSubName).setRequestId(1).setSubType(SubType.Exclusive).build();
Future<Consumer> f1 = topic.subscribe(serverCnx, cmd.getSubscription(), cmd.getConsumerId(), cmd.getSubType(), 0, cmd.getConsumerName());
f1.get();
final CyclicBarrier barrier = new CyclicBarrier(2);
final CountDownLatch counter = new CountDownLatch(2);
final AtomicBoolean gotException = new AtomicBoolean(false);
Thread deleter = new Thread() {
@Override
public void run() {
try {
barrier.await();
assertFalse(topic.delete().isCompletedExceptionally());
} catch (Exception e) {
e.printStackTrace();
gotException.set(true);
} finally {
counter.countDown();
}
}
};
Thread unsubscriber = new Thread() {
@Override
public void run() {
try {
barrier.await();
// do topic unsubscribe
topic.unsubscribe(successSubName);
} catch (Exception e) {
e.printStackTrace();
gotException.set(true);
} finally {
counter.countDown();
}
}
};
deleter.start();
unsubscriber.start();
counter.await();
assertEquals(gotException.get(), false);
}
Aggregations