fib-pool 1.6.2 → 1.7.1
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/Readme.md +61 -4
- package/package.json +16 -33
- package/src/index.cts +18 -0
- package/src/index.d.cts +3 -0
- package/src/index.ts +278 -132
- package/tsconfig.json +6 -10
- package/.travis.yml +0 -99
- package/appveyor.yml +0 -26
- package/lib/index.js +0 -163
- package/typings/index.d.ts +0 -43
package/Readme.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
## Generic resource pooling for fibjs
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.org/package/fib-pool)
|
|
4
|
-
[](https://travis-ci.org/fibjs/fib-pool)
|
|
5
|
-
[](https://ci.appveyor.com/project/richardo2016/fib-pool)
|
|
6
4
|
|
|
7
5
|
## Install
|
|
8
6
|
|
|
@@ -13,7 +11,8 @@ npm install fib-pool [--save]
|
|
|
13
11
|
## Test
|
|
14
12
|
|
|
15
13
|
```sh
|
|
16
|
-
npm
|
|
14
|
+
npm test # fibjs test
|
|
15
|
+
npm run typecheck # fibjs --check, including test/types.ts
|
|
17
16
|
```
|
|
18
17
|
|
|
19
18
|
## Creating a pool
|
|
@@ -103,6 +102,60 @@ var res = p("test", (conn) => {
|
|
|
103
102
|
|
|
104
103
|
```
|
|
105
104
|
|
|
105
|
+
## Options
|
|
106
|
+
|
|
107
|
+
| option | type | default | notes |
|
|
108
|
+
|---|---|---|---|
|
|
109
|
+
| `create` | `(name) => item` | — | required; throwing is a failure, retried up to `retry` times |
|
|
110
|
+
| `destroy` | `(item) => void` | close/destroy/dispose | defaults to calling whichever of those three the item provides |
|
|
111
|
+
| `maxsize` | positive integer | `10` | caps both concurrency and the number of idle items |
|
|
112
|
+
| `timeout` | positive number (ms) | `60000` | how long an idle item is kept |
|
|
113
|
+
| `retry` | positive integer | `1` | how many times `create` is attempted before giving up |
|
|
114
|
+
| `strict` | boolean | `true` | see below |
|
|
115
|
+
|
|
116
|
+
The pooled item is unconstrained: `create` may return an object, a class
|
|
117
|
+
instance, a function, or a primitive. The default `destroy` calls whichever of
|
|
118
|
+
`close` / `destroy` / `dispose` the item provides and ignores items that have
|
|
119
|
+
none of them.
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
var p = Pool(() => 10); // a primitive item
|
|
123
|
+
p((v) => v + 1);
|
|
124
|
+
|
|
125
|
+
var q = Pool(() => ({ value: 1 })); // a plain object, nothing to destroy
|
|
126
|
+
q((o) => o.value);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Invalid `maxsize`, `timeout` and `retry` values throw a `TypeError` when the
|
|
130
|
+
pool is created rather than being silently coerced:
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
Pool({ create: () => ({}), maxsize: 0 }); // TypeError: maxsize must be a positive integer, received 0
|
|
134
|
+
Pool({ create: () => ({}), timeout: -5 }); // TypeError: timeout must be a positive number, received -5
|
|
135
|
+
Pool({ create: () => ({}), retry: true }); // TypeError: retry must be a positive integer, received true
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The idle list is capped by `maxsize` as well: a pool used with more names than
|
|
139
|
+
that evicts the least recently used item (and destroys it) instead of keeping
|
|
140
|
+
one idle item per name.
|
|
141
|
+
|
|
142
|
+
## Reentrancy
|
|
143
|
+
|
|
144
|
+
A pool cannot be acquired twice from the same fiber. The inner call would wait
|
|
145
|
+
for a permit that the outer call is holding, which never arrives, so it is
|
|
146
|
+
rejected instead of deadlocking:
|
|
147
|
+
|
|
148
|
+
```js
|
|
149
|
+
var p = Pool({ create: () => ({}), maxsize: 1 });
|
|
150
|
+
|
|
151
|
+
p(() => {
|
|
152
|
+
p(() => {}); // Error: Cannot pool again from the same fiber
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Nesting different pools, or acquiring the same pool from another fiber, works as
|
|
157
|
+
expected.
|
|
158
|
+
|
|
106
159
|
## Strict mode (default: enabled)
|
|
107
160
|
|
|
108
161
|
By default, the pool uses strict mode to prevent accessing pooled objects outside of the callback function. This helps prevent resource leaks and ensures proper resource management.
|
|
@@ -127,9 +180,13 @@ p((obj) => {
|
|
|
127
180
|
leaked.getValue(); // Error!
|
|
128
181
|
```
|
|
129
182
|
|
|
130
|
-
|
|
183
|
+
The guarded object behaves like the item for reading and inspection —
|
|
184
|
+
`key in obj`, `Object.keys(obj)`, `for...in`, `JSON.stringify(obj)` and
|
|
185
|
+
`util.inspect(obj)` all report the item's own members — while the guards remain:
|
|
186
|
+
|
|
131
187
|
- Setting properties on pooled objects
|
|
132
188
|
- Calling `close()`, `destroy()`, or `dispose()` methods directly
|
|
189
|
+
- Extracting a method and calling it after the callback returned
|
|
133
190
|
|
|
134
191
|
To disable strict mode:
|
|
135
192
|
|
package/package.json
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fib-pool",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Generic resource pooling for fibjs",
|
|
5
|
-
"main": "./src",
|
|
6
|
-
"types": "
|
|
5
|
+
"main": "./src/index.cts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./src/index.ts",
|
|
12
|
+
"default": "./src/index.ts"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./src/index.d.cts",
|
|
16
|
+
"default": "./src/index.cts"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
8
20
|
"repository": "git://github.com/fibjs/fib-pool.git",
|
|
9
21
|
"author": "Liu Hu <lion@9465.net>",
|
|
10
|
-
"contributors": [
|
|
11
|
-
{
|
|
12
|
-
"name": "Richard",
|
|
13
|
-
"email": "richardo2016@gmail.com"
|
|
14
|
-
}
|
|
15
|
-
],
|
|
16
22
|
"homepage": "https://github.com/fibjs/fib-pool",
|
|
17
23
|
"license": "MIT",
|
|
18
24
|
"keywords": [
|
|
@@ -22,29 +28,6 @@
|
|
|
22
28
|
],
|
|
23
29
|
"scripts": {
|
|
24
30
|
"test": "fibjs test",
|
|
25
|
-
"typecheck": "
|
|
26
|
-
"ci": "npm run typecheck && npm run test"
|
|
27
|
-
},
|
|
28
|
-
"devDependencies": {
|
|
29
|
-
"@fibjs/ci": "^2.3.0",
|
|
30
|
-
"@fibjs/types": "^0.27.1",
|
|
31
|
-
"fib-typify": "^0.8.4",
|
|
32
|
-
"typescript": "^5.9.3"
|
|
33
|
-
},
|
|
34
|
-
"ci": {
|
|
35
|
-
"type": "travis, appveyor",
|
|
36
|
-
"version": [
|
|
37
|
-
"0.21.0",
|
|
38
|
-
"0.22.0",
|
|
39
|
-
"0.23.0",
|
|
40
|
-
"0.24.0",
|
|
41
|
-
"0.25.0",
|
|
42
|
-
"0.26.0",
|
|
43
|
-
"0.26.1",
|
|
44
|
-
"0.27.0",
|
|
45
|
-
"0.28.0",
|
|
46
|
-
"0.29.0",
|
|
47
|
-
"0.30.0"
|
|
48
|
-
]
|
|
31
|
+
"typecheck": "fibjs --check"
|
|
49
32
|
}
|
|
50
33
|
}
|
package/src/index.cts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CommonJS entry point.
|
|
3
|
+
*
|
|
4
|
+
* The pool is implemented in `index.ts` as an ES module, so requiring that
|
|
5
|
+
* file yields the module namespace object (`{ default, __esModule }`) rather
|
|
6
|
+
* than the factory. Callers of `require('fib-pool')` expect the export to *be*
|
|
7
|
+
* the factory function, so this bridge unwraps the default export.
|
|
8
|
+
*
|
|
9
|
+
* A static `import` is not an option here: this file is CommonJS, so it must
|
|
10
|
+
* load the implementation through `require` to get the namespace object.
|
|
11
|
+
*
|
|
12
|
+
* `module.exports =` is used instead of `export =` because fibjs runs
|
|
13
|
+
* TypeScript in strip-only mode, which rejects export assignments. The type of
|
|
14
|
+
* this file is described by the sibling `index.d.cts`.
|
|
15
|
+
*/
|
|
16
|
+
const impl = require('./index.ts');
|
|
17
|
+
|
|
18
|
+
module.exports = impl.default;
|
package/src/index.d.cts
ADDED
package/src/index.ts
CHANGED
|
@@ -2,29 +2,36 @@ import * as coroutine from 'coroutine';
|
|
|
2
2
|
import * as util from 'util';
|
|
3
3
|
|
|
4
4
|
declare namespace FibPoolNS {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The shape the default destroy looks for. All three members are optional:
|
|
7
|
+
* it calls whichever of them the item actually provides, and a non-function
|
|
8
|
+
* value (a plain property) is ignored.
|
|
9
|
+
*
|
|
10
|
+
* This is deliberately *not* a constraint on the pooled item. Every member
|
|
11
|
+
* is optional, which makes it a weak type, and TypeScript rejects any type
|
|
12
|
+
* without a property in common with a weak type. Constraining the item to
|
|
13
|
+
* it would reject the perfectly valid `Pool(() => 10)` and
|
|
14
|
+
* `Pool(() => ({ value: 1 }))`, so the constraint is absent and the cast to
|
|
15
|
+
* this shape happens only inside the default destroy, where a primitive
|
|
16
|
+
* simply has no such member to call.
|
|
17
|
+
*/
|
|
7
18
|
interface DippedItemStruct {
|
|
8
|
-
close?:
|
|
9
|
-
destroy?:
|
|
10
|
-
dispose?:
|
|
19
|
+
close?: unknown;
|
|
20
|
+
destroy?: unknown;
|
|
21
|
+
dispose?: unknown;
|
|
11
22
|
}
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
/**
|
|
25
|
+
* `T` is the pooled item and may be anything `create` returns, including a
|
|
26
|
+
* primitive. It is only inferred, never constrained.
|
|
27
|
+
*/
|
|
28
|
+
interface FibPoolOptionArgs<T = any> {
|
|
29
|
+
create: (name: string) => T;
|
|
15
30
|
destroy?: (item?: T) => any;
|
|
16
|
-
maxsize?: number
|
|
17
|
-
timeout?: number
|
|
18
|
-
retry?: number
|
|
19
|
-
strict?: boolean
|
|
20
|
-
}
|
|
21
|
-
interface FibPoolOptionResult<T extends DippedItemStruct = {}> {
|
|
22
|
-
create: FibPoolOptionArgs<T>['create']
|
|
23
|
-
destroy: FibPoolOptionArgs<T>['destroy']
|
|
24
|
-
maxsize: FibPoolOptionArgs<T>['maxsize']
|
|
25
|
-
timeout: FibPoolOptionArgs<T>['timeout']
|
|
26
|
-
retry: FibPoolOptionArgs<T>['retry']
|
|
27
|
-
strict: FibPoolOptionArgs<T>['strict']
|
|
31
|
+
maxsize?: number;
|
|
32
|
+
timeout?: number;
|
|
33
|
+
retry?: number;
|
|
34
|
+
strict?: boolean;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
interface FibPoolDipperFn<T_CREATED_ITEM, T_POOL_FUNC_RETURN = any> {
|
|
@@ -35,62 +42,171 @@ declare namespace FibPoolNS {
|
|
|
35
42
|
<T_RETURN = T_POOL_FUNC_RETURN>(name: string, func: FibPoolDipperFn<T_CREATED_ITEM, T_RETURN>): T_RETURN
|
|
36
43
|
<T_RETURN = T_POOL_FUNC_RETURN>(func: FibPoolDipperFn<T_CREATED_ITEM, T_RETURN>): T_RETURN
|
|
37
44
|
} & {
|
|
38
|
-
connections
|
|
39
|
-
info
|
|
45
|
+
connections(): number;
|
|
46
|
+
info(): {
|
|
40
47
|
maxsize: number;
|
|
41
48
|
count: number;
|
|
42
49
|
running: number;
|
|
43
50
|
wait: number;
|
|
44
51
|
timeout: number;
|
|
45
|
-
};
|
|
46
|
-
clear
|
|
52
|
+
};
|
|
53
|
+
clear(): void;
|
|
47
54
|
}
|
|
48
55
|
}
|
|
49
56
|
|
|
50
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Calls the value when it is a function and ignores it otherwise: a pooled item
|
|
59
|
+
* may expose a plain property named close/destroy/dispose.
|
|
60
|
+
*/
|
|
61
|
+
function callIfFunction(v: unknown) {
|
|
62
|
+
if (util.isFunction(v))
|
|
63
|
+
(v as (...args: any[]) => any)();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `maxsize` and `retry` are counts, `timeout` is a duration. Both are rejected
|
|
68
|
+
* up front instead of being silently coerced into a default or handed to the
|
|
69
|
+
* semaphore, which would fail far from the option that is wrong.
|
|
70
|
+
*/
|
|
71
|
+
function toPositiveInteger(value: unknown, name: string): number {
|
|
72
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0 || Math.floor(value) !== value)
|
|
73
|
+
throw new TypeError(`${name} must be a positive integer, received ${String(value)}`);
|
|
74
|
+
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function toPositiveNumber(value: unknown, name: string): number {
|
|
79
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0)
|
|
80
|
+
throw new TypeError(`${name} must be a positive number, received ${String(value)}`);
|
|
81
|
+
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The pool always hands out an Error: `create` or the callback may throw a
|
|
87
|
+
* string, a number, or nothing at all, and the caller expects to be able to
|
|
88
|
+
* read `.message`. A thrown falsy value (0, '', false, null, undefined) is still
|
|
89
|
+
* a failure and must not be mistaken for a successful create, so this returns an
|
|
90
|
+
* Error for every input.
|
|
91
|
+
*/
|
|
92
|
+
function toError(e: unknown): Error {
|
|
93
|
+
if (e instanceof Error)
|
|
94
|
+
return e;
|
|
95
|
+
|
|
51
96
|
if (typeof e === 'string')
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
97
|
+
return new Error(e);
|
|
98
|
+
|
|
99
|
+
return new Error(String(e));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Guards a pooled item while the callback runs. The item is read through a
|
|
104
|
+
* getter rather than captured by value: once it goes back to the pool the
|
|
105
|
+
* handle must stop working, which is what the "outside of pool scope" error
|
|
106
|
+
* reports.
|
|
107
|
+
*
|
|
108
|
+
* The reflection traps matter as much as the getter: without them `key in obj`,
|
|
109
|
+
* `Object.keys`, `for...in` and `JSON.stringify` all see the empty proxy target
|
|
110
|
+
* instead of the item.
|
|
111
|
+
*/
|
|
112
|
+
function wrapStrict<T extends object>(item: () => T | undefined): T {
|
|
113
|
+
const current = () => {
|
|
114
|
+
const o = item();
|
|
115
|
+
if (o === undefined)
|
|
116
|
+
throw new Error("access object outside of pool scope");
|
|
117
|
+
|
|
118
|
+
return o;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return new Proxy({}, {
|
|
122
|
+
get(target, prop) {
|
|
123
|
+
if (prop === 'close' || prop === 'destroy' || prop === 'dispose')
|
|
124
|
+
throw new Error("Cannot close/destroy/dispose");
|
|
125
|
+
|
|
126
|
+
const o = current();
|
|
127
|
+
const value = (o as any)[prop];
|
|
128
|
+
if (typeof value === 'function') {
|
|
129
|
+
/* the item is resolved again when the method runs: a method
|
|
130
|
+
extracted inside the callback and called after it returned
|
|
131
|
+
must not keep the item alive outside its scope */
|
|
132
|
+
return function () {
|
|
133
|
+
const self = current();
|
|
134
|
+
return (self as any)[prop].apply(self, arguments);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
},
|
|
139
|
+
has(target, prop) {
|
|
140
|
+
/* no close/destroy/dispose refusal here: the key is reported like
|
|
141
|
+
any other (ownKeys lists it too), only reading or calling those
|
|
142
|
+
members is refused, in `get` */
|
|
143
|
+
return Reflect.has(current() as object, prop);
|
|
144
|
+
},
|
|
145
|
+
ownKeys() {
|
|
146
|
+
return Reflect.ownKeys(current() as object);
|
|
147
|
+
},
|
|
148
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
149
|
+
const d = Reflect.getOwnPropertyDescriptor(current() as object, prop);
|
|
150
|
+
|
|
151
|
+
/* every key of the proxy target is configurable: a descriptor that
|
|
152
|
+
claims otherwise would break the proxy invariants */
|
|
153
|
+
return d && Object.assign(d, { configurable: true });
|
|
154
|
+
},
|
|
155
|
+
set() {
|
|
156
|
+
throw new Error("Cannot set property");
|
|
157
|
+
}
|
|
158
|
+
}) as T;
|
|
55
159
|
}
|
|
56
160
|
|
|
57
161
|
export default function GetPool<
|
|
58
|
-
T_CREATED_ITEM
|
|
59
|
-
T_POOL_FUNC_RETURN
|
|
162
|
+
T_CREATED_ITEM,
|
|
163
|
+
T_POOL_FUNC_RETURN = any
|
|
60
164
|
> (
|
|
61
165
|
_opt: FibPoolNS.FibPoolOptionArgs<T_CREATED_ITEM> | FibPoolNS.FibPoolOptionArgs<T_CREATED_ITEM>['create'],
|
|
62
166
|
maxsize?: number,
|
|
63
167
|
timeout?: number
|
|
64
168
|
): FibPoolNS.FibPool<T_CREATED_ITEM, T_POOL_FUNC_RETURN> {
|
|
65
169
|
/* clean input arguments :start */
|
|
66
|
-
let opt
|
|
170
|
+
let opt: FibPoolNS.FibPoolOptionArgs<T_CREATED_ITEM>;
|
|
171
|
+
|
|
67
172
|
if (util.isFunction(_opt)) {
|
|
68
|
-
opt =
|
|
69
|
-
create: _opt,
|
|
173
|
+
opt = {
|
|
174
|
+
create: _opt as (name: string) => T_CREATED_ITEM,
|
|
70
175
|
maxsize: maxsize,
|
|
71
176
|
timeout: timeout
|
|
72
177
|
};
|
|
178
|
+
} else {
|
|
179
|
+
opt = _opt as FibPoolNS.FibPoolOptionArgs<T_CREATED_ITEM>;
|
|
73
180
|
}
|
|
74
181
|
|
|
75
182
|
const create = opt.create;
|
|
76
|
-
const destroy = opt.destroy || ((o: {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
|
|
183
|
+
const destroy = opt.destroy || ((o: unknown) => {
|
|
184
|
+
/* create may return null/undefined or any primitive: there is nothing
|
|
185
|
+
to destroy then. Functions are kept, since they can carry members. */
|
|
186
|
+
if (o === null || o === undefined)
|
|
187
|
+
return;
|
|
188
|
+
|
|
189
|
+
if (typeof o !== 'object' && typeof o !== 'function')
|
|
190
|
+
return;
|
|
191
|
+
|
|
192
|
+
const item = o as FibPoolNS.DippedItemStruct;
|
|
193
|
+
|
|
194
|
+
callIfFunction(item.close);
|
|
195
|
+
callIfFunction(item.destroy);
|
|
196
|
+
callIfFunction(item.dispose);
|
|
84
197
|
});
|
|
85
198
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
199
|
+
const maxsizeValue = opt.maxsize === undefined ? 10 : toPositiveInteger(opt.maxsize, 'maxsize');
|
|
200
|
+
let timeoutValue = opt.timeout === undefined ? 60000 : toPositiveNumber(opt.timeout, 'timeout');
|
|
201
|
+
|
|
202
|
+
/* the idle scan runs at a tenth of the timeout, but never more often than
|
|
203
|
+
every 10ms */
|
|
204
|
+
let tm = timeoutValue / 10;
|
|
89
205
|
if (tm < 10)
|
|
90
206
|
tm = 10;
|
|
91
207
|
|
|
92
|
-
const retry = opt.retry
|
|
93
|
-
const
|
|
208
|
+
const retry = opt.retry === undefined ? 1 : toPositiveInteger(opt.retry, 'retry');
|
|
209
|
+
const strictMode = opt.strict === undefined ? true : opt.strict;
|
|
94
210
|
/* clean input arguments :end */
|
|
95
211
|
|
|
96
212
|
let pools = <{
|
|
@@ -109,17 +225,16 @@ export default function GetPool<
|
|
|
109
225
|
let count = 0;
|
|
110
226
|
let running = 0;
|
|
111
227
|
|
|
112
|
-
const sem = new coroutine.Semaphore(
|
|
113
|
-
let clearTimer: Class_Timer;
|
|
228
|
+
const sem = new coroutine.Semaphore(maxsizeValue);
|
|
229
|
+
let clearTimer: Class_Timer | null = null;
|
|
114
230
|
|
|
115
231
|
function clearPool() {
|
|
116
|
-
let c: typeof pools[any];
|
|
117
232
|
const d = new Date().getTime();
|
|
118
233
|
|
|
119
234
|
while (count) {
|
|
120
|
-
c = pools[0];
|
|
235
|
+
const c = pools[0];
|
|
121
236
|
|
|
122
|
-
if (d - c.time.getTime() >
|
|
237
|
+
if (d - c.time.getTime() > timeoutValue) {
|
|
123
238
|
pools = pools.slice(1);
|
|
124
239
|
count--;
|
|
125
240
|
|
|
@@ -135,18 +250,22 @@ export default function GetPool<
|
|
|
135
250
|
clearTimer = null;
|
|
136
251
|
}
|
|
137
252
|
} else if (!clearTimer) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
253
|
+
/* the timer must not hold the process alive: the pool is idle
|
|
254
|
+
between uses */
|
|
255
|
+
clearTimer = setInterval(clearPool, tm).unref();
|
|
141
256
|
}
|
|
142
257
|
}
|
|
143
258
|
|
|
259
|
+
/**
|
|
260
|
+
* Hand the item back: wake the first waiter bound to `name`, or park the
|
|
261
|
+
* item in the idle list. An errored item is never parked, but a successful
|
|
262
|
+
* create may legitimately produce `undefined` and is parked as is.
|
|
263
|
+
*/
|
|
144
264
|
function putback(
|
|
145
|
-
name:
|
|
146
|
-
o: T_CREATED_ITEM,
|
|
265
|
+
name: string,
|
|
266
|
+
o: T_CREATED_ITEM | undefined,
|
|
147
267
|
e?: Error
|
|
148
268
|
) {
|
|
149
|
-
e = ensureError(e);
|
|
150
269
|
for (let i = 0; i < jobs.length; i++) {
|
|
151
270
|
const job = jobs[i];
|
|
152
271
|
if (job.name === name) {
|
|
@@ -158,26 +277,38 @@ export default function GetPool<
|
|
|
158
277
|
}
|
|
159
278
|
}
|
|
160
279
|
|
|
161
|
-
if (e === undefined)
|
|
280
|
+
if (e === undefined) {
|
|
281
|
+
/* The idle list is capped by maxsize: a pool used with more names
|
|
282
|
+
than that would otherwise keep one idle item per name and grow
|
|
283
|
+
without bound. The oldest idle item gives way to the one just
|
|
284
|
+
returned, so the most recently used names stay cached. */
|
|
285
|
+
if (count >= maxsizeValue && count) {
|
|
286
|
+
const evicted = pools[0];
|
|
287
|
+
pools = pools.slice(1);
|
|
288
|
+
count--;
|
|
289
|
+
coroutine.start(destroy, evicted.o);
|
|
290
|
+
}
|
|
291
|
+
|
|
162
292
|
pools[count++] = {
|
|
163
|
-
o: o,
|
|
293
|
+
o: o as T_CREATED_ITEM,
|
|
164
294
|
name: name,
|
|
165
295
|
time: new Date()
|
|
166
296
|
};
|
|
297
|
+
}
|
|
167
298
|
}
|
|
168
299
|
|
|
169
300
|
function connect(name: string) {
|
|
170
|
-
let o: T_CREATED_ITEM;
|
|
171
|
-
let
|
|
172
|
-
let err: Error;
|
|
301
|
+
let o: T_CREATED_ITEM | undefined;
|
|
302
|
+
let err: Error | undefined;
|
|
173
303
|
|
|
174
|
-
|
|
304
|
+
for (let cn = 1; ; cn++) {
|
|
175
305
|
try {
|
|
176
306
|
o = create(name);
|
|
177
307
|
break;
|
|
178
308
|
} catch (e) {
|
|
179
|
-
|
|
180
|
-
|
|
309
|
+
/* any thrown value is a failure, including 0 or '' */
|
|
310
|
+
if (cn >= retry) {
|
|
311
|
+
err = toError(e);
|
|
181
312
|
break;
|
|
182
313
|
}
|
|
183
314
|
}
|
|
@@ -186,100 +317,115 @@ export default function GetPool<
|
|
|
186
317
|
putback(name, o, err);
|
|
187
318
|
}
|
|
188
319
|
|
|
189
|
-
|
|
320
|
+
/* The fiber is used as fiber-local storage: it is the only place a marker
|
|
321
|
+
can live without leaking between fibers. A fiber that already holds an
|
|
322
|
+
item from this pool would wait on itself when it asks again, which the
|
|
323
|
+
semaphore can never satisfy once every permit is out. */
|
|
324
|
+
const fiberDepth = Symbol('fib-pool depth');
|
|
325
|
+
|
|
326
|
+
type FiberState = Class_Fiber & { [fiberDepth]?: true };
|
|
327
|
+
|
|
328
|
+
function enterFiber(): FiberState {
|
|
329
|
+
const fiber = coroutine.current() as FiberState;
|
|
330
|
+
|
|
331
|
+
if (fiber[fiberDepth])
|
|
332
|
+
throw new Error("Cannot pool again from the same fiber: the pool is already held by this callback");
|
|
333
|
+
|
|
334
|
+
fiber[fiberDepth] = true;
|
|
335
|
+
|
|
336
|
+
return fiber;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function leaveFiber(fiber: FiberState) {
|
|
340
|
+
delete fiber[fiberDepth];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const pool = ((
|
|
190
344
|
name: string | FibPoolNS.FibPoolDipperFn<T_CREATED_ITEM, T_POOL_FUNC_RETURN>,
|
|
191
345
|
func?: FibPoolNS.FibPoolDipperFn<T_CREATED_ITEM, T_POOL_FUNC_RETURN>
|
|
192
346
|
) => {
|
|
193
347
|
if (typeof name === 'function') {
|
|
194
|
-
func = name
|
|
348
|
+
func = name;
|
|
195
349
|
name = "";
|
|
196
|
-
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const dip = func as FibPoolNS.FibPoolDipperFn<T_CREATED_ITEM, T_POOL_FUNC_RETURN>;
|
|
197
353
|
|
|
198
354
|
let r: T_POOL_FUNC_RETURN;
|
|
199
|
-
let o:
|
|
200
|
-
let
|
|
355
|
+
let o: T_CREATED_ITEM | undefined;
|
|
356
|
+
let reused = false;
|
|
357
|
+
const fiber = enterFiber();
|
|
201
358
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
359
|
+
try {
|
|
360
|
+
clearPool();
|
|
361
|
+
sem.acquire();
|
|
362
|
+
|
|
363
|
+
if (count) {
|
|
364
|
+
for (let i = count - 1; i >= 0; i--)
|
|
365
|
+
if (pools[i].name === name) {
|
|
366
|
+
reused = true
|
|
367
|
+
o = pools[i].o;
|
|
368
|
+
pools.splice(i, 1);
|
|
369
|
+
count--;
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
215
373
|
|
|
216
|
-
|
|
217
|
-
|
|
374
|
+
if (!reused) {
|
|
375
|
+
coroutine.start(connect, name);
|
|
218
376
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
377
|
+
const job: typeof jobs[any] = {
|
|
378
|
+
name: name,
|
|
379
|
+
ev: new coroutine.Event()
|
|
380
|
+
};
|
|
381
|
+
jobs.push(job);
|
|
382
|
+
|
|
383
|
+
job.ev.wait();
|
|
384
|
+
if (job.e) {
|
|
385
|
+
sem.post();
|
|
386
|
+
throw job.e;
|
|
387
|
+
}
|
|
388
|
+
o = job.o;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
running++;
|
|
392
|
+
try {
|
|
393
|
+
const po = (strictMode && o !== null && typeof o === 'object')
|
|
394
|
+
? wrapStrict<T_CREATED_ITEM & object>(() => o as T_CREATED_ITEM & object)
|
|
395
|
+
: o as T_CREATED_ITEM;
|
|
224
396
|
|
|
225
|
-
|
|
226
|
-
|
|
397
|
+
r = dip(po);
|
|
398
|
+
putback(name, o);
|
|
399
|
+
o = undefined;
|
|
400
|
+
} catch (e) {
|
|
401
|
+
if (o !== undefined)
|
|
402
|
+
coroutine.start(destroy, o);
|
|
403
|
+
o = undefined;
|
|
404
|
+
throw toError(e);
|
|
405
|
+
} finally {
|
|
406
|
+
running--;
|
|
227
407
|
sem.post();
|
|
228
|
-
|
|
408
|
+
clearPool();
|
|
229
409
|
}
|
|
230
|
-
o = job.o;
|
|
231
|
-
}
|
|
232
410
|
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
const po = (_strict && typeof o === 'object') ? new Proxy({}, {
|
|
236
|
-
get: function (target, prop) {
|
|
237
|
-
if (prop === 'close' || prop === 'destroy' || prop === 'dispose')
|
|
238
|
-
throw new Error("Cannot close/destroy/dispose");
|
|
239
|
-
if (o === undefined)
|
|
240
|
-
throw new Error("access object outside of pool scope");
|
|
241
|
-
const value = o[prop];
|
|
242
|
-
if (typeof value === 'function') {
|
|
243
|
-
return function () {
|
|
244
|
-
return value.apply(o, arguments);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return value;
|
|
248
|
-
},
|
|
249
|
-
set: function (target, prop, value) {
|
|
250
|
-
throw new Error("Cannot set property");
|
|
251
|
-
}
|
|
252
|
-
}) as any : o;
|
|
253
|
-
|
|
254
|
-
r = func(po as T_CREATED_ITEM);
|
|
255
|
-
putback(name, o);
|
|
256
|
-
o = undefined;
|
|
257
|
-
} catch (e) {
|
|
258
|
-
if (o !== undefined)
|
|
259
|
-
coroutine.start(destroy, o);
|
|
260
|
-
o = undefined;
|
|
261
|
-
throw ensureError(e);
|
|
411
|
+
return r;
|
|
262
412
|
} finally {
|
|
263
|
-
|
|
264
|
-
sem.post();
|
|
265
|
-
clearPool();
|
|
413
|
+
leaveFiber(fiber);
|
|
266
414
|
}
|
|
267
|
-
|
|
268
|
-
return r;
|
|
269
|
-
};
|
|
415
|
+
}) as FibPoolNS.FibPool<T_CREATED_ITEM, T_POOL_FUNC_RETURN>;
|
|
270
416
|
|
|
271
417
|
pool.connections = () => count
|
|
272
418
|
|
|
273
419
|
pool.info = () => ({
|
|
274
|
-
maxsize:
|
|
420
|
+
maxsize: maxsizeValue,
|
|
275
421
|
count: count,
|
|
276
422
|
running: running,
|
|
277
423
|
wait: sem.count(),
|
|
278
|
-
timeout:
|
|
424
|
+
timeout: timeoutValue
|
|
279
425
|
})
|
|
280
426
|
|
|
281
427
|
pool.clear = () => {
|
|
282
|
-
|
|
428
|
+
timeoutValue = -1;
|
|
283
429
|
clearPool();
|
|
284
430
|
}
|
|
285
431
|
|
package/tsconfig.json
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
|
|
3
|
+
// `fibjs --check` derives its default lib from the target: with es6
|
|
4
|
+
// that is lib.dom, which collides with the fibjs built-in types.
|
|
5
|
+
// es2020 is the lowest target whose default lib stays es-only.
|
|
6
|
+
"target": "es2020",
|
|
4
7
|
"module": "commonjs",
|
|
5
|
-
"
|
|
6
|
-
"removeComments": true,
|
|
7
|
-
"noEmit": true,
|
|
8
|
-
"types": [
|
|
9
|
-
"@fibjs/types"
|
|
10
|
-
]
|
|
8
|
+
"noEmit": true
|
|
11
9
|
},
|
|
12
10
|
"exclude": [
|
|
13
|
-
"test",
|
|
14
|
-
"typings",
|
|
15
11
|
"node_modules"
|
|
16
12
|
]
|
|
17
|
-
}
|
|
13
|
+
}
|
package/.travis.yml
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
language: node_js
|
|
2
|
-
node_js: '6'
|
|
3
|
-
matrix:
|
|
4
|
-
include:
|
|
5
|
-
- os: linux
|
|
6
|
-
env:
|
|
7
|
-
- VERSION=0.21.0
|
|
8
|
-
- os: linux
|
|
9
|
-
env:
|
|
10
|
-
- VERSION=0.22.0
|
|
11
|
-
- os: linux
|
|
12
|
-
env:
|
|
13
|
-
- VERSION=0.23.0
|
|
14
|
-
- os: linux
|
|
15
|
-
env:
|
|
16
|
-
- VERSION=0.24.0
|
|
17
|
-
- os: linux
|
|
18
|
-
env:
|
|
19
|
-
- VERSION=0.25.0
|
|
20
|
-
- os: linux
|
|
21
|
-
env:
|
|
22
|
-
- VERSION=0.26.0
|
|
23
|
-
- os: linux
|
|
24
|
-
env:
|
|
25
|
-
- VERSION=0.26.1
|
|
26
|
-
- os: linux
|
|
27
|
-
env:
|
|
28
|
-
- VERSION=0.27.0
|
|
29
|
-
- os: linux
|
|
30
|
-
env:
|
|
31
|
-
- VERSION=0.28.0
|
|
32
|
-
- os: linux
|
|
33
|
-
env:
|
|
34
|
-
- VERSION=0.29.0
|
|
35
|
-
- os: linux
|
|
36
|
-
env:
|
|
37
|
-
- VERSION=0.30.0
|
|
38
|
-
- os: osx
|
|
39
|
-
osx_image: xcode9
|
|
40
|
-
env:
|
|
41
|
-
- VERSION=0.21.0
|
|
42
|
-
- os: osx
|
|
43
|
-
osx_image: xcode9
|
|
44
|
-
env:
|
|
45
|
-
- VERSION=0.22.0
|
|
46
|
-
- os: osx
|
|
47
|
-
osx_image: xcode9
|
|
48
|
-
env:
|
|
49
|
-
- VERSION=0.23.0
|
|
50
|
-
- os: osx
|
|
51
|
-
osx_image: xcode9
|
|
52
|
-
env:
|
|
53
|
-
- VERSION=0.24.0
|
|
54
|
-
- os: osx
|
|
55
|
-
osx_image: xcode9
|
|
56
|
-
env:
|
|
57
|
-
- VERSION=0.25.0
|
|
58
|
-
- os: osx
|
|
59
|
-
osx_image: xcode9
|
|
60
|
-
env:
|
|
61
|
-
- VERSION=0.26.0
|
|
62
|
-
- os: osx
|
|
63
|
-
osx_image: xcode9
|
|
64
|
-
env:
|
|
65
|
-
- VERSION=0.26.1
|
|
66
|
-
- os: osx
|
|
67
|
-
osx_image: xcode9
|
|
68
|
-
env:
|
|
69
|
-
- VERSION=0.27.0
|
|
70
|
-
- os: osx
|
|
71
|
-
osx_image: xcode9
|
|
72
|
-
env:
|
|
73
|
-
- VERSION=0.28.0
|
|
74
|
-
- os: osx
|
|
75
|
-
osx_image: xcode9
|
|
76
|
-
env:
|
|
77
|
-
- VERSION=0.29.0
|
|
78
|
-
- os: osx
|
|
79
|
-
osx_image: xcode9
|
|
80
|
-
env:
|
|
81
|
-
- VERSION=0.30.0
|
|
82
|
-
before_install:
|
|
83
|
-
- OS=linux
|
|
84
|
-
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
|
85
|
-
rvm install ruby-2.4.0;
|
|
86
|
-
rvm --default use 2.4.0;
|
|
87
|
-
ruby -v;
|
|
88
|
-
brew update;
|
|
89
|
-
brew install xz;
|
|
90
|
-
OS=darwin;
|
|
91
|
-
fi
|
|
92
|
-
script:
|
|
93
|
-
- npm i
|
|
94
|
-
- mkdir -p ./node_modules/.bin
|
|
95
|
-
- rm -rf ./node_modules/.bin/fibjs
|
|
96
|
-
- curl -SL "https://github.com/fibjs/fibjs/releases/download/v${VERSION}/fibjs-v${VERSION}-${OS}-x64.xz" -o ./node_modules/.bin/fibjs.xz
|
|
97
|
-
- xz -d ./node_modules/.bin/fibjs.xz
|
|
98
|
-
- chmod a+x ./node_modules/.bin/fibjs
|
|
99
|
-
- npm run ci
|
package/appveyor.yml
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
environment:
|
|
2
|
-
nodejs_version: '6'
|
|
3
|
-
matrix:
|
|
4
|
-
- VERSION: 0.21.0
|
|
5
|
-
- VERSION: 0.22.0
|
|
6
|
-
- VERSION: 0.23.0
|
|
7
|
-
- VERSION: 0.24.0
|
|
8
|
-
- VERSION: 0.25.0
|
|
9
|
-
- VERSION: 0.26.0
|
|
10
|
-
- VERSION: 0.26.1
|
|
11
|
-
- VERSION: 0.27.0
|
|
12
|
-
- VERSION: 0.28.0
|
|
13
|
-
- VERSION: 0.29.0
|
|
14
|
-
- VERSION: 0.30.0
|
|
15
|
-
|
|
16
|
-
install:
|
|
17
|
-
- ps: Install-Product node $env:nodejs_version
|
|
18
|
-
- npm i
|
|
19
|
-
- If Not Exist "node_modules\.bin" (mkdir node_modules\.bin)
|
|
20
|
-
- curl -fsSL -o node_modules\.bin\fibjs.cab "https://github.com/fibjs/fibjs/releases/download/v%VERSION%/fibjs-v%VERSION%-windows-x64.cab"
|
|
21
|
-
- expand node_modules\.bin\fibjs.cab node_modules\.bin\fibjs.exe
|
|
22
|
-
|
|
23
|
-
test_script:
|
|
24
|
-
- npm run ci
|
|
25
|
-
|
|
26
|
-
build: off
|
package/lib/index.js
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const coroutine = require("coroutine");
|
|
3
|
-
const util = require("util");
|
|
4
|
-
function ensureError(e) {
|
|
5
|
-
if (typeof e === 'string')
|
|
6
|
-
e = new Error(e);
|
|
7
|
-
return e;
|
|
8
|
-
}
|
|
9
|
-
module.exports = function GetPool(_opt, maxsize, timeout) {
|
|
10
|
-
let opt = _opt;
|
|
11
|
-
if (util.isFunction(_opt)) {
|
|
12
|
-
opt = {
|
|
13
|
-
create: _opt,
|
|
14
|
-
maxsize: maxsize,
|
|
15
|
-
timeout: timeout
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
const create = opt.create;
|
|
19
|
-
const destroy = opt.destroy || ((o) => {
|
|
20
|
-
if (util.isFunction(o.close))
|
|
21
|
-
o.close();
|
|
22
|
-
if (util.isFunction(o.destroy))
|
|
23
|
-
o.destroy();
|
|
24
|
-
if (util.isFunction(o.dispose))
|
|
25
|
-
o.dispose();
|
|
26
|
-
});
|
|
27
|
-
maxsize = opt.maxsize || 10;
|
|
28
|
-
timeout = opt.timeout || 60000;
|
|
29
|
-
let tm = timeout / 10;
|
|
30
|
-
if (tm < 10)
|
|
31
|
-
tm = 10;
|
|
32
|
-
const retry = opt.retry || 1;
|
|
33
|
-
let pools = [];
|
|
34
|
-
const jobs = [];
|
|
35
|
-
let count = 0;
|
|
36
|
-
let running = 0;
|
|
37
|
-
const sem = new coroutine.Semaphore(maxsize);
|
|
38
|
-
let clearTimer;
|
|
39
|
-
function clearPool() {
|
|
40
|
-
let c;
|
|
41
|
-
const d = new Date().getTime();
|
|
42
|
-
while (count) {
|
|
43
|
-
c = pools[0];
|
|
44
|
-
if (d - c.time.getTime() > timeout) {
|
|
45
|
-
pools = pools.slice(1);
|
|
46
|
-
count--;
|
|
47
|
-
if (c.o !== undefined)
|
|
48
|
-
coroutine.start(destroy, c.o);
|
|
49
|
-
}
|
|
50
|
-
else
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
if (!count) {
|
|
54
|
-
if (clearTimer) {
|
|
55
|
-
clearTimer.clear();
|
|
56
|
-
clearTimer = null;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
else if (!clearTimer)
|
|
60
|
-
clearTimer = setInterval(clearPool, tm);
|
|
61
|
-
}
|
|
62
|
-
function putback(name, o, e) {
|
|
63
|
-
e = ensureError(e);
|
|
64
|
-
for (let i = 0; i < jobs.length; i++) {
|
|
65
|
-
const job = jobs[i];
|
|
66
|
-
if (job.name === name) {
|
|
67
|
-
jobs.splice(i, 1);
|
|
68
|
-
job.o = o;
|
|
69
|
-
job.e = e;
|
|
70
|
-
job.ev.set();
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (e === undefined)
|
|
75
|
-
pools[count++] = {
|
|
76
|
-
o: o,
|
|
77
|
-
name: name,
|
|
78
|
-
time: new Date()
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
function connect(name) {
|
|
82
|
-
let o;
|
|
83
|
-
let cn = 0;
|
|
84
|
-
let err;
|
|
85
|
-
while (true) {
|
|
86
|
-
try {
|
|
87
|
-
o = create(name);
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
catch (e) {
|
|
91
|
-
if (++cn >= retry) {
|
|
92
|
-
err = e;
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
putback(name, o, err);
|
|
98
|
-
}
|
|
99
|
-
const pool = (name, func) => {
|
|
100
|
-
if (typeof name === 'function') {
|
|
101
|
-
func = name;
|
|
102
|
-
name = "";
|
|
103
|
-
}
|
|
104
|
-
let r;
|
|
105
|
-
let o;
|
|
106
|
-
let p = false;
|
|
107
|
-
clearPool();
|
|
108
|
-
sem.acquire();
|
|
109
|
-
if (count) {
|
|
110
|
-
for (let i = count - 1; i >= 0; i--)
|
|
111
|
-
if (pools[i].name === name) {
|
|
112
|
-
p = true;
|
|
113
|
-
o = pools[i].o;
|
|
114
|
-
pools.splice(i, 1);
|
|
115
|
-
count--;
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
if (!p) {
|
|
120
|
-
coroutine.start(connect, name);
|
|
121
|
-
const job = {
|
|
122
|
-
name: name,
|
|
123
|
-
ev: new coroutine.Event()
|
|
124
|
-
};
|
|
125
|
-
jobs.push(job);
|
|
126
|
-
job.ev.wait();
|
|
127
|
-
if (job.e) {
|
|
128
|
-
sem.post();
|
|
129
|
-
throw ensureError(job.e);
|
|
130
|
-
}
|
|
131
|
-
o = job.o;
|
|
132
|
-
}
|
|
133
|
-
running++;
|
|
134
|
-
try {
|
|
135
|
-
r = func(o);
|
|
136
|
-
putback(name, o);
|
|
137
|
-
}
|
|
138
|
-
catch (e) {
|
|
139
|
-
if (o !== undefined)
|
|
140
|
-
coroutine.start(destroy, o);
|
|
141
|
-
throw ensureError(e);
|
|
142
|
-
}
|
|
143
|
-
finally {
|
|
144
|
-
running--;
|
|
145
|
-
sem.post();
|
|
146
|
-
clearPool();
|
|
147
|
-
}
|
|
148
|
-
return r;
|
|
149
|
-
};
|
|
150
|
-
pool.connections = () => count;
|
|
151
|
-
pool.info = () => ({
|
|
152
|
-
maxsize: maxsize,
|
|
153
|
-
count: count,
|
|
154
|
-
running: running,
|
|
155
|
-
wait: sem.count(),
|
|
156
|
-
timeout: timeout
|
|
157
|
-
});
|
|
158
|
-
pool.clear = () => {
|
|
159
|
-
timeout = -1;
|
|
160
|
-
clearPool();
|
|
161
|
-
};
|
|
162
|
-
return pool;
|
|
163
|
-
};
|
package/typings/index.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
declare namespace FibPoolNS {
|
|
2
|
-
type FirstParameter<T> = T extends (arg: infer T, ...args: any[]) => any ? T : never;
|
|
3
|
-
interface DippedItemStruct {
|
|
4
|
-
close?: FibPoolOptionResult['destroy'];
|
|
5
|
-
destroy?: FibPoolOptionResult['destroy'];
|
|
6
|
-
dispose?: FibPoolOptionResult['destroy'];
|
|
7
|
-
}
|
|
8
|
-
interface FibPoolOptionArgs<T extends DippedItemStruct = {}> {
|
|
9
|
-
create: (name: string) => T;
|
|
10
|
-
destroy?: (item?: T) => any;
|
|
11
|
-
maxsize?: number;
|
|
12
|
-
timeout?: number;
|
|
13
|
-
retry?: number | boolean;
|
|
14
|
-
strict?: boolean;
|
|
15
|
-
}
|
|
16
|
-
interface FibPoolOptionResult<T extends DippedItemStruct = {}> {
|
|
17
|
-
create: FibPoolOptionArgs<T>['create'];
|
|
18
|
-
destroy: FibPoolOptionArgs<T>['destroy'];
|
|
19
|
-
maxsize: FibPoolOptionArgs<T>['maxsize'];
|
|
20
|
-
timeout: FibPoolOptionArgs<T>['timeout'];
|
|
21
|
-
retry: FibPoolOptionArgs<T>['retry'];
|
|
22
|
-
strict: FibPoolOptionArgs<T>['strict'];
|
|
23
|
-
}
|
|
24
|
-
interface FibPoolDipperFn<T_CREATED_ITEM, T_POOL_FUNC_RETURN = any> {
|
|
25
|
-
(o: T_CREATED_ITEM): T_POOL_FUNC_RETURN;
|
|
26
|
-
}
|
|
27
|
-
type FibPool<T_CREATED_ITEM, T_POOL_FUNC_RETURN = any> = {
|
|
28
|
-
<T_RETURN = T_POOL_FUNC_RETURN>(name: string, func: FibPoolDipperFn<T_CREATED_ITEM, T_RETURN>): T_RETURN;
|
|
29
|
-
<T_RETURN = T_POOL_FUNC_RETURN>(func: FibPoolDipperFn<T_CREATED_ITEM, T_RETURN>): T_RETURN;
|
|
30
|
-
} & {
|
|
31
|
-
connections?(): number;
|
|
32
|
-
info?(): {
|
|
33
|
-
maxsize: number;
|
|
34
|
-
count: number;
|
|
35
|
-
running: number;
|
|
36
|
-
wait: number;
|
|
37
|
-
timeout: number;
|
|
38
|
-
};
|
|
39
|
-
clear?(): void;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
declare const _default: <T_CREATED_ITEM extends FibPoolNS.DippedItemStruct, T_POOL_FUNC_RETURN>(_opt: FibPoolNS.FibPoolOptionArgs<T_CREATED_ITEM> | ((name: string) => T_CREATED_ITEM), maxsize?: number, timeout?: number) => FibPoolNS.FibPool<T_CREATED_ITEM, T_POOL_FUNC_RETURN>;
|
|
43
|
-
export = _default;
|