use of org.reactivestreams.Subscriber in project camel by apache.
the class EventTypeTest method testOnErrorHeaderNotForwarded.
@Test
public void testOnErrorHeaderNotForwarded() throws Exception {
new RouteBuilder() {
@Override
public void configure() throws Exception {
from("reactive-streams:numbers").to("mock:endpoint");
}
}.addRoutesToCamelContext(context);
Subscriber<Integer> numbers = CamelReactiveStreams.get(context).streamSubscriber("numbers", Integer.class);
context.start();
RuntimeException ex = new RuntimeException("1");
Flowable.just(1).map(n -> {
if (n == 1) {
throw ex;
}
return n;
}).subscribe(numbers);
MockEndpoint endpoint = getMockEndpoint("mock:endpoint");
endpoint.expectedMessageCount(0);
endpoint.assertIsSatisfied(200);
}
use of org.reactivestreams.Subscriber in project ratpack by ratpack.
the class DefaultResponseTransmitter method transmitter.
@Override
public Subscriber<ByteBuf> transmitter(HttpResponseStatus responseStatus) {
return new Subscriber<ByteBuf>() {
private Subscription subscription;
private final AtomicBoolean done = new AtomicBoolean();
private final ChannelFutureListener cancelOnFailure = future -> {
if (!future.isSuccess()) {
cancel();
}
};
private final GenericFutureListener<Future<? super Void>> cancelOnCloseListener = c -> cancel();
private void cancel() {
channel.closeFuture().removeListener(cancelOnCloseListener);
if (done.compareAndSet(false, true)) {
subscription.cancel();
post(responseStatus);
}
}
@Override
public void onSubscribe(Subscription subscription) {
if (subscription == null) {
throw new NullPointerException("'subscription' is null");
}
if (this.subscription != null) {
subscription.cancel();
return;
}
this.subscription = subscription;
ChannelFuture channelFuture = pre(responseStatus, true);
if (channelFuture == null) {
subscription.cancel();
isKeepAlive = false;
notifyListeners(responseStatus);
} else {
channelFuture.addListener(f -> {
if (f.isSuccess() && channel.isOpen()) {
channel.closeFuture().addListener(cancelOnCloseListener);
if (channel.isWritable()) {
this.subscription.request(1);
}
onWritabilityChanged = () -> {
if (channel.isWritable() && !done.get()) {
this.subscription.request(1);
}
};
} else {
cancel();
}
});
}
}
@Override
public void onNext(ByteBuf o) {
o.touch();
if (channel.isOpen()) {
channel.writeAndFlush(new DefaultHttpContent(o)).addListener(cancelOnFailure);
if (channel.isWritable()) {
subscription.request(1);
}
} else {
o.release();
cancel();
}
}
@Override
public void onError(Throwable t) {
if (t == null) {
throw new NullPointerException("error is null");
}
LOGGER.warn("Exception thrown transmitting stream", t);
if (done.compareAndSet(false, true)) {
channel.closeFuture().removeListener(cancelOnCloseListener);
post(responseStatus);
}
}
@Override
public void onComplete() {
if (done.compareAndSet(false, true)) {
channel.closeFuture().removeListener(cancelOnCloseListener);
post(responseStatus);
}
}
};
}
use of org.reactivestreams.Subscriber in project ratpack by ratpack.
the class ExecutionBoundPublisher method subscribe.
@Override
public void subscribe(Subscriber<? super T> subscriber) {
DefaultExecution execution = DefaultExecution.require();
execution.delimitStream(subscriber::onError, continuation -> publisher.subscribe(new Subscriber<T>() {
private Subscription subscription;
private final AtomicBoolean cancelled = new AtomicBoolean();
private final AtomicBoolean pendingCancelSignal = new AtomicBoolean(true);
private boolean dispatch(Block block) {
if (cancelled.get()) {
return false;
} else if (execution.isBound()) {
try {
block.execute();
return true;
} catch (Exception e) {
// really should not happen
throw Exceptions.uncheck(e);
}
} else {
return continuation.event(block);
}
}
@Override
public void onSubscribe(final Subscription subscription) {
this.subscription = subscription;
dispatch(() -> subscriber.onSubscribe(new Subscription() {
@Override
public void request(long n) {
dispatch(() -> subscription.request(n));
}
@Override
public void cancel() {
if (cancelled.compareAndSet(false, true)) {
if (execution.isBound()) {
subscription.cancel();
continuation.complete(Block.noop());
} else {
pendingCancelSignal.set(true);
continuation.complete(() -> {
if (pendingCancelSignal.compareAndSet(true, false)) {
subscription.cancel();
}
});
}
}
}
}));
}
@Override
public void onNext(final T element) {
boolean added = dispatch(() -> {
if (cancelled.get()) {
dispose(element);
} else {
subscriber.onNext(element);
}
});
if (!added) {
dispose(element);
if (cancelled.get()) {
if (execution.isBound() && pendingCancelSignal.compareAndSet(true, false)) {
subscription.cancel();
continuation.complete(Block.noop());
}
}
}
}
private void dispose(T element) {
try {
disposer.execute(element);
} catch (Exception e) {
DefaultExecution.LOGGER.warn("Exception raised disposing stream item will be ignored - ", e);
}
}
@Override
public void onComplete() {
continuation.complete(() -> {
if (!cancelled.get()) {
subscriber.onComplete();
}
});
}
@Override
public void onError(final Throwable cause) {
if (!cancelled.get()) {
continuation.complete(() -> subscriber.onError(cause));
}
}
}));
}
use of org.reactivestreams.Subscriber in project ratpack by ratpack.
the class FanOutPublisher method subscribe.
@Override
public void subscribe(Subscriber<? super T> s) {
s.onSubscribe(new ManagedSubscription<T>(s, disposer) {
Iterator<? extends T> iterator;
Subscription subscription;
AtomicReference<State> state = new AtomicReference<>(State.UNSUBSCRIBED);
@Override
protected void onRequest(long n) {
if (state.compareAndSet(State.UNSUBSCRIBED, State.PENDING_SUBSCRIBE)) {
publisher.subscribe(new Subscriber<Iterable<? extends T>>() {
@Override
public void onSubscribe(Subscription s) {
subscription = s;
state.set(State.REQUESTED);
s.request(1);
}
@Override
public void onNext(Iterable<? extends T> ts) {
iterator = ts.iterator();
state.set(State.IDLE);
drain();
}
@Override
public void onError(Throwable t) {
emitError(t);
drain();
}
@Override
public void onComplete() {
subscription = null;
state.compareAndSet(State.REQUESTED, State.IDLE);
drain();
}
});
} else if (iterator != null) {
drain();
}
}
private void drain() {
if (state.compareAndSet(State.IDLE, State.EMITTING)) {
if (isDone()) {
if (iterator != null) {
while (iterator.hasNext()) {
dispose(iterator.next());
}
}
return;
}
boolean hasNext = false;
if (iterator != null) {
while ((hasNext = iterator.hasNext()) && shouldEmit()) {
emitNext(iterator.next());
}
}
if (!hasNext) {
// iterator is empty
if (subscription == null) {
emitComplete();
} else if (hasDemand()) {
state.set(State.REQUESTED);
subscription.request(1);
return;
}
}
state.set(State.IDLE);
if (hasDemand() || isDone()) {
drain();
}
}
}
@Override
protected void onCancel() {
if (subscription != null) {
subscription.cancel();
}
}
});
}
use of org.reactivestreams.Subscriber in project ratpack by ratpack.
the class FlattenPublisher method subscribe.
@Override
public void subscribe(Subscriber<? super T> subscriber) {
subscriber.onSubscribe(new ManagedSubscription<T>(subscriber, disposer) {
private Subscription outerSubscription;
private Subscription innerSubscription;
private final AtomicReference<State> state = new AtomicReference<>(State.INIT);
volatile boolean pendingComplete;
@Override
protected void onRequest(long n) {
if (state.compareAndSet(State.INIT, State.SUBSCRIBE)) {
if (outerSubscription == null) {
subscribeUpstream();
}
} else if (innerSubscription != null) {
innerSubscription.request(n);
} else {
nextPublisher();
}
}
private void subscribeUpstream() {
publisher.subscribe(new Subscriber<Publisher<T>>() {
@Override
public void onSubscribe(Subscription subscription) {
outerSubscription = subscription;
outerSubscription.request(1);
}
@Override
public void onNext(Publisher<T> next) {
next.subscribe(new Subscriber<T>() {
@Override
public void onSubscribe(Subscription s) {
innerSubscription = s;
state.set(State.EMITTING);
innerSubscription.request(getDemand());
}
@Override
public void onNext(T t) {
emitNext(t);
}
@Override
public void onError(Throwable t) {
outerSubscription.cancel();
emitError(t);
}
@Override
public void onComplete() {
innerSubscription = null;
state.set(State.IDLE);
nextPublisher();
}
});
}
@Override
public void onError(Throwable t) {
if (innerSubscription != null) {
innerSubscription.cancel();
innerSubscription = null;
}
emitError(t);
}
@Override
public void onComplete() {
pendingComplete = true;
nextPublisher();
}
});
}
@Override
protected void onCancel() {
if (innerSubscription != null) {
innerSubscription.cancel();
innerSubscription = null;
}
if (outerSubscription != null) {
outerSubscription.cancel();
outerSubscription = null;
}
}
private void nextPublisher() {
if (state.compareAndSet(State.IDLE, State.PENDING)) {
if (pendingComplete) {
emitComplete();
} else if (hasDemand()) {
outerSubscription.request(1);
} else {
state.set(State.IDLE);
if (hasDemand()) {
nextPublisher();
}
}
} else if (state.get() == State.PENDING && pendingComplete) {
emitComplete();
}
}
});
}
Aggregations