Skip to content

Commit

Permalink
chore: WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Zork33 committed Oct 26, 2023
1 parent 9187879 commit 0f7daf4
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 176 deletions.
66 changes: 0 additions & 66 deletions src/DriverContext.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/__tests__/integration/bytestring-identity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {destroyDriver, initDriver, TABLE} from '../../test-utils';
import {Column, Session, TableDescription} from '../../table';
import {declareType, TypedData, Types} from '../../types';
import {withRetries} from '../../retries';
import {DriverContext} from "../../DriverContext";
import {ContextWithLogger} from "../../context-with-logger";

async function createTable(session: Session) {
await session.dropTable(TABLE);
Expand Down Expand Up @@ -78,7 +78,7 @@ describe('bytestring identity', () => {

beforeAll(async () => {
driver = await initDriver();
await DriverContext.getSafe(driver, 'test.beforeAll').do(() =>
await ContextWithLogger.getSafe(driver.logger, 'test.beforeAll').do(() =>
driver.tableClient.withSession(async (session) => {
await createTable(session);
await fillTableWithData(session, initialRows);
Expand Down
33 changes: 33 additions & 0 deletions src/__tests__/unit/context-with-logger.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {ContextWithLogger} from '../../context-with-logger';
import Driver from "./../../driver";
import {buildTestLogger} from "../../utils/tests/test-logger";

describe('driverConext', () => {

it('getSafe', async () => {
const {testLogger, testLoggerFn} = buildTestLogger()
const ctx1 = ContextWithLogger.getSafe(testLogger, 'method1');
await ctx1.do(() => {
const ctx2 = ContextWithLogger.getSafe(testLogger, 'method2');
expect(ctx2).toBe(ctx1);
});
expect(testLoggerFn.mock.calls).toEqual([['trace', 'method1'], ['trace', 'method2']]);
});

it('get - ok', async () => {
const {testLogger, testLoggerFn} = buildTestLogger()
const driver = Object.create(Driver.prototype) as Driver;
(driver as any).logger = testLogger;

const ctx1 = ContextWithLogger.getSafe(testLogger,'method1');
await ctx1.do(() => {
const ctx2 = ContextWithLogger.get('method2');
expect(ctx2).toBe(ctx1);
});
expect(testLoggerFn.mock.calls).toEqual([['trace', 'method1'], ['trace', 'method2']]);
});

it('get - error', async () => {
expect(() => ContextWithLogger.get('method')).toThrow();
});
});
54 changes: 0 additions & 54 deletions src/__tests__/unit/driverContext.test.ts

This file was deleted.

82 changes: 82 additions & 0 deletions src/context-with-logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {Context, getContext, NOT_A_CONTEXT} from "./utils/context";
import {Logger} from "./utils/simple-logger";

/**
* Context with reference to the head object - driver.
*/
export class ContextWithLogger extends Context {
private constructor(context: Context, readonly logger: Logger) {
super(context);
}

/**
* This method should be called in methods that can be called by a client code - if this type of context
* does not already exist, it will be created. It is important to have access to Logger object to build new context.
*/
static getSafe(logger: Logger, methodName: string) {
const ctx = getContext();

let context = ctx.findContextByClass<ContextWithLogger>(ContextWithLogger);

if (context === NOT_A_CONTEXT) {
context = new ContextWithLogger(ctx, logger);
}

context.trace(methodName, ctx);

return context;
}

/**
* Returns the context of this type. If there is no such context - throws an error.
*/
static get(methodName: string) {
const ctx = getContext();

let context = ctx.findContextByClass<ContextWithLogger>(ContextWithLogger);

if (context === NOT_A_CONTEXT) {
throw new Error('ContextWithLogger is not in the context chain. Consider using RiverContext.getSafe()')
}

context.trace(methodName, ctx);

return context;
}

/**
* Guarantees error logging if the code is called from a thread other than
* the main thread, such as setTimeout or setInterval.
*
* An error is NOT thrown after logging. And NO result.
*/
async doHandleError<T>(callback: () => T): Promise<void> {
try {
await super.do(callback);
} catch(error) {
this.logger.error(error);
}
}

/**
* Guarantees error logging if the code is called from a thread other than
* the main thread, such as setTimeout or setInterval.
*
* An error is NOT thrown after logging. And NO result.
*/
doHandleErrorSync<T>(callback: () => T): void {
try {
super.doSync(callback);
} catch(error) {
this.logger.error(error);
}
}

/**
* Writes trace to logger and creates span if tracing is enabled.
*/
private trace(methodName: string, ctx: Context) {
this.logger.trace(methodName, ctx); // as parameter goes las ontext in the chain
// TODO: name span
}
}
34 changes: 19 additions & 15 deletions src/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import SchemeClient from './scheme';
import {ClientOptions} from './utils';
import {parseConnectionString} from './parse-connection-string';
import {makeSslCredentials, ISslCredentials} from './ssl-credentials';
import {ContextWithLogger} from "./context-with-logger";

export interface IPoolSettings {
minLimit?: number;
Expand Down Expand Up @@ -42,9 +43,10 @@ export default class Driver {

constructor(settings: IDriverSettings) {
this.logger = settings.logger || new SimpleLogger();
const ctx = ContextWithLogger.getSafe(this.logger, 'ydb_nodejs_sdk.driver.ctor');

if (settings.connectionString) {
const {endpoint, database} = parseConnectionString(settings.connectionString);
const {endpoint, database} = ctx.doSync(() => parseConnectionString(settings.connectionString!));
this.endpoint = endpoint;
this.database = database;
} else if (!settings.endpoint) {
Expand All @@ -56,43 +58,44 @@ export default class Driver {
this.database = settings.database;
}

this.sslCredentials = makeSslCredentials(this.endpoint, this.logger, settings.sslCredentials);
this.sslCredentials = ctx.doSync(() => makeSslCredentials(this.endpoint, this.logger, settings.sslCredentials));

this.authService = settings.authService;
this.poolSettings = settings.poolSettings;
this.clientOptions = settings.clientOptions;

this.discoveryService = new DiscoveryService({
this.discoveryService = ctx.doSync(() => new DiscoveryService({
endpoint: this.endpoint,
database: this.database,
authService: this.authService,
sslCredentials: this.sslCredentials,
discoveryPeriod: ENDPOINT_DISCOVERY_PERIOD,
logger: this.logger,
});
this.tableClient = new TableClient({
}));
this.tableClient = ctx.doSync(() => new TableClient({
database: this.database,
authService: this.authService,
sslCredentials: this.sslCredentials,
poolSettings: this.poolSettings,
clientOptions: this.clientOptions,
discoveryService: this.discoveryService,
logger: this.logger,
});
this.schemeClient = new SchemeClient({
}));
this.schemeClient = ctx.doSync(() => new SchemeClient({
database: this.database,
authService: this.authService,
sslCredentials: this.sslCredentials,
clientOptions: this.clientOptions,
discoveryService: this.discoveryService,
logger: this.logger,
});
}));
}

public async ready(timeout: number): Promise<boolean> {
const ctx = ContextWithLogger.getSafe(this.logger, 'ydb_nodejs_sdk.driver.ready');
try {
await this.discoveryService.ready(timeout);
this.logger.debug('Driver is ready!');
await ctx.do(() => this.discoveryService.ready(timeout));
ctx.logger.debug('Driver is ready!');
return true;
} catch (e) {
if (e instanceof TimeoutExpired) {
Expand All @@ -104,10 +107,11 @@ export default class Driver {
}

public async destroy(): Promise<void> {
this.logger.debug('Destroying driver...');
this.discoveryService.destroy();
await this.tableClient.destroy();
await this.schemeClient.destroy();
this.logger.debug('Driver has been destroyed.');
const ctx = ContextWithLogger.getSafe(this.logger, 'ydb_nodejs_sdk.driver.destroy');
ctx.logger.debug('Destroying driver...');
ctx.do(() => this.discoveryService.destroy());
await ctx.do(() => this.tableClient.destroy());
await ctx.do(() => this.schemeClient.destroy());
ctx.logger.debug('Driver has been destroyed.');
}
}
8 changes: 4 additions & 4 deletions src/retries/withRetries.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {RetryParameters} from "./RetryParameters";
import {RetryStrategy} from "./RetryStrategy";
import {DriverContext} from "../DriverContext";
import {ContextWithLogger} from "../context-with-logger";
import {Trace} from "./consts";

/**
Expand All @@ -12,12 +12,12 @@ export async function withRetries<T>(
originalFunction: () => Promise<T>,
strategyParams?: RetryParameters,
) {
const ydbSdkContext = DriverContext.get(Trace.withRetries);
const ctx = ContextWithLogger.get(Trace.withRetries);

const wrappedMethodName = originalFunction.name;
if (!strategyParams) {
strategyParams = new RetryParameters();
}
const strategy = new RetryStrategy(wrappedMethodName, strategyParams, ydbSdkContext.logger);
return await strategy.retry(originalFunction);
const strategy = ctx.doSync(() => new RetryStrategy(wrappedMethodName, strategyParams!, ctx.logger));
return await ctx.do(() => strategy.retry(originalFunction));
}
Loading

0 comments on commit 0f7daf4

Please sign in to comment.