This repository has been archived by the owner on Jun 21, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Refactored .send() on websocket session
- Loading branch information
Showing
7 changed files
with
364 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
...eway-tests/src/test/java/io/scalecube/services/gateway/websocket/CancelledSubscriber.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package io.scalecube.services.gateway.websocket; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import reactor.core.CoreSubscriber; | ||
|
||
public class CancelledSubscriber implements CoreSubscriber { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(CancelledSubscriber.class); | ||
|
||
public static final CancelledSubscriber INSTANCE = new CancelledSubscriber(); | ||
|
||
private CancelledSubscriber() { | ||
// Do not instantiate | ||
} | ||
|
||
@Override | ||
public void onSubscribe(org.reactivestreams.Subscription s) { | ||
// no-op | ||
} | ||
|
||
@Override | ||
public void onNext(Object o) { | ||
LOGGER.warn("Received ({}) which will be dropped immediately due cancelled aeron inbound", o); | ||
} | ||
|
||
@Override | ||
public void onError(Throwable t) { | ||
// no-op | ||
} | ||
|
||
@Override | ||
public void onComplete() { | ||
// no-op | ||
} | ||
} |
176 changes: 176 additions & 0 deletions
176
...-gateway-tests/src/test/java/io/scalecube/services/gateway/websocket/ReactiveAdapter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
package io.scalecube.services.gateway.websocket; | ||
|
||
import java.util.concurrent.atomic.AtomicLongFieldUpdater; | ||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; | ||
import org.reactivestreams.Subscription; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import reactor.core.CoreSubscriber; | ||
import reactor.core.Exceptions; | ||
import reactor.core.publisher.BaseSubscriber; | ||
import reactor.core.publisher.Flux; | ||
import reactor.core.publisher.Operators; | ||
|
||
public final class ReactiveAdapter extends BaseSubscriber<Object> implements ReactiveOperator { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(ReactiveAdapter.class); | ||
|
||
private static final AtomicLongFieldUpdater<ReactiveAdapter> REQUESTED = | ||
AtomicLongFieldUpdater.newUpdater(ReactiveAdapter.class, "requested"); | ||
|
||
@SuppressWarnings("rawtypes") | ||
private static final AtomicReferenceFieldUpdater<ReactiveAdapter, CoreSubscriber> | ||
DESTINATION_SUBSCRIBER = | ||
AtomicReferenceFieldUpdater.newUpdater( | ||
ReactiveAdapter.class, CoreSubscriber.class, "destinationSubscriber"); | ||
|
||
private final FluxReceive inbound = new FluxReceive(); | ||
|
||
private volatile long requested; | ||
private volatile boolean fastPath; | ||
private long produced; | ||
private volatile CoreSubscriber<? super Object> destinationSubscriber; | ||
private Throwable lastError; | ||
|
||
@Override | ||
public boolean isDisposed() { | ||
return destinationSubscriber == CancelledSubscriber.INSTANCE; | ||
} | ||
|
||
@Override | ||
public void dispose(Throwable throwable) { | ||
Subscription upstream = upstream(); | ||
if (upstream != null) { | ||
upstream.cancel(); | ||
} | ||
CoreSubscriber<?> destination = | ||
DESTINATION_SUBSCRIBER.getAndSet(this, CancelledSubscriber.INSTANCE); | ||
if (destination != null) { | ||
destination.onError(throwable); | ||
} | ||
} | ||
|
||
@Override | ||
public void dispose() { | ||
inbound.cancel(); | ||
} | ||
|
||
public Flux<Object> receive() { | ||
return inbound; | ||
} | ||
|
||
@Override | ||
public void lastError(Throwable throwable) { | ||
lastError = throwable; | ||
} | ||
|
||
@Override | ||
public Throwable lastError() { | ||
return lastError; | ||
} | ||
|
||
@Override | ||
public void tryNext(Object Object) { | ||
if (!isDisposed()) { | ||
destinationSubscriber.onNext(Object); | ||
} else { | ||
LOGGER.warn("[tryNext] reactiveAdapter is disposed, dropping : " + Object); | ||
} | ||
} | ||
|
||
@Override | ||
public boolean isFastPath() { | ||
return fastPath; | ||
} | ||
|
||
@Override | ||
public void commitProduced() { | ||
if (produced > 0) { | ||
Operators.produced(REQUESTED, this, produced); | ||
produced = 0; | ||
} | ||
} | ||
|
||
@Override | ||
public long incrementProduced() { | ||
return ++produced; | ||
} | ||
|
||
@Override | ||
public long requested(long limit) { | ||
return Math.min(requested, limit); | ||
} | ||
|
||
@Override | ||
protected void hookOnSubscribe(Subscription subscription) { | ||
subscription.request(requested); | ||
} | ||
|
||
@Override | ||
protected void hookOnNext(Object Object) { | ||
tryNext(Object); | ||
} | ||
|
||
@Override | ||
protected void hookOnComplete() { | ||
dispose(); | ||
} | ||
|
||
@Override | ||
protected void hookOnError(Throwable throwable) { | ||
dispose(throwable); | ||
} | ||
|
||
@Override | ||
protected void hookOnCancel() { | ||
dispose(); | ||
} | ||
|
||
class FluxReceive extends Flux<Object> implements Subscription { | ||
|
||
@Override | ||
public void request(long n) { | ||
Subscription upstream = upstream(); | ||
if (upstream != null) { | ||
upstream.request(n); | ||
} | ||
if (fastPath) { | ||
return; | ||
} | ||
if (n == Long.MAX_VALUE) { | ||
fastPath = true; | ||
requested = Long.MAX_VALUE; | ||
return; | ||
} | ||
Operators.addCap(REQUESTED, ReactiveAdapter.this, n); | ||
} | ||
|
||
@Override | ||
public void cancel() { | ||
Subscription upstream = upstream(); | ||
if (upstream != null) { | ||
upstream.cancel(); | ||
} | ||
CoreSubscriber<?> destination = | ||
DESTINATION_SUBSCRIBER.getAndSet(ReactiveAdapter.this, CancelledSubscriber.INSTANCE); | ||
if (destination != null) { | ||
destination.onComplete(); | ||
} | ||
} | ||
|
||
@Override | ||
public void subscribe(CoreSubscriber<? super Object> destinationSubscriber) { | ||
boolean result = | ||
DESTINATION_SUBSCRIBER.compareAndSet(ReactiveAdapter.this, null, destinationSubscriber); | ||
if (result) { | ||
destinationSubscriber.onSubscribe(this); | ||
} else { | ||
Operators.error( | ||
destinationSubscriber, | ||
isDisposed() | ||
? Exceptions.failWithCancel() | ||
: Exceptions.duplicateOnSubscribeException()); | ||
} | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
...gateway-tests/src/test/java/io/scalecube/services/gateway/websocket/ReactiveOperator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package io.scalecube.services.gateway.websocket; | ||
|
||
import reactor.core.Disposable; | ||
|
||
public interface ReactiveOperator extends Disposable { | ||
|
||
void dispose(Throwable throwable); | ||
|
||
void lastError(Throwable throwable); | ||
|
||
Throwable lastError(); | ||
|
||
void tryNext(Object fragment); | ||
|
||
boolean isFastPath(); | ||
|
||
void commitProduced(); | ||
|
||
long incrementProduced(); | ||
|
||
long requested(long limit); | ||
} |
Oops, something went wrong.