rsocket-rxjs
Version:
RSocket Protocol Client Implementation
119 lines (118 loc) • 4.84 kB
JavaScript
import { defer, Observable, of } from "rxjs";
import { BackpressureStrategy } from "../../api/rsocket.api";
import { factory } from '../../core/config-log4j';
import { EncodingRSocketResponder } from "../encoding-rsocket-responder";
import { WellKnownMimeTypes } from "../well-known-mime-types";
export class RequestResponseMapping {
constructor(route, handler, options) {
this.route = route;
this.handler = handler;
this.options = options;
}
}
export class RequestStreamMapping {
constructor(route, handler, options, backpressureStrategy = BackpressureStrategy.BufferDelay) {
this.route = route;
this.handler = handler;
this.options = options;
this.backpressureStrategy = backpressureStrategy;
}
}
export class RequestFNFMapping {
constructor(route, handler, options) {
this.route = route;
this.handler = handler;
this.options = options;
}
}
const log = factory.getLogger('rsocket.extensions.messages.RSocketRoutingResponder');
export class RSocketRoutingResponder extends EncodingRSocketResponder {
constructor(encodingRSocket) {
super(encodingRSocket);
this.encodingRSocket = encodingRSocket;
this._requestResponseMappers = [];
this._requestStreamMappers = [];
this._requestFNFMappers = [];
}
removeHandler(route) {
this._requestResponseMappers = this._requestResponseMappers.filter(v => v.route != route);
this._requestStreamMappers = this._requestStreamMappers.filter(v => v.route != route);
this._requestFNFMappers = this._requestFNFMappers.filter(v => v.route != route);
}
addRequestResponseHandler(route, handler, options) {
this.addMapping(new RequestResponseMapping(route, handler, options), this._requestResponseMappers);
}
addRequestStreamHandler(route, handler, options, backpressureStrategy = BackpressureStrategy.BufferDelay) {
this.addMapping(new RequestStreamMapping(route, handler, options, backpressureStrategy), this._requestStreamMappers);
}
addRequestFNFHandler(route, handler, options) {
this.addMapping(new RequestFNFMapping(route, handler, options), this._requestFNFMappers);
}
addMapping(mapping, target) {
if (target.findIndex(m => m.route == mapping.route) == -1) {
target.push(mapping);
}
else {
throw new Error(`Mapping for topic ${mapping} already registered`);
}
}
handleDecodedRequestStream(payload) {
const mapper = this.getMapping(this.getTopic(payload), this._requestStreamMappers);
const stream = defer(() => {
log.debug("Executing Request Stream Handler for: " + mapper.route);
const result = mapper.handler(payload);
let obs;
if (result instanceof Observable) {
obs = result;
}
else {
obs = of(result);
}
return obs;
});
return {
stream: stream,
backpressureStrategy: mapper.backpressureStrategy
};
}
handleDecodedRequestResponse(payload) {
return defer(() => {
const mapper = this.getMapping(this.getTopic(payload), this._requestResponseMappers);
log.debug("Executing Request Response Handler for: " + mapper.route);
const result = mapper.handler(payload);
let obs;
if (result instanceof Observable) {
obs = result;
}
else {
obs = of(result);
}
return obs;
});
}
handleDecodedFireAndForget(payload) {
const mapper = this.getMapping(this.getTopic(payload), this._requestFNFMappers);
log.debug('Executing Request FNF Handler for: ' + mapper.route);
mapper.handler(payload);
}
getMapping(route, target) {
const mapping = target.find(m => m.route == route);
if (mapping == undefined) {
throw Error(`No handler registered for ${route}`);
}
return mapping;
}
getTopic(payload) {
if (payload.metadata == undefined) {
throw new Error('Cannot get route. No metadata defined');
}
if (payload.metadataMimeType == WellKnownMimeTypes.MESSAGE_X_RSOCKET_ROUTING_V0.name) {
return payload.metadata;
}
if (payload.metadataMimeType == WellKnownMimeTypes.MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0.name) {
let compositeMetadata = payload.metadata;
return compositeMetadata.route;
}
throw new Error('Failed to get route information from metadata');
}
}