@itwin/presentation-common
Version:
Common pieces for iModel.js presentation packages
187 lines • 8.51 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module RPC
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.RpcRequestsHandler = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const CommonLoggerCategory_js_1 = require("./CommonLoggerCategory.js");
const Error_js_1 = require("./Error.js");
const PresentationRpcInterface_js_1 = require("./PresentationRpcInterface.js");
const Utils_js_1 = require("./Utils.js");
/**
* Default timeout for how long we're going to wait for RPC request to be fulfilled before throwing
* a timeout error.
*/
const DEFAULT_REQUEST_TIMEOUT = 10 * 60 * 1000; // 10 minutes
/**
* RPC requests handler that wraps [[PresentationRpcInterface]] and
* adds handling for cases when backend needs to be synced with client
* state.
*
* @internal
*/
class RpcRequestsHandler {
/** Timeout for how long the handler going to wait for RPC request to be fulfilled before throwing a timeout error. */
timeout;
/** ID that identifies this handler as a client */
clientId;
constructor(props) {
this.clientId = props?.clientId ?? core_bentley_1.Guid.createValue();
this.timeout = props?.timeout ?? DEFAULT_REQUEST_TIMEOUT;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
get rpcClient() {
return core_common_1.RpcManager.getClientForInterface(PresentationRpcInterface_js_1.PresentationRpcInterface);
}
async requestWithTimeout(func, diagnosticsHandler) {
const rpcResponsePromise = func();
const rpcRequest = core_common_1.RpcRequest.current(this.rpcClient);
const timeout = (0, Utils_js_1.createCancellableTimeoutPromise)(this.timeout);
return Promise.race([
(async () => {
let diagnostics;
try {
const response = await rpcResponsePromise;
diagnostics = response.diagnostics;
switch (response.statusCode) {
case Error_js_1.PresentationStatus.Success:
return response.result;
default:
throw new Error_js_1.PresentationError(response.statusCode, response.errorMessage);
}
}
finally {
diagnosticsHandler && diagnostics && diagnosticsHandler(diagnostics);
}
})(),
timeout.promise.then(() => {
throw new Error(`Processing the request took longer than the configured limit of ${this.timeout} ms`);
}),
]).finally(() => {
rpcRequest?.cancel();
timeout.cancel();
});
}
/**
* Send the request to backend. We'll wait for the response for `this.timeout` ms, and if we don't get the response by
* then, we'll throw an error.
*/
async request(func, options, ...additionalOptions) {
const { imodel, diagnostics, ...optionsNoIModel } = options;
const { handler: diagnosticsHandler, ...diagnosticsOptions } = diagnostics ?? {};
if (isOptionsWithRuleset(optionsNoIModel)) {
optionsNoIModel.rulesetOrId = cleanupRuleset(optionsNoIModel.rulesetOrId);
}
const rpcOptions = {
...optionsNoIModel,
clientId: this.clientId,
};
if (diagnostics) {
rpcOptions.diagnostics = diagnosticsOptions;
}
const doRequest = async () => func(imodel, rpcOptions, ...additionalOptions);
const result = await this.requestWithTimeout(doRequest, diagnosticsHandler);
return result;
}
async getNodesCount(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getNodesCount.bind(this.rpcClient), options);
}
async getPagedNodes(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getPagedNodes.bind(this.rpcClient), options);
}
async getNodesDescriptor(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const response = await this.request(this.rpcClient.getNodesDescriptor.bind(this.rpcClient), options);
if (typeof response === "string") {
return JSON.parse(response);
}
return response;
}
async getNodePaths(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getNodePaths.bind(this.rpcClient), options);
}
async getFilteredNodePaths(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getFilteredNodePaths.bind(this.rpcClient), options);
}
async getContentSources(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getContentSources.bind(this.rpcClient), options);
}
async getContentDescriptor(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getContentDescriptor.bind(this.rpcClient), options);
}
async getContentSetSize(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getContentSetSize.bind(this.rpcClient), options);
}
async getPagedContent(options) {
return this.request(
// eslint-disable-next-line @typescript-eslint/no-deprecated
this.rpcClient.getPagedContent.bind(this.rpcClient), options);
}
async getPagedContentSet(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getPagedContentSet.bind(this.rpcClient), options);
}
async getPagedDistinctValues(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getPagedDistinctValues.bind(this.rpcClient), options);
}
async getContentInstanceKeys(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getContentInstanceKeys.bind(this.rpcClient), options);
}
async getDisplayLabelDefinition(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getDisplayLabelDefinition.bind(this.rpcClient), options);
}
async getPagedDisplayLabelDefinitions(options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return this.request(this.rpcClient.getPagedDisplayLabelDefinitions.bind(this.rpcClient), options);
}
/* eslint-disable @typescript-eslint/no-deprecated */
async getSelectionScopes(options) {
return this.request(this.rpcClient.getSelectionScopes.bind(this.rpcClient), options);
}
async computeSelection(options) {
return this.request(this.rpcClient.computeSelection.bind(this.rpcClient), options);
}
}
exports.RpcRequestsHandler = RpcRequestsHandler;
function isOptionsWithRuleset(options) {
return typeof options.rulesetOrId === "object";
}
const RULESET_SUPPORTED_PROPERTIES_OBJ = {
id: true,
rules: true,
version: true,
requiredSchemas: true,
supplementationInfo: true,
vars: true,
};
function cleanupRuleset(ruleset) {
const cleanedUpRuleset = { ...ruleset };
for (const propertyKey of Object.keys(cleanedUpRuleset)) {
if (!RULESET_SUPPORTED_PROPERTIES_OBJ.hasOwnProperty(propertyKey)) {
if (propertyKey === "$schema") {
delete cleanedUpRuleset[propertyKey];
}
else {
core_bentley_1.Logger.logWarning(CommonLoggerCategory_js_1.PresentationCommonLoggerCategory.Package, `Provided ruleset contains unrecognized attribute '${propertyKey}'. It either doesn't exist or may be no longer supported.`);
}
}
}
return cleanedUpRuleset;
}
//# sourceMappingURL=RpcRequestsHandler.js.map