ydb-sdk
Version:
Node.js bindings for working with YDB API over gRPC
115 lines (114 loc) • 5.14 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryClient = void 0;
const events_1 = __importDefault(require("events"));
const table_1 = require("../table");
const query_session_pool_1 = require("./query-session-pool");
const symbols_1 = require("./symbols");
const errors_1 = require("../errors");
const context_1 = require("../context");
const symbols_2 = require("../retries/symbols");
/**
* YDB Query Service client.
*
* # Experimental
*
* Notice: This API is EXPERIMENTAL and may be changed or removed in a later release.
*/
class QueryClient extends events_1.default {
constructor(settings) {
super();
this.retrier = settings.retrier;
this.pool = new query_session_pool_1.QuerySessionPool(settings);
this.logger = settings.logger;
}
async destroy() {
await this.pool.destroy();
}
async do(opts) {
return opts.ctx.wrap({
timeout: opts.timeout
}, async (ctx) => {
return this.retrier.retry(ctx, async (_ctx) => {
var _a;
const session = await this.pool.acquire();
session[symbols_1.ctxSymbol] = ctx;
if (opts.hasOwnProperty('idempotent')) {
session[symbols_1.isIdempotentDoLevelSymbol] = true;
session[symbols_1.isIdempotentSymbol] = opts.idempotent;
}
if (opts.hasOwnProperty('onTrailer')) {
session[symbols_1.sessionTrailerCallbackSymbol] = opts.onTrailer;
}
let error;
try {
if (opts.txSettings)
session[symbols_1.sessionTxSettingsSymbol] = opts.txSettings;
let res;
try {
res = await opts.fn(session);
}
catch (err) {
if (err instanceof errors_1.YdbError) {
delete session[symbols_1.sessionTxIdSymbol];
}
throw err;
}
if (session[symbols_1.sessionTxIdSymbol]) { // there is an open transaction within session
if (opts.txSettings) {
// likely doTx was called and user expects have the transaction being commited
await session[symbols_1.sessionCommitTransactionSymbol]();
}
else {
// likely do() was called and user intentionally haven't closed transaction
await session[symbols_1.sessionRollbackTransactionSymbol]();
}
}
return { result: res };
}
catch (err) {
error = err;
return { err: error, idempotent: session[symbols_1.isIdempotentSymbol] };
}
finally {
delete session[symbols_1.ctxSymbol];
delete session[symbols_1.sessionTxSettingsSymbol];
delete session[symbols_1.sessionCurrentOperationSymbol];
delete session[symbols_1.isIdempotentDoLevelSymbol];
delete session[symbols_1.isIdempotentSymbol];
delete session[symbols_1.sessionTrailerCallbackSymbol];
// @ts-ignore
if (error && ((_a = error[symbols_2.RetryPolicySymbol]) === null || _a === void 0 ? void 0 : _a.deleteSession)) {
this.logger.debug('Encountered bad or busy session, re-creating the session');
session.emit(query_session_pool_1.SessionEvent.SESSION_BROKEN);
}
else {
session[symbols_1.sessionReleaseSymbol]();
}
}
});
});
}
doTx(opts) {
if (!opts.txSettings) {
opts = Object.assign(Object.assign({}, opts), { txSettings: table_1.AUTO_TX.beginTx });
}
return this.do(opts);
}
}
exports.QueryClient = QueryClient;
__decorate([
(0, context_1.ensureContext)()
], QueryClient.prototype, "do", null);
__decorate([
(0, context_1.ensureContext)()
], QueryClient.prototype, "doTx", null);