mini-semaphore 1.3.9 → 1.3.10

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  [![CircleCI](https://circleci.com/gh/jeffy-g/mini-semaphore/tree/master.svg?style=svg)](https://circleci.com/gh/jeffy-g/mini-semaphore/tree/master)
2
2
  ![GitHub](https://img.shields.io/github/license/jeffy-g/mini-semaphore?style=plastic)
3
+ [![npm version](https://badge.fury.io/js/mini-semaphore.svg)](https://badge.fury.io/js/mini-semaphore)
4
+ ![node](https://img.shields.io/node/v/mini-semaphore.svg?style=plastic)
5
+ [![Total alerts](https://img.shields.io/lgtm/alerts/g/jeffy-g/mini-semaphore.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/jeffy-g/mini-semaphore/alerts/)
6
+ [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/jeffy-g/mini-semaphore.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/jeffy-g/mini-semaphore/context:javascript)
7
+
8
+ ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/jeffy-g/mini-semaphore.svg?style=plastic)
9
+ ![npm bundle size](https://img.shields.io/bundlephobia/min/mini-semaphore?style=plastic)
10
+ ![npm](https://img.shields.io/npm/dm/mini-semaphore.svg?style=plastic)
11
+ ![GitHub commit activity](https://img.shields.io/github/commit-activity/m/jeffy-g/mini-semaphore.svg?style=plastic)
3
12
 
4
13
  # Mini Semaphore (mini-semaphore
5
14
 
package/cjs/class.js CHANGED
@@ -1,4 +1,6 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MiniSemaphore = void 0;
2
4
  /*!
3
5
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4
6
  Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
@@ -6,17 +8,58 @@
6
8
  https://opensource.org/licenses/mit-license.php
7
9
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8
10
  */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.MiniSemaphore = void 0;
11
+ /**
12
+ * @file minimal implementation of semaphore (class implementation
13
+ * @author jeffy-g <hirotom1107@gmail.com>
14
+ * @version 1.0
15
+ */
11
16
  const core = require("./core");
12
17
  const deque_1 = require("./deque");
13
18
  const a = core.acquire;
14
19
  const r = core.release;
20
+ /**
21
+ * #### Mini Semaphore
22
+ *
23
+ * + minimal implementation of semaphore
24
+ *
25
+ * @example
26
+ * import { MiniSemaphore } from "mini-semaphore";
27
+ *
28
+ * const s = new MiniSemaphore(10);
29
+ * async function fetchTypeData(type_id) {
30
+ * await s.acquire();
31
+ * try {
32
+ * return fetch(`https://esi.evetech.net/latest/universe/types/${type_id}/`);
33
+ * } finally {
34
+ * s.release();
35
+ * }
36
+ * }
37
+ *
38
+ * //
39
+ * // or automatic acquire/release
40
+ * //
41
+ * async function fetchTypeData(type_id) {
42
+ * return s.flow(async () => fetch(`https://esi.evetech.net/latest/universe/types/${type_id}/`));
43
+ * }
44
+ *
45
+ * @date 2020/2/7
46
+ * @version 1.0
47
+ */
15
48
  class MiniSemaphore {
49
+ /**
50
+ * constructs a semaphore instance limited at `capacity`
51
+ *
52
+ * @param capacity limitation of concurrent async by `capacity`
53
+ */
16
54
  constructor(capacity) {
17
55
  this.limit = this.capacity = capacity;
18
56
  this.q = new deque_1.Deque(capacity);
19
57
  }
58
+ /**
59
+ * If there is enough capacity, execute the `resolve` immediately
60
+ *
61
+ * If not, put it in a queue and wait for the currently pending process to execute `release`
62
+ */
20
63
  acquire(lazy) {
21
64
  return a(this, lazy);
22
65
  }
@@ -29,6 +72,10 @@ class MiniSemaphore {
29
72
  get pending() {
30
73
  return this.q.length;
31
74
  }
75
+ /**
76
+ * automatic acquire/release
77
+ * @param process
78
+ */
32
79
  async flow(process, lazy) {
33
80
  await a(this, lazy);
34
81
  try {
@@ -39,4 +86,4 @@ class MiniSemaphore {
39
86
  }
40
87
  }
41
88
  }
42
- exports.MiniSemaphore = MiniSemaphore;
89
+ exports.MiniSemaphore = MiniSemaphore;
package/cjs/core.js CHANGED
@@ -1,14 +1,28 @@
1
1
  "use strict";
2
- /*!
3
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4
- Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
5
- Released under the MIT license
6
- https://opensource.org/licenses/mit-license.php
7
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8
- */
9
2
  Object.defineProperty(exports, "__esModule", { value: true });
10
3
  exports.release = exports.acquire = void 0;
11
4
  const extras_1 = require("./extras");
5
+ /**
6
+ * @typedef ISimplifiedLock
7
+ * @prop {(lazy?: boolean) => Promise<void>} acquire acquire the process rights&#64;param lazy Whether the privilege acquisition process is deffer. default `true`
8
+ * @prop {() => void} release release the pending of one
9
+ * @prop {(restriction: number) => void} setRestriction Change sharing restrictions to the value of `restriction`&#64;param {number} restriction
10
+ * @prop {number} pending Get the number of currently pending processes&#64;type {number}
11
+ * @prop {number} limit limitation
12
+ * @prop {number} capacity capacity
13
+ */
14
+ /**
15
+ * @typedef {<T>(f: () => Promise<T>, lazy?: boolean) => Promise<T>} TFlow
16
+ * @typedef {ISimplifiedLock & { flow: TFlow }} IFlowableLock
17
+ * @typedef {() => void} TVoidFunction
18
+ * @typedef {import("./deque").Deque} Deque
19
+ * @typedef {IFlowableLock & { readonly q: Deque }} TFlowableLock
20
+ */
21
+ /**
22
+ *
23
+ * @param {TFlowableLock} z
24
+ * @param {TVoidFunction} r
25
+ */
12
26
  const box = (z, r) => {
13
27
  if (z.capacity > 0) {
14
28
  z.capacity--, r();
@@ -17,6 +31,12 @@ const box = (z, r) => {
17
31
  z.q.push(r);
18
32
  }
19
33
  };
34
+ /**
35
+ *
36
+ * @param {TFlowableLock} dis
37
+ * @param {boolean} [lazy] default: true
38
+ * @returns {Promise<void>}
39
+ */
20
40
  const acquire = (dis, lazy = true) => {
21
41
  return new Promise(r => {
22
42
  if (!lazy) {
@@ -28,14 +48,18 @@ const acquire = (dis, lazy = true) => {
28
48
  });
29
49
  };
30
50
  exports.acquire = acquire;
51
+ /**
52
+ * @param {TFlowableLock} dis
53
+ * @returns {void}
54
+ */
31
55
  const release = (dis) => {
32
56
  dis.capacity++;
33
57
  if (dis.q.length) {
34
- dis.capacity -= 1, (dis.q.shift() || extras_1.THROW)();
58
+ dis.capacity -= 1, (dis.q.shift() || /* istanbul ignore next */ extras_1.THROW)();
35
59
  }
36
60
  if (dis.capacity > dis.limit) {
37
61
  console.warn("inconsistent release!");
38
62
  dis.capacity = dis.limit;
39
63
  }
40
64
  };
41
- exports.release = release;
65
+ exports.release = release;
package/cjs/deque.js CHANGED
@@ -1,12 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Deque = void 0;
4
- const am = (src, si, dst, di, len) => {
4
+ /**
5
+ * arrayMove
6
+ *
7
+ * @param src
8
+ * @param si
9
+ * @param dst
10
+ * @param di
11
+ * @param len
12
+ */
13
+ const am = /* istanbul ignore next */ (src, si, dst, di, len) => {
5
14
  for (let j = 0; j < len; ++j) {
6
15
  dst[j + di] = src[j + si];
7
16
  src[j + si] = void 0;
8
17
  }
9
18
  };
19
+ /**
20
+ * pow2AtLeast
21
+ * @param n
22
+ */
10
23
  const p2l = (n) => {
11
24
  n = n >>> 0;
12
25
  n = n - 1;
@@ -17,16 +30,34 @@ const p2l = (n) => {
17
30
  n = n | (n >> 16);
18
31
  return n + 1;
19
32
  };
33
+ /**
34
+ * getCapacity
35
+ * @param n
36
+ */
20
37
  const gc = (n) => {
38
+ // @ts-ignore typescript cannot allow (undefined | 0) expression
21
39
  return p2l(Math.min(Math.max(16, n | 0), 1073741824));
22
40
  };
41
+ /**
42
+ * ### Implementation restricted to FIFO
43
+ *
44
+ * this class is based on https://github.com/petkaantonov/deque/blob/master/js/deque.js
45
+ * Released under the MIT License: https://github.com/petkaantonov/deque/blob/master/LICENSE
46
+ */
23
47
  class Deque {
48
+ /**
49
+ * default capacity `16`
50
+ * @param ic initial capacity
51
+ */
24
52
  constructor(ic) {
25
53
  this._c = gc(ic);
26
54
  this._l = 0;
27
55
  this._f = 0;
28
56
  this._a = [];
29
57
  }
58
+ /**
59
+ * @param s subject
60
+ */
30
61
  push(s) {
31
62
  const l = this._l;
32
63
  if (this._c < l + 1) {
@@ -38,6 +69,7 @@ class Deque {
38
69
  }
39
70
  shift() {
40
71
  const l = this._l;
72
+ /* istanbul ignore if */
41
73
  if (l === 0) {
42
74
  return void 0;
43
75
  }
@@ -53,13 +85,19 @@ class Deque {
53
85
  }
54
86
  }
55
87
  exports.Deque = Deque;
88
+ /**
89
+ * resize to
90
+ *
91
+ * @param n expected capacity
92
+ */
56
93
  const rt = (dis, n) => {
57
94
  const oc = dis._c;
58
95
  dis._c = n;
59
96
  const f = dis._f;
60
97
  const l = dis._l;
98
+ /* istanbul ignore next */
61
99
  if (f + l > oc) {
62
100
  const mc = (f + l) & (oc - 1);
63
101
  am(dis._a, 0, dis._a, oc, mc);
64
102
  }
65
- };
103
+ };
package/cjs/extras.js CHANGED
@@ -4,4 +4,4 @@ exports.THROW = void 0;
4
4
  const THROW = () => {
5
5
  throw new Error("mini-semaphore: inconsistent occurred");
6
6
  };
7
- exports.THROW = THROW;
7
+ exports.THROW = THROW;
@@ -1,4 +1,6 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.restrictor = void 0;
2
4
  /*!
3
5
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4
6
  Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
@@ -6,14 +8,35 @@
6
8
  https://opensource.org/licenses/mit-license.php
7
9
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8
10
  */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.restrictor = void 0;
11
+ /**
12
+ * @file Utility module using `MiniSemaphore`
13
+ * @author jeffy-g <hirotom1107@gmail.com>
14
+ * @version 1.0
15
+ */
11
16
  const c = require("./class");
17
+ /**
18
+ * @typedef {string | number} TLockRecordKey
19
+ */
20
+ /**
21
+ * Flow Restriction
22
+ */
12
23
  var restrictor;
13
24
  (function (restrictor) {
14
25
  const { MiniSemaphore: MS } = c;
26
+ /**
27
+ * @internal
28
+ */
15
29
  const internalLock = new MS(1);
30
+ /**
31
+ *
32
+ */
16
33
  let locks = Object.create(null);
34
+ /**
35
+ *
36
+ * @param {TLockRecordKey} key
37
+ * @param {number} restriction
38
+ * @throws when different restriction
39
+ */
17
40
  const get = async (key, restriction) => {
18
41
  await internalLock.acquire(false);
19
42
  let lock = locks[key];
@@ -27,12 +50,28 @@ var restrictor;
27
50
  internalLock.release();
28
51
  return lock;
29
52
  };
53
+ /**
54
+ * get the semaphore associated with the value of `key`
55
+ *
56
+ * + ⚠️ The object to be retrieved with `key` must already be created with `multi` ore `one`
57
+ *
58
+ * @param {TLockRecordKey} key
59
+ * @returns `IFlowableLock` instance or `undefined`
60
+ */
30
61
  restrictor.getLockByKey = async (key) => {
31
62
  await internalLock.acquire(false);
32
63
  const l = locks[key];
33
64
  internalLock.release();
34
65
  return l;
35
66
  };
67
+ /**
68
+ * Eliminate unused instances for the `timeSpan` seconds
69
+ *
70
+ * @param {number} timeSpan specify unit as seconds
71
+ * @param {true} [debug] enable debug
72
+ * @returns {Promise<number>} eliminated count
73
+ * @date 2020/6/19
74
+ */
36
75
  restrictor.cleanup = async (timeSpan, debug) => {
37
76
  await internalLock.acquire(false);
38
77
  const currentLocks = locks;
@@ -40,7 +79,7 @@ var restrictor;
40
79
  const keys = Object.keys(currentLocks);
41
80
  let eliminatedCount = 0;
42
81
  let eliminatedKeys;
43
- !timeSpan && (timeSpan = 1);
82
+ !timeSpan && /* istanbul ignore next */ (timeSpan = 1);
44
83
  timeSpan *= 1000;
45
84
  if (debug) {
46
85
  eliminatedKeys = [];
@@ -66,6 +105,14 @@ var restrictor;
66
105
  }
67
106
  return eliminatedCount;
68
107
  };
108
+ /**
109
+ * Allocate a semaphore for each `key`, and limit the number of shares with the value of `restriction`
110
+ *
111
+ * @template {any} T
112
+ * @param {TLockRecordKey} key number or string as tag
113
+ * @param {number} restriction number of process restriction
114
+ * @param {() => Promise<T>} pb the process body
115
+ */
69
116
  async function multi(key, restriction, pb) {
70
117
  const s = await get(key, restriction);
71
118
  const result = s.flow(pb);
@@ -73,8 +120,18 @@ var restrictor;
73
120
  return result;
74
121
  }
75
122
  restrictor.multi = multi;
123
+ /**
124
+ * synonym of `multi(key, 1, pb)`
125
+ *
126
+ * + use case
127
+ * * Avoid concurrent requests to the same url
128
+ *
129
+ * @template {any} T
130
+ * @param {TLockRecordKey} key number or string as tag
131
+ * @param {() => Promise<T>} pb the process body
132
+ */
76
133
  async function one(key, pb) {
77
134
  return multi(key, 1, pb);
78
135
  }
79
136
  restrictor.one = one;
80
- })(restrictor = exports.restrictor || (exports.restrictor = {}));
137
+ })(restrictor = exports.restrictor || (exports.restrictor = {}));
package/cjs/index.js CHANGED
@@ -7,7 +7,7 @@
7
7
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.restrictor = exports.Deque = exports.create = exports.MiniSemaphore = void 0;
10
+ exports.version = exports.restrictor = exports.Deque = exports.create = exports.MiniSemaphore = void 0;
11
11
  var class_1 = require("./class");
12
12
  Object.defineProperty(exports, "MiniSemaphore", { enumerable: true, get: function () { return class_1.MiniSemaphore; } });
13
13
  var object_1 = require("./object");
@@ -16,3 +16,4 @@ var deque_1 = require("./deque");
16
16
  Object.defineProperty(exports, "Deque", { enumerable: true, get: function () { return deque_1.Deque; } });
17
17
  var flow_restrictor_1 = require("./flow-restrictor");
18
18
  Object.defineProperty(exports, "restrictor", { enumerable: true, get: function () { return flow_restrictor_1.restrictor; } });
19
+ exports.version = "v1.3.10";
package/cjs/object.js CHANGED
@@ -1,4 +1,6 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.create = void 0;
2
4
  /*!
3
5
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4
6
  Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
@@ -6,29 +8,55 @@
6
8
  https://opensource.org/licenses/mit-license.php
7
9
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8
10
  */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.create = void 0;
11
+ /**
12
+ * @file minimal implementation of semaphore (object implementation
13
+ * @author jeffy-g <hirotom1107@gmail.com>
14
+ * @version 1.0
15
+ */
11
16
  const core = require("./core");
12
17
  const deque_1 = require("./deque");
13
18
  const a = core.acquire;
14
19
  const r = core.release;
20
+ /**
21
+ * object implementation of `IFlowableLock`
22
+ *
23
+ * + constructs a semaphore object limited at `capacity`
24
+ *
25
+ * @param {number} capacity limitation of concurrent async by `capacity`
26
+ * @date 2020/2/7
27
+ * @version 1.0
28
+ */
15
29
  const create = (capacity) => {
16
30
  return {
17
31
  capacity,
18
32
  limit: capacity,
19
33
  q: new deque_1.Deque(capacity),
34
+ /**
35
+ *
36
+ * @param {boolean} [lazy]
37
+ * @returns {Promise<void>}
38
+ */
20
39
  acquire(lazy) {
21
40
  return a(this, lazy);
22
41
  },
23
42
  release() {
24
43
  r(this);
25
44
  },
45
+ /**
46
+ * @param {number} restriction
47
+ */
26
48
  setRestriction(restriction) {
27
49
  this.limit = this.capacity = restriction;
28
50
  },
29
51
  get pending() {
30
52
  return this.q.length;
31
53
  },
54
+ /**
55
+ * @template {any} T
56
+ * @param {() => Promise<T>} process
57
+ * @param {boolean} [lazy]
58
+ * @returns {Promise<T>}
59
+ */
32
60
  async flow(process, lazy) {
33
61
  await a(this, lazy);
34
62
  try {
@@ -40,4 +68,4 @@ const create = (capacity) => {
40
68
  }
41
69
  };
42
70
  };
43
- exports.create = create;
71
+ exports.create = create;
package/esm/class.mjs ADDED
@@ -0,0 +1,85 @@
1
+ /*!
2
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
+ Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
4
+ Released under the MIT license
5
+ https://opensource.org/licenses/mit-license.php
6
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
+ */
8
+ /**
9
+ * @file minimal implementation of semaphore (class implementation
10
+ * @author jeffy-g <hirotom1107@gmail.com>
11
+ * @version 1.0
12
+ */
13
+ import * as core from "./core.mjs";
14
+ import { Deque } from "./deque.mjs";
15
+ const a = core.acquire;
16
+ const r = core.release;
17
+ /**
18
+ * #### Mini Semaphore
19
+ *
20
+ * + minimal implementation of semaphore
21
+ *
22
+ * @example
23
+ * import { MiniSemaphore } from "mini-semaphore";
24
+ *
25
+ * const s = new MiniSemaphore(10);
26
+ * async function fetchTypeData(type_id) {
27
+ * await s.acquire();
28
+ * try {
29
+ * return fetch(`https://esi.evetech.net/latest/universe/types/${type_id}/`);
30
+ * } finally {
31
+ * s.release();
32
+ * }
33
+ * }
34
+ *
35
+ * //
36
+ * // or automatic acquire/release
37
+ * //
38
+ * async function fetchTypeData(type_id) {
39
+ * return s.flow(async () => fetch(`https://esi.evetech.net/latest/universe/types/${type_id}/`));
40
+ * }
41
+ *
42
+ * @date 2020/2/7
43
+ * @version 1.0
44
+ */
45
+ export class MiniSemaphore {
46
+ /**
47
+ * constructs a semaphore instance limited at `capacity`
48
+ *
49
+ * @param capacity limitation of concurrent async by `capacity`
50
+ */
51
+ constructor(capacity) {
52
+ this.limit = this.capacity = capacity;
53
+ this.q = new Deque(capacity);
54
+ }
55
+ /**
56
+ * If there is enough capacity, execute the `resolve` immediately
57
+ *
58
+ * If not, put it in a queue and wait for the currently pending process to execute `release`
59
+ */
60
+ acquire(lazy) {
61
+ return a(this, lazy);
62
+ }
63
+ release() {
64
+ r(this);
65
+ }
66
+ setRestriction(restriction) {
67
+ this.limit = this.capacity = restriction;
68
+ }
69
+ get pending() {
70
+ return this.q.length;
71
+ }
72
+ /**
73
+ * automatic acquire/release
74
+ * @param process
75
+ */
76
+ async flow(process, lazy) {
77
+ await a(this, lazy);
78
+ try {
79
+ return await process();
80
+ }
81
+ finally {
82
+ r(this);
83
+ }
84
+ }
85
+ }
package/esm/core.mjs ADDED
@@ -0,0 +1,60 @@
1
+ import { THROW } from "./extras.mjs";
2
+ /**
3
+ * @typedef ISimplifiedLock
4
+ * @prop {(lazy?: boolean) => Promise<void>} acquire acquire the process rights&#64;param lazy Whether the privilege acquisition process is deffer. default `true`
5
+ * @prop {() => void} release release the pending of one
6
+ * @prop {(restriction: number) => void} setRestriction Change sharing restrictions to the value of `restriction`&#64;param {number} restriction
7
+ * @prop {number} pending Get the number of currently pending processes&#64;type {number}
8
+ * @prop {number} limit limitation
9
+ * @prop {number} capacity capacity
10
+ */
11
+ /**
12
+ * @typedef {<T>(f: () => Promise<T>, lazy?: boolean) => Promise<T>} TFlow
13
+ * @typedef {ISimplifiedLock & { flow: TFlow }} IFlowableLock
14
+ * @typedef {() => void} TVoidFunction
15
+ * @typedef {import("./deque").Deque} Deque
16
+ * @typedef {IFlowableLock & { readonly q: Deque }} TFlowableLock
17
+ */
18
+ /**
19
+ *
20
+ * @param {TFlowableLock} z
21
+ * @param {TVoidFunction} r
22
+ */
23
+ const box = (z, r) => {
24
+ if (z.capacity > 0) {
25
+ z.capacity--, r();
26
+ }
27
+ else {
28
+ z.q.push(r);
29
+ }
30
+ };
31
+ /**
32
+ *
33
+ * @param {TFlowableLock} dis
34
+ * @param {boolean} [lazy] default: true
35
+ * @returns {Promise<void>}
36
+ */
37
+ export const acquire = (dis, lazy = true) => {
38
+ return new Promise(r => {
39
+ if (!lazy) {
40
+ box(dis, r);
41
+ }
42
+ else {
43
+ setTimeout(() => box(dis, r), 4);
44
+ }
45
+ });
46
+ };
47
+ /**
48
+ * @param {TFlowableLock} dis
49
+ * @returns {void}
50
+ */
51
+ export const release = (dis) => {
52
+ dis.capacity++;
53
+ if (dis.q.length) {
54
+ dis.capacity -= 1, (dis.q.shift() || /* istanbul ignore next */ THROW)();
55
+ }
56
+ if (dis.capacity > dis.limit) {
57
+ console.warn("inconsistent release!");
58
+ dis.capacity = dis.limit;
59
+ }
60
+ };
@@ -1,9 +1,22 @@
1
- const am = (src, si, dst, di, len) => {
1
+ /**
2
+ * arrayMove
3
+ *
4
+ * @param src
5
+ * @param si
6
+ * @param dst
7
+ * @param di
8
+ * @param len
9
+ */
10
+ const am = /* istanbul ignore next */ (src, si, dst, di, len) => {
2
11
  for (let j = 0; j < len; ++j) {
3
12
  dst[j + di] = src[j + si];
4
13
  src[j + si] = void 0;
5
14
  }
6
15
  };
16
+ /**
17
+ * pow2AtLeast
18
+ * @param n
19
+ */
7
20
  const p2l = (n) => {
8
21
  n = n >>> 0;
9
22
  n = n - 1;
@@ -14,16 +27,34 @@ const p2l = (n) => {
14
27
  n = n | (n >> 16);
15
28
  return n + 1;
16
29
  };
30
+ /**
31
+ * getCapacity
32
+ * @param n
33
+ */
17
34
  const gc = (n) => {
35
+ // @ts-ignore typescript cannot allow (undefined | 0) expression
18
36
  return p2l(Math.min(Math.max(16, n | 0), 1073741824));
19
37
  };
38
+ /**
39
+ * ### Implementation restricted to FIFO
40
+ *
41
+ * this class is based on https://github.com/petkaantonov/deque/blob/master/js/deque.js
42
+ * Released under the MIT License: https://github.com/petkaantonov/deque/blob/master/LICENSE
43
+ */
20
44
  export class Deque {
45
+ /**
46
+ * default capacity `16`
47
+ * @param ic initial capacity
48
+ */
21
49
  constructor(ic) {
22
50
  this._c = gc(ic);
23
51
  this._l = 0;
24
52
  this._f = 0;
25
53
  this._a = [];
26
54
  }
55
+ /**
56
+ * @param s subject
57
+ */
27
58
  push(s) {
28
59
  const l = this._l;
29
60
  if (this._c < l + 1) {
@@ -35,6 +66,7 @@ export class Deque {
35
66
  }
36
67
  shift() {
37
68
  const l = this._l;
69
+ /* istanbul ignore if */
38
70
  if (l === 0) {
39
71
  return void 0;
40
72
  }
@@ -49,13 +81,19 @@ export class Deque {
49
81
  return this._l;
50
82
  }
51
83
  }
84
+ /**
85
+ * resize to
86
+ *
87
+ * @param n expected capacity
88
+ */
52
89
  const rt = (dis, n) => {
53
90
  const oc = dis._c;
54
91
  dis._c = n;
55
92
  const f = dis._f;
56
93
  const l = dis._l;
94
+ /* istanbul ignore next */
57
95
  if (f + l > oc) {
58
96
  const mc = (f + l) & (oc - 1);
59
97
  am(dis._a, 0, dis._a, oc, mc);
60
98
  }
61
- };
99
+ };
@@ -1,3 +1,3 @@
1
- export const THROW = () => {
1
+ export const THROW = /* istanbul ignore next */ () => {
2
2
  throw new Error("mini-semaphore: inconsistent occurred");
3
- };
3
+ };
@@ -5,12 +5,35 @@
5
5
  https://opensource.org/licenses/mit-license.php
6
6
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
7
  */
8
- import * as c from "./class";
8
+ /**
9
+ * @file Utility module using `MiniSemaphore`
10
+ * @author jeffy-g <hirotom1107@gmail.com>
11
+ * @version 1.0
12
+ */
13
+ import * as c from "./class.mjs";
14
+ /**
15
+ * @typedef {string | number} TLockRecordKey
16
+ */
17
+ /**
18
+ * Flow Restriction
19
+ */
9
20
  export var restrictor;
10
21
  (function (restrictor) {
11
22
  const { MiniSemaphore: MS } = c;
23
+ /**
24
+ * @internal
25
+ */
12
26
  const internalLock = new MS(1);
27
+ /**
28
+ *
29
+ */
13
30
  let locks = Object.create(null);
31
+ /**
32
+ *
33
+ * @param {TLockRecordKey} key
34
+ * @param {number} restriction
35
+ * @throws when different restriction
36
+ */
14
37
  const get = async (key, restriction) => {
15
38
  await internalLock.acquire(false);
16
39
  let lock = locks[key];
@@ -24,12 +47,28 @@ export var restrictor;
24
47
  internalLock.release();
25
48
  return lock;
26
49
  };
50
+ /**
51
+ * get the semaphore associated with the value of `key`
52
+ *
53
+ * + ⚠️ The object to be retrieved with `key` must already be created with `multi` ore `one`
54
+ *
55
+ * @param {TLockRecordKey} key
56
+ * @returns `IFlowableLock` instance or `undefined`
57
+ */
27
58
  restrictor.getLockByKey = async (key) => {
28
59
  await internalLock.acquire(false);
29
60
  const l = locks[key];
30
61
  internalLock.release();
31
62
  return l;
32
63
  };
64
+ /**
65
+ * Eliminate unused instances for the `timeSpan` seconds
66
+ *
67
+ * @param {number} timeSpan specify unit as seconds
68
+ * @param {true} [debug] enable debug
69
+ * @returns {Promise<number>} eliminated count
70
+ * @date 2020/6/19
71
+ */
33
72
  restrictor.cleanup = async (timeSpan, debug) => {
34
73
  await internalLock.acquire(false);
35
74
  const currentLocks = locks;
@@ -37,7 +76,7 @@ export var restrictor;
37
76
  const keys = Object.keys(currentLocks);
38
77
  let eliminatedCount = 0;
39
78
  let eliminatedKeys;
40
- !timeSpan && (timeSpan = 1);
79
+ !timeSpan && /* istanbul ignore next */ (timeSpan = 1);
41
80
  timeSpan *= 1000;
42
81
  if (debug) {
43
82
  eliminatedKeys = [];
@@ -63,6 +102,14 @@ export var restrictor;
63
102
  }
64
103
  return eliminatedCount;
65
104
  };
105
+ /**
106
+ * Allocate a semaphore for each `key`, and limit the number of shares with the value of `restriction`
107
+ *
108
+ * @template {any} T
109
+ * @param {TLockRecordKey} key number or string as tag
110
+ * @param {number} restriction number of process restriction
111
+ * @param {() => Promise<T>} pb the process body
112
+ */
66
113
  async function multi(key, restriction, pb) {
67
114
  const s = await get(key, restriction);
68
115
  const result = s.flow(pb);
@@ -70,8 +117,18 @@ export var restrictor;
70
117
  return result;
71
118
  }
72
119
  restrictor.multi = multi;
120
+ /**
121
+ * synonym of `multi(key, 1, pb)`
122
+ *
123
+ * + use case
124
+ * * Avoid concurrent requests to the same url
125
+ *
126
+ * @template {any} T
127
+ * @param {TLockRecordKey} key number or string as tag
128
+ * @param {() => Promise<T>} pb the process body
129
+ */
73
130
  async function one(key, pb) {
74
131
  return multi(key, 1, pb);
75
132
  }
76
133
  restrictor.one = one;
77
- })(restrictor || (restrictor = {}));
134
+ })(restrictor || (restrictor = {}));
@@ -5,7 +5,8 @@
5
5
  https://opensource.org/licenses/mit-license.php
6
6
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
7
  */
8
- export { MiniSemaphore } from "./class";
9
- export { create } from "./object";
10
- export { Deque } from "./deque";
11
- export { restrictor } from "./flow-restrictor";
8
+ export { MiniSemaphore } from "./class.mjs";
9
+ export { create } from "./object.mjs";
10
+ export { Deque } from "./deque.mjs";
11
+ export { restrictor } from "./flow-restrictor.mjs";
12
+ export const version = "v1.3.10";
@@ -5,27 +5,55 @@
5
5
  https://opensource.org/licenses/mit-license.php
6
6
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
7
  */
8
- import * as core from "./core";
9
- import { Deque } from "./deque";
8
+ /**
9
+ * @file minimal implementation of semaphore (object implementation
10
+ * @author jeffy-g <hirotom1107@gmail.com>
11
+ * @version 1.0
12
+ */
13
+ import * as core from "./core.mjs";
14
+ import { Deque } from "./deque.mjs";
10
15
  const a = core.acquire;
11
16
  const r = core.release;
17
+ /**
18
+ * object implementation of `IFlowableLock`
19
+ *
20
+ * + constructs a semaphore object limited at `capacity`
21
+ *
22
+ * @param {number} capacity limitation of concurrent async by `capacity`
23
+ * @date 2020/2/7
24
+ * @version 1.0
25
+ */
12
26
  export const create = (capacity) => {
13
27
  return {
14
28
  capacity,
15
29
  limit: capacity,
16
30
  q: new Deque(capacity),
31
+ /**
32
+ *
33
+ * @param {boolean} [lazy]
34
+ * @returns {Promise<void>}
35
+ */
17
36
  acquire(lazy) {
18
37
  return a(this, lazy);
19
38
  },
20
39
  release() {
21
40
  r(this);
22
41
  },
42
+ /**
43
+ * @param {number} restriction
44
+ */
23
45
  setRestriction(restriction) {
24
46
  this.limit = this.capacity = restriction;
25
47
  },
26
48
  get pending() {
27
49
  return this.q.length;
28
50
  },
51
+ /**
52
+ * @template {any} T
53
+ * @param {() => Promise<T>} process
54
+ * @param {boolean} [lazy]
55
+ * @returns {Promise<T>}
56
+ */
29
57
  async flow(process, lazy) {
30
58
  await a(this, lazy);
31
59
  try {
@@ -36,4 +64,4 @@ export const create = (capacity) => {
36
64
  }
37
65
  }
38
66
  };
39
- };
67
+ };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "mini-semaphore",
3
- "version": "1.3.9",
3
+ "version": "1.3.10",
4
4
  "description": "A lightweight version of Semaphore",
5
5
  "private": false,
6
6
  "main": "./cjs/index.js",
7
- "module": "./webpack-esm/index.mjs",
7
+ "module": "./esm/index.mjs",
8
8
  "unpkg": "./umd/index.js",
9
9
  "sideEffects": false,
10
10
  "types": "./index.d.ts",
package/umd/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*! For license information please see index.js.LICENSE.txt */
2
- !function(e,t){'object'==typeof exports&&'object'==typeof module?module.exports=t():'function'==typeof define&&define.amd?define([],t):'object'==typeof exports?exports.MiniSema=t():e.MiniSema=t()}(globalThis,(()=>(()=>{"use strict";var e={518:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSemaphore=void 0;const r=i(461),n=i(761),s=r.acquire,c=r.release;t.MiniSemaphore=class{constructor(e){this.limit=this.capacity=e,this.q=new n.Deque(e)}acquire(e){return s(this,e)}release(){c(this)}setRestriction(e){this.limit=this.capacity=e}get pending(){return this.q.length}async flow(e,t){await s(this,t);try{return await e()}finally{c(this)}}}},461:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.release=t.acquire=void 0;const r=i(669),n=(e,t)=>{e.capacity>0?(e.capacity--,
2
+ !function(e,t){'object'==typeof exports&&'object'==typeof module?module.exports=t():'function'==typeof define&&define.amd?define([],t):'object'==typeof exports?exports.MiniSema=t():e.MiniSema=t()}(globalThis,(()=>(()=>{"use strict";var e={518:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSemaphore=void 0;const r=i(461),n=i(761),s=r.acquire,o=r.release;t.MiniSemaphore=class{constructor(e){this.limit=this.capacity=e,this.q=new n.Deque(e)}acquire(e){return s(this,e)}release(){o(this)}setRestriction(e){this.limit=this.capacity=e}get pending(){return this.q.length}async flow(e,t){await s(this,t);try{return await e()}finally{o(this)}}}},461:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.release=t.acquire=void 0;const r=i(669),n=(e,t)=>{e.capacity>0?(e.capacity--,
3
3
  t()):e.q.push(t)};t.acquire=(e,t=!0)=>new Promise((i=>{t?setTimeout((()=>n(e,i)),4):n(e,i)}));t.release=e=>{e.capacity++,e.q.length&&(e.capacity-=1,(e.q.shift()||r.THROW)()),e.capacity>e.limit&&(console.warn("inconsistent release!"),e.capacity=e.limit)}},761:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Deque=void 0;const i=e=>(e=>(e>>>=0,e-=1,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,1+(e|=e>>16)))(Math.min(Math.max(16,0|e),1073741824));t.Deque=class{constructor(e){this._c=i(e),this._l=0,this._f=0,this._a=[]}push(e){const t=this._l;this._c<t+1&&r(this,i(1.5*this._c+16));const n=this._f+t&this._c-1;this._a[n]=e,this._l=t+1}shift(){const e=this._l;if(0===e)return;const t=this._f,i=this._a[t];return this._a[t]=void 0,this._f=t+1&this._c-1,this._l=e-1,i}get length(){return this._l}}
4
- ;const r=(e,t)=>{const i=e._c;e._c=t;const r=e._f,n=e._l;if(r+n>i){const t=r+n&i-1;((e,t,i,r,n)=>{for(let s=0;s<n;++s)i[s+r]=e[s+t],e[s+t]=void 0})(e._a,0,e._a,i,t)}}},669:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.THROW=void 0;t.THROW=()=>{throw new Error("mini-semaphore: inconsistent occurred")}},464:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(518);(e=>{const{MiniSemaphore:t}=r,i=new t(1);let n=Object.create(null);async function s(e,r,s){const c=await(async(e,r)=>{await i.acquire(!1);let s=n[e];if(s||(n[e]=s=new t(r)),s.limit!==r)throw i.release(),new ReferenceError(`Cannot get object with different restriction: key: '${e}', lock.limit: ${s.limit} <-> restriction: ${r},`);return i.release(),s})(e,r),a=c.flow(s)
5
- ;return c.last=Date.now(),a}e.getLockByKey=async e=>{await i.acquire(!1);const t=n[e];return i.release(),t},e.cleanup=async(e,t)=>{await i.acquire(!1);const r=n,s=Object.create(null),c=Object.keys(r);let a,o=0;!e&&(e=1),e*=1e3,t&&(a=[]);for(let i=0,n=c.length;i<n;){const n=c[i++],l=r[n];l.last&&Date.now()-l.last>=e?(o++,t&&a.push(n)):s[n]=l}return n=s,i.release(),t&&console.log(`eliminated: [\n${a.join(",\n")}\n]\nlived: [\n${Object.keys(s).join(",\n")}\n]`),o},e.multi=s,e.one=async function(e,t){return s(e,1,t)}})(t.restrictor||(t.restrictor={}))},139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.create=void 0;const r=i(461),n=i(761),s=r.acquire,c=r.release;t.create=e=>({capacity:e,limit:e,q:new n.Deque(e),acquire(e){return s(this,e)},release(){c(this)},setRestriction(e){
6
- this.limit=this.capacity=e},get pending(){return this.q.length},async flow(e,t){await s(this,t);try{return await e()}finally{c(this)}}})}},t={};function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,i),s.exports}var r={};return(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.restrictor=e.Deque=e.create=e.MiniSemaphore=void 0;var t=i(518);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return n.create}});var s=i(761);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return s.Deque}});var c=i(464);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return c.restrictor}})})(),r
7
- })()));
4
+ ;const r=(e,t)=>{const i=e._c;e._c=t;const r=e._f,n=e._l;if(r+n>i){const t=r+n&i-1;((e,t,i,r,n)=>{for(let s=0;s<n;++s)i[s+r]=e[s+t],e[s+t]=void 0})(e._a,0,e._a,i,t)}}},669:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.THROW=void 0;t.THROW=()=>{throw new Error("mini-semaphore: inconsistent occurred")}},464:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(518);(e=>{const{MiniSemaphore:t}=r,i=new t(1);let n=Object.create(null);async function s(e,r,s){const o=await(async(e,r)=>{await i.acquire(!1);let s=n[e];if(s||(n[e]=s=new t(r)),s.limit!==r)throw i.release(),new ReferenceError(`Cannot get object with different restriction: key: '${e}', lock.limit: ${s.limit} <-> restriction: ${r},`);return i.release(),s})(e,r),c=o.flow(s)
5
+ ;return o.last=Date.now(),c}e.getLockByKey=async e=>{await i.acquire(!1);const t=n[e];return i.release(),t},e.cleanup=async(e,t)=>{await i.acquire(!1);const r=n,s=Object.create(null),o=Object.keys(r);let c,a=0;!e&&(e=1),e*=1e3,t&&(c=[]);for(let i=0,n=o.length;i<n;){const n=o[i++],l=r[n];l.last&&Date.now()-l.last>=e?(a++,t&&c.push(n)):s[n]=l}return n=s,i.release(),t&&console.log(`eliminated: [\n${c.join(",\n")}\n]\nlived: [\n${Object.keys(s).join(",\n")}\n]`),a},e.multi=s,e.one=async function(e,t){return s(e,1,t)}})(t.restrictor||(t.restrictor={}))},139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.create=void 0;const r=i(461),n=i(761),s=r.acquire,o=r.release;t.create=e=>({capacity:e,limit:e,q:new n.Deque(e),acquire(e){return s(this,e)},release(){o(this)},setRestriction(e){
6
+ this.limit=this.capacity=e},get pending(){return this.q.length},async flow(e,t){await s(this,t);try{return await e()}finally{o(this)}}})}},t={};function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,i),s.exports}var r={};return(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.version=e.restrictor=e.Deque=e.create=e.MiniSemaphore=void 0;var t=i(518);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return n.create}});var s=i(761);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return s.Deque}});var o=i(464);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return o.restrictor}
7
+ }),e.version="v1.3.10"})(),r})()));
package/webpack/index.js CHANGED
@@ -3,4 +3,4 @@
3
3
  e.capacity>e.limit&&(console.warn("inconsistent release!"),e.capacity=e.limit)}},761:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Deque=void 0;const i=e=>(e=>(e>>>=0,e-=1,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,1+(e|=e>>16)))(Math.min(Math.max(16,0|e),1073741824));t.Deque=class{constructor(e){this._c=i(e),this._l=0,this._f=0,this._a=[]}push(e){const t=this._l;this._c<t+1&&r(this,i(1.5*this._c+16));const n=this._f+t&this._c-1;this._a[n]=e,this._l=t+1}shift(){const e=this._l;if(0===e)return;const t=this._f,i=this._a[t];return this._a[t]=void 0,this._f=t+1&this._c-1,this._l=e-1,i}get length(){return this._l}};const r=(e,t)=>{const i=e._c;e._c=t;const r=e._f,n=e._l;if(r+n>i){const t=r+n&i-1;((e,t,i,r,n)=>{for(let s=0;s<n;++s)i[s+r]=e[s+t],e[s+t]=void 0})(e._a,0,e._a,i,t)}}},669:(e,t)=>{
4
4
  Object.defineProperty(t,"__esModule",{value:!0}),t.THROW=void 0;t.THROW=()=>{throw new Error("mini-semaphore: inconsistent occurred")}},464:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(518);(e=>{const{MiniSemaphore:t}=r,i=new t(1);let n=Object.create(null);async function s(e,r,s){const a=await(async(e,r)=>{await i.acquire(!1);let s=n[e];if(s||(n[e]=s=new t(r)),s.limit!==r)throw i.release(),new ReferenceError(`Cannot get object with different restriction: key: '${e}', lock.limit: ${s.limit} <-> restriction: ${r},`);return i.release(),s})(e,r),c=a.flow(s);return a.last=Date.now(),c}e.getLockByKey=async e=>{await i.acquire(!1);const t=n[e];return i.release(),t},e.cleanup=async(e,t)=>{await i.acquire(!1)
5
5
  ;const r=n,s=Object.create(null),a=Object.keys(r);let c,o=0;!e&&(e=1),e*=1e3,t&&(c=[]);for(let i=0,n=a.length;i<n;){const n=a[i++],l=r[n];l.last&&Date.now()-l.last>=e?(o++,t&&c.push(n)):s[n]=l}return n=s,i.release(),t&&console.log(`eliminated: [\n${c.join(",\n")}\n]\nlived: [\n${Object.keys(s).join(",\n")}\n]`),o},e.multi=s,e.one=async function(e,t){return s(e,1,t)}})(t.restrictor||(t.restrictor={}))},139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.create=void 0;const r=i(461),n=i(761),s=r.acquire,a=r.release;t.create=e=>({capacity:e,limit:e,q:new n.Deque(e),acquire(e){return s(this,e)},release(){a(this)},setRestriction(e){this.limit=this.capacity=e},get pending(){return this.q.length},async flow(e,t){await s(this,t);try{return await e()}finally{a(this)}}})}},t={}
6
- ;function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,i),s.exports}var r={};(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.restrictor=e.Deque=e.create=e.MiniSemaphore=void 0;var t=i(518);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return n.create}});var s=i(761);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return s.Deque}});var a=i(464);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return a.restrictor}})})(),module.exports=r})();
6
+ ;function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,i),s.exports}var r={};(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.version=e.restrictor=e.Deque=e.create=e.MiniSemaphore=void 0;var t=i(518);Object.defineProperty(e,"MiniSemaphore",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);Object.defineProperty(e,"create",{enumerable:!0,get:function(){return n.create}});var s=i(761);Object.defineProperty(e,"Deque",{enumerable:!0,get:function(){return s.Deque}});var a=i(464);Object.defineProperty(e,"restrictor",{enumerable:!0,get:function(){return a.restrictor}}),e.version="v1.3.10"})(),module.exports=r})();
@@ -3,4 +3,4 @@ var e={518:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MiniSema
3
3
  e.capacity>e.limit&&(console.warn("inconsistent release!"),e.capacity=e.limit)}},761:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Deque=void 0;const i=e=>(e=>(e>>>=0,e-=1,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,1+(e|=e>>16)))(Math.min(Math.max(16,0|e),1073741824));t.Deque=class{constructor(e){this._c=i(e),this._l=0,this._f=0,this._a=[]}push(e){const t=this._l;this._c<t+1&&r(this,i(1.5*this._c+16));const n=this._f+t&this._c-1;this._a[n]=e,this._l=t+1}shift(){const e=this._l;if(0===e)return;const t=this._f,i=this._a[t];return this._a[t]=void 0,this._f=t+1&this._c-1,this._l=e-1,i}get length(){return this._l}};const r=(e,t)=>{const i=e._c;e._c=t;const r=e._f,n=e._l;if(r+n>i){const t=r+n&i-1;((e,t,i,r,n)=>{for(let s=0;s<n;++s)i[s+r]=e[s+t],e[s+t]=void 0})(e._a,0,e._a,i,t)}}},669:(e,t)=>{
4
4
  Object.defineProperty(t,"__esModule",{value:!0}),t.THROW=void 0;t.THROW=()=>{throw new Error("mini-semaphore: inconsistent occurred")}},464:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restrictor=void 0;const r=i(518);(e=>{const{MiniSemaphore:t}=r,i=new t(1);let n=Object.create(null);async function s(e,r,s){const a=await(async(e,r)=>{await i.acquire(!1);let s=n[e];if(s||(n[e]=s=new t(r)),s.limit!==r)throw i.release(),new ReferenceError(`Cannot get object with different restriction: key: '${e}', lock.limit: ${s.limit} <-> restriction: ${r},`);return i.release(),s})(e,r),c=a.flow(s);return a.last=Date.now(),c}e.getLockByKey=async e=>{await i.acquire(!1);const t=n[e];return i.release(),t},e.cleanup=async(e,t)=>{await i.acquire(!1)
5
5
  ;const r=n,s=Object.create(null),a=Object.keys(r);let c,o=0;!e&&(e=1),e*=1e3,t&&(c=[]);for(let i=0,n=a.length;i<n;){const n=a[i++],l=r[n];l.last&&Date.now()-l.last>=e?(o++,t&&c.push(n)):s[n]=l}return n=s,i.release(),t&&console.log(`eliminated: [\n${c.join(",\n")}\n]\nlived: [\n${Object.keys(s).join(",\n")}\n]`),o},e.multi=s,e.one=async function(e,t){return s(e,1,t)}})(t.restrictor||(t.restrictor={}))},139:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.create=void 0;const r=i(461),n=i(761),s=r.acquire,a=r.release;t.create=e=>({capacity:e,limit:e,q:new n.Deque(e),acquire(e){return s(this,e)},release(){a(this)},setRestriction(e){this.limit=this.capacity=e},get pending(){return this.q.length},async flow(e,t){await s(this,t);try{return await e()}finally{a(this)}}})}},t={}
6
- ;function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,i),s.exports}var r={};(()=>{var e=r;Object.defineProperty(e,"X$",{value:!0}),e.gD=e.P7=e.Ue=e.G3=void 0;var t=i(518);Object.defineProperty(e,"G3",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);Object.defineProperty(e,"Ue",{enumerable:!0,get:function(){return n.create}});var s=i(761);Object.defineProperty(e,"P7",{enumerable:!0,get:function(){return s.Deque}});var a=i(464);Object.defineProperty(e,"gD",{enumerable:!0,get:function(){return a.restrictor}})})();var n=r.P7,s=r.G3,a=r.X$,c=r.Ue,o=r.gD;export{n as Deque,s as MiniSemaphore,a as __esModule,c as create,o as restrictor};
6
+ ;function i(r){var n=t[r];if(void 0!==n)return n.exports;var s=t[r]={exports:{}};return e[r](s,s.exports,i),s.exports}var r={};(()=>{var e=r;Object.defineProperty(e,"X$",{value:!0}),e.i8=e.gD=e.P7=e.Ue=e.G3=void 0;var t=i(518);Object.defineProperty(e,"G3",{enumerable:!0,get:function(){return t.MiniSemaphore}});var n=i(139);Object.defineProperty(e,"Ue",{enumerable:!0,get:function(){return n.create}});var s=i(761);Object.defineProperty(e,"P7",{enumerable:!0,get:function(){return s.Deque}});var a=i(464);Object.defineProperty(e,"gD",{enumerable:!0,get:function(){return a.restrictor}}),e.i8="v1.3.10"})();var n=r.P7,s=r.G3,a=r.X$,c=r.Ue,o=r.gD,l=r.i8;export{n as Deque,s as MiniSemaphore,a as __esModule,c as create,o as restrictor,l as version};
package/esm/class.js DELETED
@@ -1,38 +0,0 @@
1
- /*!
2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
- Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
4
- Released under the MIT license
5
- https://opensource.org/licenses/mit-license.php
6
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
- */
8
- import * as core from "./core";
9
- import { Deque } from "./deque";
10
- const a = core.acquire;
11
- const r = core.release;
12
- export class MiniSemaphore {
13
- constructor(capacity) {
14
- this.limit = this.capacity = capacity;
15
- this.q = new Deque(capacity);
16
- }
17
- acquire(lazy) {
18
- return a(this, lazy);
19
- }
20
- release() {
21
- r(this);
22
- }
23
- setRestriction(restriction) {
24
- this.limit = this.capacity = restriction;
25
- }
26
- get pending() {
27
- return this.q.length;
28
- }
29
- async flow(process, lazy) {
30
- await a(this, lazy);
31
- try {
32
- return await process();
33
- }
34
- finally {
35
- r(this);
36
- }
37
- }
38
- }
package/esm/core.js DELETED
@@ -1,36 +0,0 @@
1
- /*!
2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
- Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
4
- Released under the MIT license
5
- https://opensource.org/licenses/mit-license.php
6
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
- */
8
- import { THROW } from "./extras";
9
- const box = (z, r) => {
10
- if (z.capacity > 0) {
11
- z.capacity--, r();
12
- }
13
- else {
14
- z.q.push(r);
15
- }
16
- };
17
- export const acquire = (dis, lazy = true) => {
18
- return new Promise(r => {
19
- if (!lazy) {
20
- box(dis, r);
21
- }
22
- else {
23
- setTimeout(() => box(dis, r), 4);
24
- }
25
- });
26
- };
27
- export const release = (dis) => {
28
- dis.capacity++;
29
- if (dis.q.length) {
30
- dis.capacity -= 1, (dis.q.shift() || THROW)();
31
- }
32
- if (dis.capacity > dis.limit) {
33
- console.warn("inconsistent release!");
34
- dis.capacity = dis.limit;
35
- }
36
- };