Здравствуйте, я пишу простое веб-приложение, используя дизайн, похожий на шаблон дизайна фасада.Приложение написано на Typescript с использованием nodejs, expressjs, node-postres и inversify.Допустим, у меня есть этот простой пример
Router.ts
router.get('/test', testController.test);
TestController.ts
import { Request, Response } from 'express';
import { ITestUC } from '../usecase/TestUC';
import { di } from '../core/Di';
import { TYPES } from '../core/Types';
class TestController {
public async test(req: Request, res: Response, next: Function) {
const uc = di.get<ITestUC>(TYPES.ITestUC);
await uc.run();
res.send({ data:1 });
}
}
export const testController = new TestController();
TestUC.ts
import "reflect-metadata";
import { injectable, interfaces } from "inversify";
import { di } from "../core/Di";
import { TYPES } from "../core/Types";
import { ITestManager1 } from "../library/Test/TestManager1";
import { ITestManager2 } from "../library/Test/TestManager2";
import { PoolClient } from "pg";
import { PostgresClient, IPostgresClient } from "../core/PostgresClient";
import { IPostgresPool } from "../core/PostgresPool";
function db(transaction: boolean) {
return (target: any, property: string, descriptor: TypedPropertyDescriptor<() => void>) => {
const fn = descriptor.value;
if(!fn) return;
descriptor.value = async function (){
let poolClient: PoolClient,
postgresClient: PostgresClient = new PostgresClient();
try {
poolClient = await di.get<IPostgresPool>(TYPES.IPostgresPool).pool.connect();
postgresClient.set(poolClient);
di.rebind<IPostgresClient>(TYPES.IPostgresClient).toDynamicValue((context: interfaces.Context) => { return postgresClient });
if (transaction) postgresClient.begin();
await fn.apply(this);
if (transaction) postgresClient.commit();
} catch (e) {
if (transaction) postgresClient.rollback();
throw e;
} finally {
postgresClient.get().release();
}
}
}
}
@injectable()
export class TestUC implements ITestUC {
@db(true)
public async run(): Promise<void> {
const manager1 = await di.get<ITestManager1>(TYPES.ITestManager1);
manager1.test1('m1');
const manager2 = await di.get<ITestManager2>(TYPES.ITestManager2);
manager2.test1('m2');
}
}
export interface ITestUC {
run(): Promise<void>
}
TestManager1.ts
import { injectable, inject} from "inversify";
import "reflect-metadata";
import { TYPES } from "../../core/Types";
import { ITestSql1 } from "./TestSql1";
@injectable()
export class TestManager1 implements ITestManager1 {
@inject(TYPES.ITestSql1) private sql: ITestSql1;
public async test1(value: string) {
await this.sql.test1(value);
}
}
export interface ITestManager1 {
test1(value: string)
}
TestSql1.ts
import { injectable, inject } from "inversify";
import "reflect-metadata";
import { IPostgresClient } from "../../core/PostgresClient";
import { TYPES } from "../../core/Types";
@injectable()
export class TestSql1 implements ITestSql1{
@inject(TYPES.IPostgresClient) db: IPostgresClient;
public async test1(value: string) {
const query = {
name: 'insert-test',
text: `
INSERT INTO pr.test (
process,
operation,
key
) VALUES (
$1,
$2,
$3
)`,
values: [
this.db.get()['processID'],
1,
value
]
};
await this.db.get().query(query);
}
}
export interface ITestSql1 {
test1(value: string)
}
PostgresClient.ts
import { PoolClient } from "pg";
export class PostgresClient implements IPostgresClient {
private client: PoolClient;
get(): PoolClient {
return this.client;
}
set(client: PoolClient) {
this.client = client;
}
async begin() {
await this.client.query('BEGIN');
}
async commit() {
await this.client.query('COMMIT');
}
async rollback() {
await this.client.query('ROLLBACK');
}
}
export interface IPostgresClient {
get(): PoolClient;
set(client: PoolClient);
commit();
rollback();
begin();
}
TestManager2.ts и TestSql2.ts в основном совпадают с TestManager1.ts и TestSql1.ts
Моя проблема заключается в том, что каждыйПохоже, что запрос использует только одно и то же соединение postgresql из пула (протестировано с JMeter) и сериализует все запросы API.Pool даже не создает других подключений к postgresql.Похоже, что другие запросы ожидают завершения предыдущего запроса или освобождения соединения postgresql.
Как создать одно соединение (транзакцию) для каждого запроса, используя пул node-postgres, и в то же время не блокировать другие запросы?
Этот код блокирует?Или я что-то не так понял в документации?Или просто этот дизайн не подходит для nodejs?Я действительно не сейчас и застрял на неделю.