All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.polkadot.rpc.rx.RpcRx Maven / Gradle / Ivy

The newest version!
package org.polkadot.rpc.rx;

import com.google.common.collect.Lists;
import com.onehilltech.promises.Promise;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action;
import io.reactivex.subjects.BehaviorSubject;
import io.reactivex.subjects.PublishSubject;
import org.polkadot.common.EventEmitter;
import org.polkadot.direct.IRpcFunction;
import org.polkadot.rpc.core.IRpc;
import org.polkadot.rpc.core.RpcCore;
import org.polkadot.rpc.provider.IProvider;
import org.polkadot.utils.RxUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * RpcRx
 * The RxJS API is a wrapper around the API.
 * It allows wrapping API components with observables using RxJS.
 * 

* **Example** * ```java * import org.polkadot.rpc.rx.RpcRx; * import org.polkadot.rpc.provider.wsWsProvider; *

* WsProvider provider = new WsProvider('http://127.0.0.1:9944'); * RpcRx api = new RpcRx(provider); * ``` */ public class RpcRx extends Types.RpcRxInterface { private static final Logger logger = LoggerFactory.getLogger(RpcRx.class); private RpcCore api; private EventEmitter eventEmitter; private BehaviorSubject isConnected; /** * @param provider An API provider using HTTP or WebSocket */ public RpcRx(IProvider provider) { this(new RpcCore(provider)); } /** * @param rpc An API provider using HTTP or WebSocket */ public RpcRx(RpcCore rpc) { this.api = rpc; this.eventEmitter = new EventEmitter(); this.isConnected = BehaviorSubject.createDefault(this.api.getProvider().isConnected()); this.initEmitters(this.api.getProvider()); this.author = this.createInterface(this.api.author()); this.chain = this.createInterface(this.api.chain()); this.state = this.createInterface(this.api.state()); this.system = this.createInterface(this.api.system()); } private void initEmitters(IProvider provider) { provider.on(IProvider.ProviderInterfaceEmitted.connected, value -> { RpcRx.this.isConnected.onNext(true); RpcRx.this.emit(IProvider.ProviderInterfaceEmitted.connected); }); provider.on(IProvider.ProviderInterfaceEmitted.disconnected, value -> { RpcRx.this.isConnected.onNext(false); RpcRx.this.emit(IProvider.ProviderInterfaceEmitted.disconnected); }); } @Override public Observable isConnected() { return this.isConnected; } @Override void on(IProvider.ProviderInterfaceEmitted type, EventEmitter.EventListener handler) { this.eventEmitter.on(type, handler); } protected void emit(IProvider.ProviderInterfaceEmitted type, Object... args) { this.eventEmitter.emit(type, args); } private Types.RpcRxInterfaceSection createInterface(IRpc.RpcInterfaceSection section) { Types.RpcRxInterfaceSection ret = new Types.RpcRxInterfaceSection(); for (String functionName : section.functionNames()) { if (functionName.equals("subscribe") || functionName.equals("unsubscribe")) { continue; } ret.put(functionName, this.createObservable(functionName, section)); } return ret; } private Types.RpcRxInterfaceMethod createObservable(String name, IRpc.RpcInterfaceSection section) { IRpcFunction function = section.function(name); if (function.isSubscribe()) { return new Types.RpcRxInterfaceMethod() { @Override public Observable call(Object... params) { return createReplayV2(name, section, params); } }; } return new Types.RpcRxInterfaceMethod() { @Override public Observable call(Object... params) { Promise invoke = function.invoke(params); return RxUtils.fromPromise(invoke); } }; } private Observable createReplayV2(String name, IRpc.RpcInterfaceSection section, Object... params) { IRpcFunction function = section.function(name); PublishSubject subject = PublishSubject.create(); IRpcFunction.SubscribeCallback replayCallBack = new IRpcFunction.SubscribeCallback() { @Override public void callback(Object o) { subject.onNext(o); } }; List args = Lists.newArrayList(params); args.add(replayCallBack); Promise subscribe = function.invoke(args.toArray(new Object[0])) ._catch(error -> { subject.onError(error); return null; }); Observable ret = subject.doOnDispose(new Action() { @Override public void run() throws Exception { subscribe.then((result) -> { IRpcFunction.Unsubscribe unsubscribe = (IRpcFunction.Unsubscribe) result; logger.debug(" doOnDispose unsub"); unsubscribe.unsubscribe(); return null; })._catch(err -> { err.printStackTrace(); return null; }); } }); return ret.replay(1).refCount(); } private Observable createReplay(String name, IRpc.RpcInterfaceSection section, Object... params) { return Observable.create(new ObservableOnSubscribe() { @Override public void subscribe(ObservableEmitter emitter) throws Exception { IRpcFunction function = section.function(name); IRpcFunction.SubscribeCallback replayCallBack = RpcRx.this.createReplayCallBack(emitter); Promise promise = function.invoke(params, replayCallBack)._catch(error -> { emitter.onError(error); return null; }); emitter.setDisposable(new Disposable() { boolean disposed; @Override public void dispose() { if (disposed) { return; } disposed = true; promise.then(result -> function.unsubscribe((Integer) result)) ._catch(err -> { err.printStackTrace(); return null; }); } @Override public boolean isDisposed() { return disposed; } }); } }).replay(1).refCount(); } private IRpcFunction.SubscribeCallback createReplayCallBack(ObservableEmitter emitter) { return new IRpcFunction.SubscribeCallback() { @Override public void callback(Object o) { emitter.onNext(o); } }; } }