io.nats.client.impl.NatsSubscription Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jnats Show documentation
Show all versions of jnats Show documentation
Client library for working with the NATS messaging system.
// Copyright 2015-2018 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io.nats.client.impl;
import io.nats.client.Dispatcher;
import io.nats.client.Message;
import io.nats.client.MessageHandler;
import io.nats.client.Subscription;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
class NatsSubscription extends NatsConsumer implements Subscription {
private String subject;
private final String queueName;
private String sid;
private NatsDispatcher dispatcher;
private MessageQueue incoming;
private final AtomicLong unSubMessageLimit;
private Function beforeQueueProcessor;
NatsSubscription(String sid, String subject, String queueName, NatsConnection connection, NatsDispatcher dispatcher) {
super(connection);
this.subject = subject;
this.queueName = queueName;
this.sid = sid;
this.dispatcher = dispatcher;
this.unSubMessageLimit = new AtomicLong(-1);
if (this.dispatcher == null) {
this.incoming = new MessageQueue(false, connection.getOptions().getRequestCleanupInterval());
}
setBeforeQueueProcessor(null);
}
void reSubscribe(String newDeliverSubject) {
connection.sendUnsub(this, 0);
if (dispatcher == null) {
connection.remove(this);
sid = connection.reSubscribe(this, newDeliverSubject, queueName);
}
else {
MessageHandler handler = dispatcher.getSubscriptionHandlers().get(sid);
dispatcher.remove(this);
sid = dispatcher.reSubscribe(this, newDeliverSubject, queueName, handler);
}
subject = newDeliverSubject;
}
public boolean isActive() {
return (this.dispatcher != null || this.incoming != null);
}
void setBeforeQueueProcessor(Function beforeQueueProcessor) {
this.beforeQueueProcessor = beforeQueueProcessor == null ? m -> true : beforeQueueProcessor;
}
public Function getBeforeQueueProcessor() {
return beforeQueueProcessor;
}
void invalidate() {
if (this.incoming != null) {
this.incoming.pause();
}
this.dispatcher = null;
this.incoming = null;
}
void setUnsubLimit(long cd) {
this.unSubMessageLimit.set(cd);
}
boolean reachedUnsubLimit() {
long max = this.unSubMessageLimit.get();
long recv = this.getDeliveredCount();
return (max > 0) && (max <= recv);
}
String getSID() {
return this.sid;
}
NatsDispatcher getNatsDispatcher() {
return this.dispatcher;
}
/**
* {@inheritDoc}
*/
@Override
MessageQueue getMessageQueue() {
return this.incoming;
}
/**
* {@inheritDoc}
*/
@Override
public Dispatcher getDispatcher() {
return this.dispatcher;
}
/**
* {@inheritDoc}
*/
@Override
public String getSubject() {
return this.subject;
}
/**
* {@inheritDoc}
*/
@Override
public String getQueueName() {
return this.queueName;
}
@Override
public Message nextMessage(long timeoutMillis) throws InterruptedException, IllegalStateException {
return nextMessageInternal(Duration.ofMillis(timeoutMillis));
}
/**
* {@inheritDoc}
*/
@Override
public Message nextMessage(Duration timeout) throws InterruptedException, IllegalStateException {
return nextMessageInternal(timeout);
}
protected NatsMessage nextMessageInternal(Duration timeout) throws InterruptedException {
if (this.dispatcher != null) {
throw new IllegalStateException(
"Subscriptions that belong to a dispatcher cannot respond to nextMessage directly.");
} else if (this.incoming == null) {
throw new IllegalStateException("This subscription is inactive.");
}
NatsMessage msg = incoming.pop(timeout);
if (this.incoming == null || !this.incoming.isRunning()) { // We were unsubscribed while waiting
throw new IllegalStateException("This subscription became inactive.");
}
if (msg != null) {
this.incrementDeliveredCount();
}
if (this.reachedUnsubLimit()) {
this.connection.invalidate(this);
}
return msg;
}
/**
* {@inheritDoc}
*/
@Override
public void unsubscribe() {
if (this.dispatcher != null) {
throw new IllegalStateException(
"Subscriptions that belong to a dispatcher cannot respond to unsubscribe directly.");
} else if (this.incoming == null) {
throw new IllegalStateException("This subscription is inactive.");
}
if (isDraining()) { // No op while draining
return;
}
this.connection.unsubscribe(this, -1);
}
/**
* {@inheritDoc}
*/
@Override
public Subscription unsubscribe(int after) {
if (this.dispatcher != null) {
throw new IllegalStateException(
"Subscriptions that belong to a dispatcher cannot respond to unsubscribe directly.");
} else if (this.incoming == null) {
throw new IllegalStateException("This subscription is inactive.");
}
if (isDraining()) { // No op while draining
return this;
}
this.connection.unsubscribe(this, after);
return this;
}
/**
* {@inheritDoc}
*/
@Override
void sendUnsubForDrain() {
this.connection.sendUnsub(this, -1);
}
/**
* {@inheritDoc}
*/
@Override
void cleanUpAfterDrain() {
this.connection.invalidate(this);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy