UNPKG

@itwin/presentation-common

Version:

Common pieces for iModel.js presentation packages

187 lines • 8.51 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * 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