UNPKG

@datastax/astra-db-ts

Version:
108 lines (107 loc) 4.78 kB
// Copyright Datastax, Inc // SPDX-License-Identifier: Apache-2.0 // noinspection ExceptionCaughtLocallyJS import { HttpClient } from '../../../lib/api/clients/index.js'; import { DevOpsAPIResponseError, DevOpsAPITimeoutError, } from '../../../administration/errors.js'; import { HttpMethods } from '../../../lib/api/constants.js'; import { jsonTryParse } from '../../../lib/utils.js'; import { NonErrorError } from '../../../lib/errors.js'; import { HeadersProvider } from '../../../lib/index.js'; export class DevOpsAPIHttpClient extends HttpClient { constructor(opts) { super('devops-api', { ...opts, additionalHeaders: HeadersProvider.opts.fromObj.concat([ opts.additionalHeaders, opts.tokenProvider.toHeadersProvider(), ]), mkTimeoutError: DevOpsAPITimeoutError.mk, }); } async request(req, timeoutManager, started = 0) { return this._executeRequest(req, timeoutManager, started, this.logger.internal.generateAdminCommandRequestId()); } async requestLongRunning(req, info) { const isLongRunning = info.options?.blocking !== false; const timeoutManager = info.timeoutManager; const requestId = this.logger.internal.generateAdminCommandRequestId(); this.logger.internal.adminCommandStarted?.(requestId, this.baseUrl, req, isLongRunning, timeoutManager.initial()); const started = performance.now(); const resp = await this._executeRequest(req, timeoutManager, started, requestId); const id = (typeof info.id === 'function') ? info.id(resp) : info.id; await this._awaitStatus(id, req, info, started, requestId); this.logger.internal.adminCommandSucceeded?.(requestId, this.baseUrl, req, isLongRunning, resp, started); return resp; } async _executeRequest(req, timeoutManager, started, requestId) { const isLongRunning = started !== 0; try { const url = this.baseUrl + req.path; if (!isLongRunning) { this.logger.internal.adminCommandStarted?.(requestId, this.baseUrl, req, isLongRunning, timeoutManager.initial()); } started || (started = performance.now()); const resp = await this._request({ url: url, method: req.method, params: req.params, data: JSON.stringify(req.data), forceHttp1: true, timeoutManager, }); const data = resp.body ? jsonTryParse(resp.body, undefined) : undefined; if (resp.status >= 400) { throw new DevOpsAPIResponseError(resp, data); } if (!isLongRunning) { this.logger.internal.adminCommandSucceeded?.(requestId, this.baseUrl, req, false, data, started); } return { data: data, status: resp.status, headers: resp.headers, }; } catch (thrown) { const err = NonErrorError.asError(thrown); this.logger.internal.adminCommandFailed?.(requestId, this.baseUrl, req, isLongRunning, err, started); throw err; } } async _awaitStatus(id, req, info, started, requestId) { if (info.options?.blocking === false) { return; } const pollInterval = info.options?.pollInterval || info.defaultPollInterval; let waiting = false; for (let i = 1; i++;) { if (waiting) { continue; } waiting = true; this.logger.internal.adminCommandPolling?.(requestId, this.baseUrl, req, started, pollInterval, i); const resp = await this.request({ method: HttpMethods.Get, path: `/databases/${id}`, methodName: req.methodName, }, info.timeoutManager, started); if (resp.data?.status === info.target) { break; } if (!info.legalStates.includes(resp.data?.status)) { const okStates = [info.target, ...info.legalStates]; const error = new Error(`Created database is not in any legal state [${okStates.join(',')}]; current state: ${resp.data?.status}`); this.logger.internal.adminCommandFailed?.(requestId, this.baseUrl, req, true, error, started); throw error; } await new Promise((resolve) => { setTimeout(() => { waiting = false; resolve(); }, pollInterval); }); } } }