@entity-access/entity-access 1.0.105 → 1.0.109
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/ObjectPool.d.ts +7 -5
- package/dist/common/ObjectPool.d.ts.map +1 -1
- package/dist/common/ObjectPool.js +24 -20
- package/dist/common/ObjectPool.js.map +1 -1
- package/dist/common/cache/TimedCache.d.ts.map +1 -1
- package/dist/common/cache/TimedCache.js +2 -4
- package/dist/common/cache/TimedCache.js.map +1 -1
- package/dist/common/cloner.d.ts +4 -0
- package/dist/common/cloner.d.ts.map +1 -0
- package/dist/common/cloner.js +24 -0
- package/dist/common/cloner.js.map +1 -0
- package/dist/drivers/base/BaseDriver.d.ts +2 -0
- package/dist/drivers/base/BaseDriver.d.ts.map +1 -1
- package/dist/drivers/base/BaseDriver.js.map +1 -1
- package/dist/drivers/postgres/PostgreSqlDriver.d.ts +2 -0
- package/dist/drivers/postgres/PostgreSqlDriver.d.ts.map +1 -1
- package/dist/drivers/postgres/PostgreSqlDriver.js +49 -29
- package/dist/drivers/postgres/PostgreSqlDriver.js.map +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.d.ts +1 -0
- package/dist/drivers/sql-server/SqlServerDriver.d.ts.map +1 -1
- package/dist/drivers/sql-server/SqlServerDriver.js +3 -0
- package/dist/drivers/sql-server/SqlServerDriver.js.map +1 -1
- package/dist/entity-query/EntityType.js +6 -6
- package/dist/entity-query/EntityType.js.map +1 -1
- package/dist/query/ast/DebugStringVisitor.js +1 -1
- package/dist/query/ast/DebugStringVisitor.js.map +1 -1
- package/dist/query/ast/ExpressionToSql.d.ts.map +1 -1
- package/dist/query/ast/ExpressionToSql.js.map +1 -1
- package/dist/query/ast/ParameterScope.js +2 -2
- package/dist/query/ast/ParameterScope.js.map +1 -1
- package/dist/query/expander/QueryExpander.d.ts.map +1 -1
- package/dist/query/expander/QueryExpander.js +21 -9
- package/dist/query/expander/QueryExpander.js.map +1 -1
- package/dist/tests/db-tests/tests/select-inverse-one-to-one.js +4 -4
- package/dist/tests/db-tests/tests/select-inverse-one-to-one.js.map +1 -1
- package/dist/tests/db-tests/tests/select-nested.d.ts +3 -0
- package/dist/tests/db-tests/tests/select-nested.d.ts.map +1 -0
- package/dist/tests/db-tests/tests/select-nested.js +25 -0
- package/dist/tests/db-tests/tests/select-nested.js.map +1 -0
- package/dist/tests/model/ShoppingContext.d.ts +3 -0
- package/dist/tests/model/ShoppingContext.d.ts.map +1 -1
- package/dist/tests/model/ShoppingContext.js +14 -2
- package/dist/tests/model/ShoppingContext.js.map +1 -1
- package/dist/tests/model/createContext.js +7 -1
- package/dist/tests/model/createContext.js.map +1 -1
- package/dist/tests/pool/pool-test.d.ts +2 -0
- package/dist/tests/pool/pool-test.d.ts.map +1 -0
- package/dist/tests/pool/pool-test.js +58 -0
- package/dist/tests/pool/pool-test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/common/ObjectPool.ts +41 -24
- package/src/common/cache/TimedCache.ts +2 -4
- package/src/common/cloner.ts +23 -0
- package/src/drivers/base/BaseDriver.ts +2 -0
- package/src/drivers/postgres/PostgreSqlDriver.ts +52 -31
- package/src/drivers/sql-server/SqlServerDriver.ts +4 -0
- package/src/entity-query/EntityType.ts +6 -6
- package/src/query/ast/DebugStringVisitor.ts +1 -1
- package/src/query/ast/ExpressionToSql.ts +1 -0
- package/src/query/ast/ParameterScope.ts +2 -2
- package/src/query/expander/QueryExpander.ts +27 -10
- package/src/tests/db-tests/tests/select-inverse-one-to-one.ts +4 -4
- package/src/tests/db-tests/tests/select-nested.ts +36 -0
- package/src/tests/model/ShoppingContext.ts +11 -0
- package/src/tests/model/createContext.ts +7 -1
- package/src/tests/pool/pool-test.ts +72 -0
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import EntityAccessError from "../../common/EntityAccessError.js";
|
|
3
2
|
import ObjectPool, { IPooledObject } from "../../common/ObjectPool.js";
|
|
4
|
-
import TimedCache from "../../common/cache/TimedCache.js";
|
|
5
3
|
import QueryCompiler from "../../compiler/QueryCompiler.js";
|
|
6
4
|
import Migrations from "../../migrations/Migrations.js";
|
|
7
5
|
import PostgresAutomaticMigrations from "../../migrations/postgres/PostgresAutomaticMigrations.js";
|
|
@@ -29,13 +27,26 @@ const pgID = Symbol("pgID");
|
|
|
29
27
|
|
|
30
28
|
class DbReader implements IDbReader {
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
cursor: Cursor<any>;
|
|
31
|
+
client: IPooledObject<pg.Client>;
|
|
32
|
+
|
|
33
|
+
constructor(
|
|
34
|
+
private command: IQuery,
|
|
35
|
+
private connection: PostgreSqlConnection,
|
|
36
|
+
private signal?: AbortSignal) {
|
|
33
37
|
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
async *next(min = 100) {
|
|
41
|
+
|
|
42
|
+
const connection = await this.connection.getConnection(this.signal);
|
|
43
|
+
if (!this.connection.isInTransaction) {
|
|
44
|
+
this.client = connection;
|
|
45
|
+
}
|
|
46
|
+
const q = toQuery(this.command);
|
|
47
|
+
const cursor = this.cursor = connection.query(new Cursor(q.text, q.values));
|
|
37
48
|
do {
|
|
38
|
-
const rows = await
|
|
49
|
+
const rows = await cursor.read(min);
|
|
39
50
|
yield *rows;
|
|
40
51
|
if (rows.length === 0) {
|
|
41
52
|
break;
|
|
@@ -60,8 +71,6 @@ class DbReader implements IDbReader {
|
|
|
60
71
|
}
|
|
61
72
|
}
|
|
62
73
|
|
|
63
|
-
const poolCache = new TimedCache<string, ObjectPool<pg.Client>>();
|
|
64
|
-
|
|
65
74
|
export default class PostgreSqlDriver extends BaseDriver {
|
|
66
75
|
|
|
67
76
|
public get compiler() {
|
|
@@ -70,30 +79,62 @@ export default class PostgreSqlDriver extends BaseDriver {
|
|
|
70
79
|
|
|
71
80
|
private myCompiler = new QueryCompiler();
|
|
72
81
|
|
|
82
|
+
private pool: ObjectPool<pg.Client>;
|
|
83
|
+
|
|
73
84
|
constructor(private readonly config: IPgSqlConnectionString) {
|
|
74
85
|
super(config);
|
|
86
|
+
this.pool = new ObjectPool({
|
|
87
|
+
asyncFactory: async () => {
|
|
88
|
+
const c = new pg.Client(this.config);
|
|
89
|
+
await c.connect();
|
|
90
|
+
const row = await c.query("SELECT pg_backend_pid() as id");
|
|
91
|
+
c[pgID] = (row.rows as any).id;
|
|
92
|
+
return c;
|
|
93
|
+
},
|
|
94
|
+
destroy(item) {
|
|
95
|
+
return item.end();
|
|
96
|
+
},
|
|
97
|
+
subscribeForRemoval(po, clear) {
|
|
98
|
+
po.on("end", clear);
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
dispose() {
|
|
104
|
+
this.pool?.dispose().catch(console.error);
|
|
75
105
|
}
|
|
76
106
|
|
|
77
107
|
newConnection(): BaseConnection {
|
|
78
|
-
return new PostgreSqlConnection(this);
|
|
108
|
+
return new PostgreSqlConnection(this, this.pool);
|
|
79
109
|
}
|
|
80
110
|
}
|
|
81
111
|
|
|
82
112
|
class PostgreSqlConnection extends BaseConnection {
|
|
83
113
|
|
|
114
|
+
public get isInTransaction() {
|
|
115
|
+
return this.transaction as any as boolean;
|
|
116
|
+
}
|
|
117
|
+
|
|
84
118
|
private transaction: IPooledObject<pg.Client>;
|
|
85
119
|
|
|
86
120
|
private get config() {
|
|
87
121
|
return this.connectionString;
|
|
88
122
|
}
|
|
89
123
|
|
|
124
|
+
constructor(driver: BaseDriver, private pool: ObjectPool<pg.Client>) {
|
|
125
|
+
super(driver);
|
|
126
|
+
}
|
|
127
|
+
|
|
90
128
|
public async createTransaction(): Promise<IBaseTransaction> {
|
|
91
129
|
const tx = await this.getConnection();
|
|
92
130
|
await tx.query("BEGIN");
|
|
93
131
|
return {
|
|
94
132
|
commit: () => tx.query("COMMIT"),
|
|
95
133
|
rollback: () => tx.query("ROLLBACK"),
|
|
96
|
-
dispose: () =>
|
|
134
|
+
dispose: () => {
|
|
135
|
+
this.transaction = null;
|
|
136
|
+
return tx[Symbol.asyncDisposable]();
|
|
137
|
+
}
|
|
97
138
|
};
|
|
98
139
|
}
|
|
99
140
|
|
|
@@ -102,10 +143,7 @@ class PostgreSqlConnection extends BaseConnection {
|
|
|
102
143
|
}
|
|
103
144
|
|
|
104
145
|
public async executeReader(command: IQuery, signal?: AbortSignal): Promise<IDbReader> {
|
|
105
|
-
|
|
106
|
-
const q = toQuery(command);
|
|
107
|
-
const cursor = connection.query(new Cursor(q.text, q.values));
|
|
108
|
-
return new DbReader(cursor, this.transaction ? void 0 : connection);
|
|
146
|
+
return new DbReader(command, this, signal);
|
|
109
147
|
}
|
|
110
148
|
|
|
111
149
|
public async executeQuery(command: IQuery, signal?: AbortSignal) {
|
|
@@ -161,7 +199,7 @@ class PostgreSqlConnection extends BaseConnection {
|
|
|
161
199
|
}
|
|
162
200
|
|
|
163
201
|
|
|
164
|
-
|
|
202
|
+
public async getConnection(signal?: AbortSignal) {
|
|
165
203
|
|
|
166
204
|
if (signal?.aborted) {
|
|
167
205
|
throw new Error("Aborted");
|
|
@@ -171,24 +209,7 @@ class PostgreSqlConnection extends BaseConnection {
|
|
|
171
209
|
return this.transaction;
|
|
172
210
|
}
|
|
173
211
|
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
const pooledClient = poolCache.getOrCreate(key, this, (k, self) => new ObjectPool({
|
|
177
|
-
asyncFactory: async () => {
|
|
178
|
-
const c = new pg.Client(self.config);
|
|
179
|
-
await c.connect();
|
|
180
|
-
const row = await c.query("SELECT pg_backend_pid() as id");
|
|
181
|
-
c[pgID] = (row.rows as any).id;
|
|
182
|
-
return c;
|
|
183
|
-
},
|
|
184
|
-
destroy(item) {
|
|
185
|
-
return item.end();
|
|
186
|
-
},
|
|
187
|
-
subscribeForRemoval(po, clear) {
|
|
188
|
-
po.on("end", clear);
|
|
189
|
-
},
|
|
190
|
-
}));
|
|
191
|
-
const client = await pooledClient.acquire();
|
|
212
|
+
const client = await this.pool.acquire();
|
|
192
213
|
|
|
193
214
|
if (signal) {
|
|
194
215
|
signal.addEventListener("abort", () => this.kill(client[pgID]).catch((error) => console.error(error)));
|
|
@@ -152,9 +152,9 @@ export default class EntityType {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
public selectAllFields() {
|
|
155
|
-
if (this.selectAll) {
|
|
156
|
-
|
|
157
|
-
}
|
|
155
|
+
// if (this.selectAll) {
|
|
156
|
+
// return { ... this.selectAll };
|
|
157
|
+
// }
|
|
158
158
|
const source = this.fullyQualifiedName;
|
|
159
159
|
const as = Expression.parameter(this.name[0] + "1");
|
|
160
160
|
as.model = this;
|
|
@@ -169,9 +169,9 @@ export default class EntityType {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
public selectOneNumber() {
|
|
172
|
-
if (this.selectOne) {
|
|
173
|
-
|
|
174
|
-
}
|
|
172
|
+
// if (this.selectOne) {
|
|
173
|
+
// return { ... this.selectOne };
|
|
174
|
+
// }
|
|
175
175
|
const source = this.fullyQualifiedName;
|
|
176
176
|
const as = Expression.parameter(this.name[0] + "1");
|
|
177
177
|
as.model = this;
|
|
@@ -134,7 +134,7 @@ export default class DebugStringVisitor extends Visitor<string> {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
visitJoinExpression(e: JoinExpression): string {
|
|
137
|
-
return `\n${e.joinType} JOIN ${this.visit(e.source)}\n\t\tON ${this.visit(e.where)}\n`;
|
|
137
|
+
return `\n${e.joinType} JOIN ${this.visit(e.source)} ${this.visit(e.as)} \n\t\tON ${this.visit(e.where)}\n`;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
visitOrderByExpression(e: OrderByExpression): string {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { cloner } from "../../common/cloner.js";
|
|
1
2
|
import EntityType from "../../entity-query/EntityType.js";
|
|
2
3
|
import EntityContext from "../../model/EntityContext.js";
|
|
3
4
|
import EntityQuery from "../../model/EntityQuery.js";
|
|
5
|
+
import DebugStringVisitor from "../ast/DebugStringVisitor.js";
|
|
4
6
|
import { ArrowFunctionExpression, ExistsExpression, Expression, ExpressionType, JoinExpression, NumberLiteral, ParameterExpression, SelectStatement, TableSource } from "../ast/Expressions.js";
|
|
5
7
|
import ReplaceParameter from "../ast/ReplaceParameter.js";
|
|
6
8
|
import ArrowToExpression from "../parser/ArrowToExpression.js";
|
|
@@ -24,6 +26,8 @@ export class QueryExpander {
|
|
|
24
26
|
|
|
25
27
|
expandNode(parent: SelectStatement, model: EntityType, node: ExpressionType): [SelectStatement, EntityType] {
|
|
26
28
|
|
|
29
|
+
parent = cloner.clone(parent);
|
|
30
|
+
|
|
27
31
|
if (node.type === "ArrayExpression") {
|
|
28
32
|
for (const iterator of node.elements) {
|
|
29
33
|
this.expandNode(parent, model, iterator as ExpressionType);
|
|
@@ -83,7 +87,7 @@ export class QueryExpander {
|
|
|
83
87
|
// query = events.includeFilter(query, model, p.value) ?? query;
|
|
84
88
|
// }
|
|
85
89
|
// }
|
|
86
|
-
const select =
|
|
90
|
+
const select = cloner.clone((query as EntityQuery).selectStatement);
|
|
87
91
|
|
|
88
92
|
let where: Expression;
|
|
89
93
|
let joinWhere: Expression;
|
|
@@ -108,17 +112,18 @@ export class QueryExpander {
|
|
|
108
112
|
// ? Expression.logicalAnd(joinWhere, parent.where)
|
|
109
113
|
// : joinWhere;
|
|
110
114
|
|
|
111
|
-
|
|
115
|
+
const keyColumn = model.keys[0].columnName;
|
|
112
116
|
let columnName = fk.columnName;
|
|
113
117
|
// for inverse relation, we need to
|
|
114
118
|
// use primary key of current model
|
|
115
119
|
if (!relation.isCollection) {
|
|
116
|
-
columnName = model.keys[0].columnName;
|
|
117
|
-
keyColumn = select.model.keys[0].columnName;
|
|
120
|
+
columnName = select.model.keys[0].columnName;
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
|
|
121
124
|
const joins = (select.joins ??= []);
|
|
125
|
+
// const joinParameter = Expression.parameter(parent.sourceParameter.name);
|
|
126
|
+
// joinParameter.model = parent.sourceParameter.model;
|
|
122
127
|
joins.push(JoinExpression.create({
|
|
123
128
|
joinType: "LEFT",
|
|
124
129
|
source: parent.source as TableSource,
|
|
@@ -127,21 +132,33 @@ export class QueryExpander {
|
|
|
127
132
|
where: Expression.equal(
|
|
128
133
|
Expression.member(
|
|
129
134
|
parent.sourceParameter,
|
|
130
|
-
Expression.identifier(
|
|
135
|
+
Expression.identifier(keyColumn)
|
|
131
136
|
),
|
|
132
137
|
Expression.member(
|
|
133
138
|
select.sourceParameter,
|
|
134
|
-
Expression.identifier(
|
|
139
|
+
Expression.identifier(columnName)
|
|
135
140
|
)
|
|
136
141
|
)
|
|
137
142
|
}));
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
143
|
+
|
|
144
|
+
if (parent.where) {
|
|
145
|
+
select.where = select.where
|
|
146
|
+
? Expression.logicalAnd(select.where, parent.where)
|
|
147
|
+
: parent.where;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (parent.joins?.length) {
|
|
151
|
+
joins.push(... parent.joins);
|
|
152
|
+
}
|
|
153
|
+
// Object.setPrototypeOf(select, SelectStatement.prototype);
|
|
154
|
+
// const text = DebugStringVisitor.expressionToString(select);
|
|
155
|
+
// console.log(text);
|
|
141
156
|
(this.select.include ??= []).push(select);
|
|
142
157
|
return [select, relation.relatedEntity];
|
|
143
158
|
}
|
|
144
159
|
|
|
160
|
+
// if we can skip this if join already exists !!
|
|
161
|
+
|
|
145
162
|
joinWhere = Expression.equal(
|
|
146
163
|
Expression.member(
|
|
147
164
|
parent.sourceParameter,
|
|
@@ -153,7 +170,7 @@ export class QueryExpander {
|
|
|
153
170
|
)
|
|
154
171
|
);
|
|
155
172
|
|
|
156
|
-
parent = { ... parent, fields: [ NumberLiteral.one ]
|
|
173
|
+
parent = cloner.clone({ ... parent, fields: [ NumberLiteral.one ]});
|
|
157
174
|
|
|
158
175
|
parent.where = parent.where
|
|
159
176
|
? Expression.logicalAnd(parent.where, joinWhere)
|
|
@@ -10,11 +10,11 @@ export default async function(this: TestConfig) {
|
|
|
10
10
|
|
|
11
11
|
const context = await createContext(this.driver);
|
|
12
12
|
|
|
13
|
-
const count = await context.users.all()
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
// const count = await context.users.all()
|
|
14
|
+
// .where({} , (p) => (x) => x.profile.photos.some((a) => true) || x.profile.photos.some((a) => true))
|
|
15
|
+
// .count();
|
|
16
16
|
|
|
17
|
-
assert.equal(0, count);
|
|
17
|
+
// assert.equal(0, count);
|
|
18
18
|
|
|
19
19
|
// include inverse...
|
|
20
20
|
const all = await context.users.all()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { TestConfig } from "../../TestConfig.js";
|
|
3
|
+
import { createContext, headPhoneCategory } from "../../model/createContext.js";
|
|
4
|
+
|
|
5
|
+
export default async function(this: TestConfig) {
|
|
6
|
+
|
|
7
|
+
if (!this.db) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const context = await createContext(this.driver);
|
|
12
|
+
|
|
13
|
+
let headphone = await context.products
|
|
14
|
+
.where({ name: "Jabber Head Phones" }, (p) => (x) => x.name === p.name)
|
|
15
|
+
.include((x) => x.categories.forEach((c) => c.category.children))
|
|
16
|
+
.first();
|
|
17
|
+
|
|
18
|
+
assert.notEqual(null, headphone);
|
|
19
|
+
|
|
20
|
+
let child = headphone.categories[0].category.children[0];
|
|
21
|
+
assert.notEqual(null, child);
|
|
22
|
+
|
|
23
|
+
// select nested with filter
|
|
24
|
+
|
|
25
|
+
const blueTooth = "Bluetooth";
|
|
26
|
+
headphone = await context.products
|
|
27
|
+
.where({ name: "Jabber Head Phones", blueTooth }, (p) => (x) => x.name === p.name
|
|
28
|
+
&& x.categories.some((c) =>
|
|
29
|
+
c.category.children.some((cc) => cc.name === p.blueTooth)))
|
|
30
|
+
.include((x) => x.categories.forEach((c) => c.category.children))
|
|
31
|
+
.first();
|
|
32
|
+
|
|
33
|
+
child = headphone.categories[0].category.children[0];
|
|
34
|
+
assert.notEqual(null, child);
|
|
35
|
+
|
|
36
|
+
}
|
|
@@ -66,10 +66,21 @@ export class Category {
|
|
|
66
66
|
@Column({ length: 200 })
|
|
67
67
|
public name: string;
|
|
68
68
|
|
|
69
|
+
@Column({ dataType: "Char", length: 200, nullable: true })
|
|
70
|
+
@RelateTo(Category, {
|
|
71
|
+
property: (c) => c.parent,
|
|
72
|
+
inverseProperty: (c) => c.children
|
|
73
|
+
})
|
|
74
|
+
public parentID: string;
|
|
75
|
+
|
|
69
76
|
public productCategories: ProductCategory[];
|
|
70
77
|
|
|
71
78
|
public users: UserCategory[];
|
|
72
79
|
|
|
80
|
+
public children: Category[];
|
|
81
|
+
|
|
82
|
+
public parent: Category;
|
|
83
|
+
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
@Table("UserProfile")
|
|
@@ -236,7 +236,13 @@ export const headPhoneCategory = "head-phones";
|
|
|
236
236
|
function addHeadPhones(context: ShoppingContext, now: Date, owner: User) {
|
|
237
237
|
const category = context.categories.add({
|
|
238
238
|
name: "Headphones",
|
|
239
|
-
categoryID: headPhoneCategory
|
|
239
|
+
categoryID: headPhoneCategory,
|
|
240
|
+
children: [
|
|
241
|
+
context.categories.add({
|
|
242
|
+
name: "Bluetooth",
|
|
243
|
+
categoryID: `${headPhoneCategory}/blue-tooth`
|
|
244
|
+
})
|
|
245
|
+
]
|
|
240
246
|
});
|
|
241
247
|
|
|
242
248
|
const startDate = new Date();
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import assert from "assert";
|
|
3
|
+
import ObjectPool from "../../common/ObjectPool.js";
|
|
4
|
+
import sleep from "../../common/sleep.js";
|
|
5
|
+
|
|
6
|
+
export default async function () {
|
|
7
|
+
const pool = new ObjectPool({
|
|
8
|
+
asyncFactory: async () => {
|
|
9
|
+
await sleep(10);
|
|
10
|
+
return Promise.resolve({});
|
|
11
|
+
},
|
|
12
|
+
subscribeForRemoval: (po, clear) => void 0,
|
|
13
|
+
destroy(item) {
|
|
14
|
+
return sleep(10);
|
|
15
|
+
},
|
|
16
|
+
maxSize: 5,
|
|
17
|
+
poolSize: 2,
|
|
18
|
+
maxWait: 100
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const c1 = await pool.acquire();
|
|
22
|
+
const c2 = await pool.acquire();
|
|
23
|
+
|
|
24
|
+
await c1[Symbol.asyncDisposable]();
|
|
25
|
+
|
|
26
|
+
assert.equal(pool.freeSize, 1);
|
|
27
|
+
|
|
28
|
+
const c3 = await pool.acquire();
|
|
29
|
+
assert.equal(c1, c3);
|
|
30
|
+
|
|
31
|
+
assert.equal(pool.freeSize, 0);
|
|
32
|
+
|
|
33
|
+
const c4 = await pool.acquire();
|
|
34
|
+
assert.notEqual(c4, c1);
|
|
35
|
+
assert.notEqual(c4, c2);
|
|
36
|
+
|
|
37
|
+
assert.equal(pool.currentSize, 3);
|
|
38
|
+
|
|
39
|
+
await c3[Symbol.asyncDisposable]();
|
|
40
|
+
|
|
41
|
+
assert.equal(pool.currentSize, 3);
|
|
42
|
+
|
|
43
|
+
await c4[Symbol.asyncDisposable]();
|
|
44
|
+
await c2[Symbol.asyncDisposable]();
|
|
45
|
+
|
|
46
|
+
assert.equal(pool.currentSize, 2);
|
|
47
|
+
|
|
48
|
+
assert.equal(pool.freeSize, 2);
|
|
49
|
+
|
|
50
|
+
await pool.acquire();
|
|
51
|
+
await pool.acquire();
|
|
52
|
+
await pool.acquire();
|
|
53
|
+
await pool.acquire();
|
|
54
|
+
const last = await pool.acquire();
|
|
55
|
+
let lastError;
|
|
56
|
+
try {
|
|
57
|
+
await pool.acquire();
|
|
58
|
+
} catch (error) {
|
|
59
|
+
lastError = error;
|
|
60
|
+
}
|
|
61
|
+
if (!lastError) {
|
|
62
|
+
assert.fail("Failed");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// free last after few milliseconds
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
last[Symbol.asyncDisposable]().catch(console.error);
|
|
68
|
+
}, 10);
|
|
69
|
+
|
|
70
|
+
// this should not fail
|
|
71
|
+
await pool.acquire();
|
|
72
|
+
}
|