@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
121 lines (119 loc) • 4.43 kB
JavaScript
import { from, Observable, of, throwError } from 'rxjs';
import { filter, mergeMap, take } from 'rxjs/operators';
import { Logging } from '../diagnostics/logging';
import { RpcInboundClient } from './rpc-inbound-client';
import { RpcOutboundClient } from './rpc-outbound-client';
/**
* RPC Observable Client class.
*/
export class RpcObservableClient {
rpc;
command;
version;
id = 0;
requestCommand;
resultCommand;
resultBuffer = [];
resultObservers = [];
/**
* Initializes a new instance of the RpcObservableClient class.
*
* @param rpc The rpc object.
* @param command the command string.
* @param version the version string.
*/
constructor(rpc, command, version) {
this.rpc = rpc;
this.command = command;
this.version = version;
this.requestCommand = `${command}-Request`;
this.resultCommand = `${command}-Result`;
this.rpc.register(this.resultCommand, this.handler.bind(this));
this.rpc.registerInboundHandler(this.resultCommand, this.handler.bind(this));
this.rpc.registerOutboundHandler(this.resultCommand, this.handler.bind(this));
}
/**
* Make observable call.
*
* @param request The the request data.
* @param outbound The outbound RPC channel. (request initiated from Shell.)
* @return An observable for the response message
*/
observableCall(request, outbound) {
const id = this.id++;
const observableRequest = { id, request };
Logging.logDebug(this.requestCommand, `Sending request: "${this.requestCommand}"`, observableRequest);
const replayResult = this.replayResult();
return from(this.rpcCall(observableRequest, outbound))
.pipe(mergeMap(() => replayResult), filter(observableResult => {
if (observableResult.id !== observableRequest.id) {
return false;
}
// clean up the buffer.
const index = this.resultBuffer.findIndex(item => item.id === observableResult.id);
if (index >= 0) {
this.resultBuffer.splice(index, 1);
}
return true;
}), take(1), mergeMap((result) => {
if (result.error) {
result.error.sourceName = result.sourceName;
result.error.sourceSubName = result.sourceSubName;
result.error.sourceVersion = result.sourceVersion;
return throwError(() => result.error);
}
result.result = result.result || {};
result.result.sourceName = result.sourceName;
result.result.sourceSubName = result.sourceSubName;
result.result.sourceVersion = result.sourceVersion;
return of(result.result);
}));
}
/**
* Making rpc call to shell or module.
*
* @param request the request packet data.
* @param outbound the outbound object from Shell to module request.
* @return Promise<void> the promise object.
*/
rpcCall(request, outbound) {
if (outbound) {
return RpcOutboundClient.callOutbound(this.rpc.rpcManager.rpcChannel, outbound, this.requestCommand, this.version, request);
}
return RpcInboundClient.call(this.rpc, this.requestCommand, this.version, request);
}
/**
* Create a replay observable. Replays result data if results exists.
*/
replayResult() {
return new Observable(observer => {
this.resultObservers.push(observer);
// replay.
for (const item of this.resultBuffer) {
observer.next(item);
}
return () => {
const index = this.resultObservers.findIndex(item => item === observer);
if (index >= 0) {
this.resultObservers.splice(index, 1);
}
observer.complete();
};
});
}
/**
* Handles rpc response messages.
*
* @param result the result of observable request.
*/
handler(result) {
// store.
this.resultBuffer.push(result);
// distributed to all active observers.
for (const observer of this.resultObservers) {
observer.next(result);
}
return Promise.resolve();
}
}
//# sourceMappingURL=rpc-observable-client.js.map