1 | ;
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = void 0;
|
7 |
|
8 | var _events = _interopRequireDefault(require("events"));
|
9 |
|
10 | var _autoBind = _interopRequireDefault(require("auto-bind"));
|
11 |
|
12 | var _AsyncQueue = _interopRequireWildcard(require("./AsyncQueue"));
|
13 |
|
14 | var _asyncSyncUtils = require("./asyncSyncUtils");
|
15 |
|
16 | var _errorUtils = require("./errorUtils");
|
17 |
|
18 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
19 |
|
20 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
21 |
|
22 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
23 |
|
24 | /**
|
25 | * A thread-pool abstraction for ES6 async operations",
|
26 | *
|
27 | * @export
|
28 | * @class ThreadPool
|
29 | * @extends {EventEmitter}
|
30 | */
|
31 | class ThreadPool extends _events.default {
|
32 | static async run(options) {
|
33 | options.errorHandler = options.errorHandler || (err => {
|
34 | throw err;
|
35 | });
|
36 |
|
37 | const tp = new ThreadPool(options);
|
38 |
|
39 | if (options.items) {
|
40 | await tp.queueItems(options.items);
|
41 | }
|
42 |
|
43 | return await tp.runAllQueued();
|
44 | }
|
45 |
|
46 | static async all(items, task, threads) {
|
47 | const tp = new ThreadPool({
|
48 | task: task,
|
49 | threads: threads,
|
50 | items: items
|
51 | });
|
52 |
|
53 | if (items) {
|
54 | await tp.queueItems(items);
|
55 | }
|
56 |
|
57 | return await tp.runAllQueued();
|
58 | }
|
59 | /**
|
60 | * Creates an instance of ThreadPool
|
61 | */
|
62 |
|
63 |
|
64 | constructor(options) {
|
65 | super();
|
66 |
|
67 | _defineProperty(this, "queuedCount", 0);
|
68 |
|
69 | _defineProperty(this, "startedCount", 0);
|
70 |
|
71 | _defineProperty(this, "endedCount", 0);
|
72 |
|
73 | _defineProperty(this, "_options", void 0);
|
74 |
|
75 | _defineProperty(this, "_errorHandler", void 0);
|
76 |
|
77 | _defineProperty(this, "_uncaughtErrors", []);
|
78 |
|
79 | _defineProperty(this, "_closed", false);
|
80 |
|
81 | _defineProperty(this, "_queuedTasks", void 0);
|
82 |
|
83 | _defineProperty(this, "_threadsSemaphore", void 0);
|
84 |
|
85 | _defineProperty(this, "_completeEvent", void 0);
|
86 |
|
87 | _defineProperty(this, "_allTasksCompleteOrSomeFailedEvent", void 0);
|
88 |
|
89 | _defineProperty(this, "_res", []);
|
90 |
|
91 | this._options = options;
|
92 | this._options.threads = this._options.threads || Infinity;
|
93 |
|
94 | this._errorHandler = this._options.errorHandler || (err => {
|
95 | throw err;
|
96 | }); // eslint-disable-line no-console
|
97 |
|
98 |
|
99 | this._queuedTasks = new _AsyncQueue.default({
|
100 | name: options.name,
|
101 | maxSize: options.queueMaxSize
|
102 | });
|
103 | this._threadsSemaphore = new _asyncSyncUtils.Semaphore(this._options.threads);
|
104 | this._completeEvent = new _asyncSyncUtils.OneTimeBroadcastEvent(false);
|
105 | this._allTasksCompleteOrSomeFailedEvent = new _asyncSyncUtils.OneTimeBroadcastEvent(false);
|
106 | (0, _autoBind.default)(this);
|
107 | }
|
108 | /**
|
109 | * Queues an itme from the ThreadPool
|
110 | */
|
111 |
|
112 |
|
113 | async queueItem(item) {
|
114 | if (this._closed) throw new Error(`Trying to queue a job to a closed ThreadPool`);
|
115 | const index = this.queuedCount++;
|
116 | await this._queuedTasks.enqueue({
|
117 | func: async () => this._res[index] = await this._options.task(item),
|
118 | index: index
|
119 | });
|
120 | }
|
121 | /**
|
122 | * Queues an itme from the ThreadPool
|
123 | */
|
124 |
|
125 |
|
126 | async queueItems(queueItem) {
|
127 | for (const item of queueItem) {
|
128 | await this.queueItem(item);
|
129 | }
|
130 | }
|
131 | /**
|
132 | * Starts executing all queued tasks
|
133 | *
|
134 | * This function should be awaited - it will return after the ThreadPool has been closed and all it's tasks completed, or after a task threw an error.
|
135 | */
|
136 |
|
137 |
|
138 | async run() {
|
139 | try {
|
140 | while (true) {
|
141 | // wait for an available task
|
142 | // TODO: also wait for errors here?
|
143 | let task;
|
144 |
|
145 | try {
|
146 | task = await this._queuedTasks.dequeue();
|
147 | } catch (err) {
|
148 | if (err instanceof _AsyncQueue.QueueClosedError) break;
|
149 | throw err;
|
150 | } // wait for an available 'thread'
|
151 |
|
152 |
|
153 | await this._threadsSemaphore.enter();
|
154 |
|
155 | if (this._uncaughtErrors.length) {
|
156 | break;
|
157 | }
|
158 |
|
159 | this._allTasksCompleteOrSomeFailedEvent.reset(); // NOTE: no await
|
160 |
|
161 |
|
162 | this._runTask(task);
|
163 | } // wait for completion
|
164 |
|
165 |
|
166 | if (this.startedCount > 0) {
|
167 | await this._allTasksCompleteOrSomeFailedEvent.wait();
|
168 | }
|
169 |
|
170 | this._throwUncaughtErrors();
|
171 | } finally {
|
172 | this._completeEvent.signal();
|
173 | }
|
174 | }
|
175 | /**
|
176 | * Starts executing all queued tasks
|
177 | *
|
178 | * This function should not be awaited - it will return immediatly
|
179 | */
|
180 |
|
181 |
|
182 | startRun() {
|
183 | (async () => {
|
184 | try {
|
185 | await this.run();
|
186 | } catch (err) {} // eslint-disable-line no-empty
|
187 |
|
188 | })();
|
189 | }
|
190 | /**
|
191 | * Closes the ThreadPool for further task queueing, the ThreadPool's completion can be awaited afte'r it's called
|
192 | */
|
193 |
|
194 |
|
195 | close() {
|
196 | this._closed = true;
|
197 |
|
198 | this._queuedTasks.close(); // NOTE: NO AWAIT
|
199 | // TODO: await completion
|
200 |
|
201 | }
|
202 | /**
|
203 | * Closes the ThreadPool, runs it's tasks and awaits their completion
|
204 | */
|
205 |
|
206 |
|
207 | async runAllQueued() {
|
208 | this.close();
|
209 | await this.run();
|
210 | return this._res;
|
211 | }
|
212 | /**
|
213 | * Awaits the closing and completion of all ThreadPool tasks
|
214 | */
|
215 |
|
216 |
|
217 | async waitComplete() {
|
218 | await this._completeEvent.wait();
|
219 |
|
220 | this._throwUncaughtErrors();
|
221 |
|
222 | return this._res;
|
223 | }
|
224 | /**
|
225 | * Closes the ThreadPool and awaits the running and completion of all ThreadPool tasks
|
226 | */
|
227 |
|
228 |
|
229 | async closeAndWaitComplete() {
|
230 | this.close();
|
231 | return await this.waitComplete();
|
232 | }
|
233 | /****************** privates ******************/
|
234 |
|
235 |
|
236 | _throwUncaughtErrors() {
|
237 | if (this._uncaughtErrors.length > 0) {
|
238 | throw new _errorUtils.ExtendedError(`Errors were thrown during execution of ThreadPool`, {
|
239 | threadPoolName: this._options.name,
|
240 | errorCount: this._uncaughtErrors.length,
|
241 | errorMessages: this._uncaughtErrors.map(e => e.message),
|
242 | uncaughtErrors: this._uncaughtErrors
|
243 | });
|
244 | }
|
245 | }
|
246 |
|
247 | async _runTask(task) {
|
248 | try {
|
249 | this.startedCount++;
|
250 | await task.func();
|
251 | } catch (err) {
|
252 | try {
|
253 | this._errorHandler(err);
|
254 | } catch (err2) {
|
255 | this._uncaughtErrors.push(err2);
|
256 |
|
257 | await this._allTasksCompleteOrSomeFailedEvent.signal();
|
258 | }
|
259 | } finally {
|
260 | this.endedCount++; // fire 'progress' event
|
261 |
|
262 | this.emit('progress', {
|
263 | endedCount: this.endedCount
|
264 | });
|
265 |
|
266 | this._threadsSemaphore.exit();
|
267 |
|
268 | if (this._threadsSemaphore.takenCount === 0) {
|
269 | this._allTasksCompleteOrSomeFailedEvent.signal();
|
270 | }
|
271 | }
|
272 | }
|
273 |
|
274 | }
|
275 |
|
276 | exports.default = ThreadPool;
|
277 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9UaHJlYWRQb29sLmpzIl0sIm5hbWVzIjpbIlRocmVhZFBvb2wiLCJFdmVudEVtaXR0ZXIiLCJydW4iLCJvcHRpb25zIiwiZXJyb3JIYW5kbGVyIiwiZXJyIiwidHAiLCJpdGVtcyIsInF1ZXVlSXRlbXMiLCJydW5BbGxRdWV1ZWQiLCJhbGwiLCJ0YXNrIiwidGhyZWFkcyIsImNvbnN0cnVjdG9yIiwiX29wdGlvbnMiLCJJbmZpbml0eSIsIl9lcnJvckhhbmRsZXIiLCJfcXVldWVkVGFza3MiLCJBc3luY1F1ZXVlIiwibmFtZSIsIm1heFNpemUiLCJxdWV1ZU1heFNpemUiLCJfdGhyZWFkc1NlbWFwaG9yZSIsIlNlbWFwaG9yZSIsIl9jb21wbGV0ZUV2ZW50IiwiT25lVGltZUJyb2FkY2FzdEV2ZW50IiwiX2FsbFRhc2tzQ29tcGxldGVPclNvbWVGYWlsZWRFdmVudCIsInF1ZXVlSXRlbSIsIml0ZW0iLCJfY2xvc2VkIiwiRXJyb3IiLCJpbmRleCIsInF1ZXVlZENvdW50IiwiZW5xdWV1ZSIsImZ1bmMiLCJfcmVzIiwiZGVxdWV1ZSIsIlF1ZXVlQ2xvc2VkRXJyb3IiLCJlbnRlciIsIl91bmNhdWdodEVycm9ycyIsImxlbmd0aCIsInJlc2V0IiwiX3J1blRhc2siLCJzdGFydGVkQ291bnQiLCJ3YWl0IiwiX3Rocm93VW5jYXVnaHRFcnJvcnMiLCJzaWduYWwiLCJzdGFydFJ1biIsImNsb3NlIiwid2FpdENvbXBsZXRlIiwiY2xvc2VBbmRXYWl0Q29tcGxldGUiLCJFeHRlbmRlZEVycm9yIiwidGhyZWFkUG9vbE5hbWUiLCJlcnJvckNvdW50IiwiZXJyb3JNZXNzYWdlcyIsIm1hcCIsImUiLCJtZXNzYWdlIiwidW5jYXVnaHRFcnJvcnMiLCJlcnIyIiwicHVzaCIsImVuZGVkQ291bnQiLCJlbWl0IiwiZXhpdCIsInRha2VuQ291bnQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFFQTs7QUFDQTs7QUFFQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFpQkE7Ozs7Ozs7QUFPZSxNQUFNQSxVQUFOLFNBQStCQyxlQUEvQixDQUE0QztBQWlCekQsZUFBYUMsR0FBYixDQUFpQkMsT0FBakIsRUFBc0U7QUFDcEVBLElBQUFBLE9BQU8sQ0FBQ0MsWUFBUixHQUF1QkQsT0FBTyxDQUFDQyxZQUFSLEtBQTBCQyxHQUFELElBQVM7QUFBRSxZQUFNQSxHQUFOO0FBQVcsS0FBL0MsQ0FBdkI7O0FBQ0EsVUFBTUMsRUFBRSxHQUFHLElBQUlOLFVBQUosQ0FBZUcsT0FBZixDQUFYOztBQUNBLFFBQUlBLE9BQU8sQ0FBQ0ksS0FBWixFQUFtQjtBQUNqQixZQUFNRCxFQUFFLENBQUNFLFVBQUgsQ0FBY0wsT0FBTyxDQUFDSSxLQUF0QixDQUFOO0FBQ0Q7O0FBQ0QsV0FBTyxNQUFNRCxFQUFFLENBQUNHLFlBQUgsRUFBYjtBQUNEOztBQUVELGVBQWFDLEdBQWIsQ0FBaUJILEtBQWpCLEVBQWtDSSxJQUFsQyxFQUFpRUMsT0FBakUsRUFBc0c7QUFDcEcsVUFBTU4sRUFBRSxHQUFHLElBQUlOLFVBQUosQ0FBZTtBQUN4QlcsTUFBQUEsSUFBSSxFQUFFQSxJQURrQjtBQUV4QkMsTUFBQUEsT0FBTyxFQUFFQSxPQUZlO0FBR3hCTCxNQUFBQSxLQUFLLEVBQUVBO0FBSGlCLEtBQWYsQ0FBWDs7QUFLQSxRQUFJQSxLQUFKLEVBQVc7QUFDVCxZQUFNRCxFQUFFLENBQUNFLFVBQUgsQ0FBY0QsS0FBZCxDQUFOO0FBQ0Q7O0FBQ0QsV0FBTyxNQUFNRCxFQUFFLENBQUNHLFlBQUgsRUFBYjtBQUNEO0FBR0Q7Ozs7O0FBR0FJLEVBQUFBLFdBQVcsQ0FBQ1YsT0FBRCxFQUFtQztBQUM1Qzs7QUFENEMseUNBeEN4QixDQXdDd0I7O0FBQUEsMENBdkN2QixDQXVDdUI7O0FBQUEsd0NBdEN6QixDQXNDeUI7O0FBQUE7O0FBQUE7O0FBQUEsNkNBbENkLEVBa0NjOztBQUFBLHFDQWpDM0IsS0FpQzJCOztBQUFBOztBQUFBOztBQUFBOztBQUFBOztBQUFBLGtDQTVCN0IsRUE0QjZCOztBQUc1QyxTQUFLVyxRQUFMLEdBQWdCWCxPQUFoQjtBQUNBLFNBQUtXLFFBQUwsQ0FBY0YsT0FBZCxHQUF3QixLQUFLRSxRQUFMLENBQWNGLE9BQWQsSUFBeUJHLFFBQWpEOztBQUVBLFNBQUtDLGFBQUwsR0FBcUIsS0FBS0YsUUFBTCxDQUFjVixZQUFkLEtBQWdDQyxHQUFELElBQVM7QUFBRSxZQUFNQSxHQUFOO0FBQVcsS0FBckQsQ0FBckIsQ0FONEMsQ0FNZ0M7OztBQUU1RSxTQUFLWSxZQUFMLEdBQW9CLElBQUlDLG1CQUFKLENBQWU7QUFDakNDLE1BQUFBLElBQUksRUFBRWhCLE9BQU8sQ0FBQ2dCLElBRG1CO0FBRWpDQyxNQUFBQSxPQUFPLEVBQUVqQixPQUFPLENBQUNrQjtBQUZnQixLQUFmLENBQXBCO0FBSUEsU0FBS0MsaUJBQUwsR0FBeUIsSUFBSUMseUJBQUosQ0FBYyxLQUFLVCxRQUFMLENBQWNGLE9BQTVCLENBQXpCO0FBQ0EsU0FBS1ksY0FBTCxHQUFzQixJQUFJQyxxQ0FBSixDQUEwQixLQUExQixDQUF0QjtBQUNBLFNBQUtDLGtDQUFMLEdBQTBDLElBQUlELHFDQUFKLENBQTBCLEtBQTFCLENBQTFDO0FBRUEsMkJBQVMsSUFBVDtBQUNEO0FBRUQ7Ozs7O0FBR0EsUUFBTUUsU0FBTixDQUFnQkMsSUFBaEIsRUFBd0M7QUFDdEMsUUFBSSxLQUFLQyxPQUFULEVBQ0UsTUFBTSxJQUFJQyxLQUFKLENBQVcsOENBQVgsQ0FBTjtBQUVGLFVBQU1DLEtBQUssR0FBRyxLQUFLQyxXQUFMLEVBQWQ7QUFDQSxVQUFNLEtBQUtmLFlBQUwsQ0FBa0JnQixPQUFsQixDQUEwQjtBQUM5QkMsTUFBQUEsSUFBSSxFQUFFLFlBQVksS0FBS0MsSUFBTCxDQUFVSixLQUFWLElBQW1CLE1BQU0sS0FBS2pCLFFBQUwsQ0FBY0gsSUFBZCxDQUFtQmlCLElBQW5CLENBRGI7QUFFOUJHLE1BQUFBLEtBQUssRUFBRUE7QUFGdUIsS0FBMUIsQ0FBTjtBQUlEO0FBRUQ7Ozs7O0FBR0EsUUFBTXZCLFVBQU4sQ0FBaUJtQixTQUFqQixFQUFxRDtBQUNuRCxTQUFLLE1BQU1DLElBQVgsSUFBbUJELFNBQW5CLEVBQThCO0FBQzVCLFlBQU0sS0FBS0EsU0FBTCxDQUFlQyxJQUFmLENBQU47QUFDRDtBQUNGO0FBRUQ7Ozs7Ozs7QUFLQSxRQUFNMUIsR0FBTixHQUFZO0FBQ1YsUUFBSTtBQUNGLGFBQU8sSUFBUCxFQUFhO0FBRVg7QUFDQTtBQUNBLFlBQUlTLElBQUo7O0FBQ0EsWUFBSTtBQUNGQSxVQUFBQSxJQUFJLEdBQUcsTUFBTSxLQUFLTSxZQUFMLENBQWtCbUIsT0FBbEIsRUFBYjtBQUNELFNBRkQsQ0FFRSxPQUFPL0IsR0FBUCxFQUFZO0FBQ1osY0FBSUEsR0FBRyxZQUFZZ0MsNEJBQW5CLEVBQ0U7QUFDRixnQkFBTWhDLEdBQU47QUFDRCxTQVhVLENBYVg7OztBQUNBLGNBQU0sS0FBS2lCLGlCQUFMLENBQXVCZ0IsS0FBdkIsRUFBTjs7QUFDQSxZQUFJLEtBQUtDLGVBQUwsQ0FBcUJDLE1BQXpCLEVBQWlDO0FBQy9CO0FBQ0Q7O0FBRUQsYUFBS2Qsa0NBQUwsQ0FBd0NlLEtBQXhDLEdBbkJXLENBcUJYOzs7QUFDQSxhQUFLQyxRQUFMLENBQWMvQixJQUFkO0FBQ0QsT0F4QkMsQ0EwQkY7OztBQUNBLFVBQUksS0FBS2dDLFlBQUwsR0FBb0IsQ0FBeEIsRUFBMkI7QUFDekIsY0FBTSxLQUFLakIsa0NBQUwsQ0FBd0NrQixJQUF4QyxFQUFOO0FBQ0Q7O0FBRUQsV0FBS0Msb0JBQUw7QUFDRCxLQWhDRCxTQWdDVTtBQUNSLFdBQUtyQixjQUFMLENBQW9Cc0IsTUFBcEI7QUFDRDtBQUNGO0FBRUQ7Ozs7Ozs7QUFLQUMsRUFBQUEsUUFBUSxHQUFHO0FBQ1QsS0FBQyxZQUFZO0FBQ1gsVUFBSTtBQUNGLGNBQU0sS0FBSzdDLEdBQUwsRUFBTjtBQUNELE9BRkQsQ0FFRSxPQUFPRyxHQUFQLEVBQVksQ0FBRSxDQUhMLENBR007O0FBQ2xCLEtBSkQ7QUFLRDtBQUVEOzs7OztBQUdBMkMsRUFBQUEsS0FBSyxHQUFHO0FBQ04sU0FBS25CLE9BQUwsR0FBZSxJQUFmOztBQUNBLFNBQUtaLFlBQUwsQ0FBa0IrQixLQUFsQixHQUZNLENBRW9CO0FBQzFCOztBQUNEO0FBRUQ7Ozs7O0FBR0EsUUFBTXZDLFlBQU4sR0FBd0M7QUFDdEMsU0FBS3VDLEtBQUw7QUFDQSxVQUFNLEtBQUs5QyxHQUFMLEVBQU47QUFDQSxXQUFPLEtBQUtpQyxJQUFaO0FBQ0Q7QUFFRDs7Ozs7QUFHQSxRQUFNYyxZQUFOLEdBQXdDO0FBQ3RDLFVBQU0sS0FBS3pCLGNBQUwsQ0FBb0JvQixJQUFwQixFQUFOOztBQUNBLFNBQUtDLG9CQUFMOztBQUNBLFdBQU8sS0FBS1YsSUFBWjtBQUNEO0FBRUQ7Ozs7O0FBR0EsUUFBTWUsb0JBQU4sR0FBZ0Q7QUFDOUMsU0FBS0YsS0FBTDtBQUNBLFdBQU8sTUFBTSxLQUFLQyxZQUFMLEVBQWI7QUFDRDtBQUVEOzs7QUFFQUosRUFBQUEsb0JBQW9CLEdBQUc7QUFDckIsUUFBSSxLQUFLTixlQUFMLENBQXFCQyxNQUFyQixHQUE4QixDQUFsQyxFQUFxQztBQUNuQyxZQUFNLElBQUlXLHlCQUFKLENBQW1CLG1EQUFuQixFQUF1RTtBQUMzRUMsUUFBQUEsY0FBYyxFQUFFLEtBQUt0QyxRQUFMLENBQWNLLElBRDZDO0FBRTNFa0MsUUFBQUEsVUFBVSxFQUFFLEtBQUtkLGVBQUwsQ0FBcUJDLE1BRjBDO0FBRzNFYyxRQUFBQSxhQUFhLEVBQUUsS0FBS2YsZUFBTCxDQUFxQmdCLEdBQXJCLENBQXlCQyxDQUFDLElBQUlBLENBQUMsQ0FBQ0MsT0FBaEMsQ0FINEQ7QUFJM0VDLFFBQUFBLGNBQWMsRUFBRSxLQUFLbkI7QUFKc0QsT0FBdkUsQ0FBTjtBQU1EO0FBQ0Y7O0FBRUQsUUFBTUcsUUFBTixDQUFlL0IsSUFBZixFQUE4QjtBQUM1QixRQUFJO0FBQ0YsV0FBS2dDLFlBQUw7QUFDQSxZQUFNaEMsSUFBSSxDQUFDdUIsSUFBTCxFQUFOO0FBQ0QsS0FIRCxDQUdFLE9BQU83QixHQUFQLEVBQVk7QUFDWixVQUFJO0FBQ0YsYUFBS1csYUFBTCxDQUFtQlgsR0FBbkI7QUFDRCxPQUZELENBRUUsT0FBT3NELElBQVAsRUFBYTtBQUNiLGFBQUtwQixlQUFMLENBQXFCcUIsSUFBckIsQ0FBMEJELElBQTFCOztBQUNBLGNBQU0sS0FBS2pDLGtDQUFMLENBQXdDb0IsTUFBeEMsRUFBTjtBQUNEO0FBQ0YsS0FWRCxTQVVVO0FBQ1IsV0FBS2UsVUFBTCxHQURRLENBRVI7O0FBQ0EsV0FBS0MsSUFBTCxDQUFVLFVBQVYsRUFBc0I7QUFBRUQsUUFBQUEsVUFBVSxFQUFFLEtBQUtBO0FBQW5CLE9BQXRCOztBQUNBLFdBQUt2QyxpQkFBTCxDQUF1QnlDLElBQXZCOztBQUNBLFVBQUksS0FBS3pDLGlCQUFMLENBQXVCMEMsVUFBdkIsS0FBc0MsQ0FBMUMsRUFBNkM7QUFDM0MsYUFBS3RDLGtDQUFMLENBQXdDb0IsTUFBeEM7QUFDRDtBQUNGO0FBQ0Y7O0FBaE53RCIsInNvdXJjZXNDb250ZW50IjpbIi8vIEBmbG93XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSAnZXZlbnRzJ1xuaW1wb3J0IGF1dG9CaW5kIGZyb20gJ2F1dG8tYmluZCdcblxuaW1wb3J0IEFzeW5jUXVldWUsIHsgUXVldWVDbG9zZWRFcnJvciB9IGZyb20gJy4vQXN5bmNRdWV1ZSdcbmltcG9ydCB7IE9uZVRpbWVCcm9hZGNhc3RFdmVudCwgU2VtYXBob3JlIH0gZnJvbSAnLi9hc3luY1N5bmNVdGlscydcbmltcG9ydCB7IEV4dGVuZGVkRXJyb3IgfSBmcm9tICcuL2Vycm9yVXRpbHMnXG5cblxudHlwZSBUaHJlYWRQb29sT3B0aW9uczxULCBSPiA9IHtcbiAgbmFtZT86ID9zdHJpbmcsXG4gIHRocmVhZHM/OiA/bnVtYmVyLFxuICBpdGVtcz86ID9BcnJheTxUPixcbiAgdGFzazogKGl0ZW06IFQpID0+IFByb21pc2U8Uj4sXG4gIGVycm9ySGFuZGxlcj86ID8oZXJyOiBFcnJvcikgPT4gdm9pZCwgXG4gIHF1ZXVlTWF4U2l6ZT86ID9udW1iZXIsXG59XG5cbnR5cGUgVGFzazxSPiA9IHsgXG4gIGZ1bmM6ICgpID0+IFByb21pc2U8Uj4sIFxuICBpbmRleDogbnVtYmVyLFxufVxuXG4vKipcbiAqIEEgdGhyZWFkLXBvb2wgYWJzdHJhY3Rpb24gZm9yIEVTNiBhc3luYyBvcGVyYXRpb25zXCIsXG4gKiBcbiAqIEBleHBvcnRcbiAqIEBjbGFzcyBUaHJlYWRQb29sXG4gKiBAZXh0ZW5kcyB7RXZlbnRFbWl0dGVyfVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUaHJlYWRQb29sPFQsIFI+IGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgXG4gIHF1ZXVlZENvdW50OiBudW1iZXIgPSAwXG4gIHN0YXJ0ZWRDb3VudDogbnVtYmVyID0gMFxuICBlbmRlZENvdW50OiBudW1iZXIgPSAwXG5cbiAgX29wdGlvbnM6IFRocmVhZFBvb2xPcHRpb25zPFQsIFI+XG4gIF9lcnJvckhhbmRsZXI6IChlcnI6IEVycm9yKSA9PiB2b2lkXG4gIF91bmNhdWdodEVycm9yczogQXJyYXk8RXJyb3I+ID0gW11cbiAgX2Nsb3NlZDogYm9vbGVhbiA9IGZhbHNlXG4gIF9xdWV1ZWRUYXNrczogQXN5bmNRdWV1ZTx7IGZ1bmM6ICgpID0+IFByb21pc2U8Uj4sIGluZGV4OiBudW1iZXIgfT5cbiAgX3RocmVhZHNTZW1hcGhvcmU6IFNlbWFwaG9yZVxuICBfY29tcGxldGVFdmVudDogT25lVGltZUJyb2FkY2FzdEV2ZW50XG4gIF9hbGxUYXNrc0NvbXBsZXRlT3JTb21lRmFpbGVkRXZlbnQ6IE9uZVRpbWVCcm9hZGNhc3RFdmVudFxuICBfcmVzOiBBcnJheTxSPiA9IFtdXG5cblxuICBzdGF0aWMgYXN5bmMgcnVuKG9wdGlvbnM6IFRocmVhZFBvb2xPcHRpb25zPFQsIFI+KTogUHJvbWlzZTxBcnJheTxSPj4ge1xuICAgIG9wdGlvbnMuZXJyb3JIYW5kbGVyID0gb3B0aW9ucy5lcnJvckhhbmRsZXIgfHwgKChlcnIpID0+IHsgdGhyb3cgZXJyIH0pXG4gICAgY29uc3QgdHAgPSBuZXcgVGhyZWFkUG9vbChvcHRpb25zKVxuICAgIGlmIChvcHRpb25zLml0ZW1zKSB7XG4gICAgICBhd2FpdCB0cC5xdWV1ZUl0ZW1zKG9wdGlvbnMuaXRlbXMpXG4gICAgfVxuICAgIHJldHVybiBhd2FpdCB0cC5ydW5BbGxRdWV1ZWQoKVxuICB9XG5cbiAgc3RhdGljIGFzeW5jIGFsbChpdGVtczogQXJyYXk8VD4sIHRhc2s6IChpdGVtOiBUKSA9PiBQcm9taXNlPFI+LCB0aHJlYWRzOiA/bnVtYmVyKTogUHJvbWlzZTxBcnJheTxSPj4ge1xuICAgIGNvbnN0IHRwID0gbmV3IFRocmVhZFBvb2woe1xuICAgICAgdGFzazogdGFzayxcbiAgICAgIHRocmVhZHM6IHRocmVhZHMsXG4gICAgICBpdGVtczogaXRlbXMsXG4gICAgfSlcbiAgICBpZiAoaXRlbXMpIHtcbiAgICAgIGF3YWl0IHRwLnF1ZXVlSXRlbXMoaXRlbXMpXG4gICAgfVxuICAgIHJldHVybiBhd2FpdCB0cC5ydW5BbGxRdWV1ZWQoKVxuICB9XG5cblxuICAvKipcbiAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBUaHJlYWRQb29sXG4gICAqL1xuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBUaHJlYWRQb29sT3B0aW9uczxULCBSPikge1xuICAgIHN1cGVyKClcblxuICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zXG4gICAgdGhpcy5fb3B0aW9ucy50aHJlYWRzID0gdGhpcy5fb3B0aW9ucy50aHJlYWRzIHx8IEluZmluaXR5XG5cbiAgICB0aGlzLl9lcnJvckhhbmRsZXIgPSB0aGlzLl9vcHRpb25zLmVycm9ySGFuZGxlciB8fCAoKGVycikgPT4geyB0aHJvdyBlcnIgfSkgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlXG5cbiAgICB0aGlzLl9xdWV1ZWRUYXNrcyA9IG5ldyBBc3luY1F1ZXVlKHsgXG4gICAgICBuYW1lOiBvcHRpb25zLm5hbWUsXG4gICAgICBtYXhTaXplOiBvcHRpb25zLnF1ZXVlTWF4U2l6ZSxcbiAgICB9KVxuICAgIHRoaXMuX3RocmVhZHNTZW1hcGhvcmUgPSBuZXcgU2VtYXBob3JlKHRoaXMuX29wdGlvbnMudGhyZWFkcylcbiAgICB0aGlzLl9jb21wbGV0ZUV2ZW50ID0gbmV3IE9uZVRpbWVCcm9hZGNhc3RFdmVudChmYWxzZSlcbiAgICB0aGlzLl9hbGxUYXNrc0NvbXBsZXRlT3JTb21lRmFpbGVkRXZlbnQgPSBuZXcgT25lVGltZUJyb2FkY2FzdEV2ZW50KGZhbHNlKVxuXG4gICAgYXV0b0JpbmQodGhpcylcbiAgfVxuXG4gIC8qKlxuICAgKiBRdWV1ZXMgYW4gaXRtZSBmcm9tIHRoZSBUaHJlYWRQb29sXG4gICAqL1xuICBhc3luYyBxdWV1ZUl0ZW0oaXRlbTogVCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLl9jbG9zZWQpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRyeWluZyB0byBxdWV1ZSBhIGpvYiB0byBhIGNsb3NlZCBUaHJlYWRQb29sYClcblxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5xdWV1ZWRDb3VudCsrICAgXG4gICAgYXdhaXQgdGhpcy5fcXVldWVkVGFza3MuZW5xdWV1ZSh7IFxuICAgICAgZnVuYzogYXN5bmMgKCkgPT4gdGhpcy5fcmVzW2luZGV4XSA9IGF3YWl0IHRoaXMuX29wdGlvbnMudGFzayhpdGVtKSwgXG4gICAgICBpbmRleDogaW5kZXgsXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBRdWV1ZXMgYW4gaXRtZSBmcm9tIHRoZSBUaHJlYWRQb29sXG4gICAqL1xuICBhc3luYyBxdWV1ZUl0ZW1zKHF1ZXVlSXRlbTogQXJyYXk8VD4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgcXVldWVJdGVtKSB7XG4gICAgICBhd2FpdCB0aGlzLnF1ZXVlSXRlbShpdGVtKVxuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIFN0YXJ0cyBleGVjdXRpbmcgYWxsIHF1ZXVlZCB0YXNrc1xuICAgKiBcbiAgICogVGhpcyBmdW5jdGlvbiBzaG91bGQgYmUgYXdhaXRlZCAtIGl0IHdpbGwgcmV0dXJuIGFmdGVyIHRoZSBUaHJlYWRQb29sIGhhcyBiZWVuIGNsb3NlZCBhbmQgYWxsIGl0J3MgdGFza3MgY29tcGxldGVkLCBvciBhZnRlciBhIHRhc2sgdGhyZXcgYW4gZXJyb3IuXG4gICAqL1xuICBhc3luYyBydW4oKSB7XG4gICAgdHJ5IHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG5cbiAgICAgICAgLy8gd2FpdCBmb3IgYW4gYXZhaWxhYmxlIHRhc2tcbiAgICAgICAgLy8gVE9ETzogYWxzbyB3YWl0IGZvciBlcnJvcnMgaGVyZT9cbiAgICAgICAgbGV0IHRhc2tcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0YXNrID0gYXdhaXQgdGhpcy5fcXVldWVkVGFza3MuZGVxdWV1ZSgpXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBRdWV1ZUNsb3NlZEVycm9yKVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB0aHJvdyBlcnJcbiAgICAgICAgfVxuICBcbiAgICAgICAgLy8gd2FpdCBmb3IgYW4gYXZhaWxhYmxlICd0aHJlYWQnXG4gICAgICAgIGF3YWl0IHRoaXMuX3RocmVhZHNTZW1hcGhvcmUuZW50ZXIoKVxuICAgICAgICBpZiAodGhpcy5fdW5jYXVnaHRFcnJvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICBcbiAgICAgICAgdGhpcy5fYWxsVGFza3NDb21wbGV0ZU9yU29tZUZhaWxlZEV2ZW50LnJlc2V0KClcbiAgICAgICAgXG4gICAgICAgIC8vIE5PVEU6IG5vIGF3YWl0XG4gICAgICAgIHRoaXMuX3J1blRhc2sodGFzaylcbiAgICAgIH1cbiAgXG4gICAgICAvLyB3YWl0IGZvciBjb21wbGV0aW9uXG4gICAgICBpZiAodGhpcy5zdGFydGVkQ291bnQgPiAwKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX2FsbFRhc2tzQ29tcGxldGVPclNvbWVGYWlsZWRFdmVudC53YWl0KClcbiAgICAgIH1cbiAgXG4gICAgICB0aGlzLl90aHJvd1VuY2F1Z2h0RXJyb3JzKClcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5fY29tcGxldGVFdmVudC5zaWduYWwoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydHMgZXhlY3V0aW5nIGFsbCBxdWV1ZWQgdGFza3NcbiAgICogXG4gICAqIFRoaXMgZnVuY3Rpb24gc2hvdWxkIG5vdCBiZSBhd2FpdGVkIC0gaXQgd2lsbCByZXR1cm4gaW1tZWRpYXRseVxuICAgKi9cbiAgc3RhcnRSdW4oKSB7XG4gICAgKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMucnVuKClcbiAgICAgIH0gY2F0Y2ggKGVycikge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1lbXB0eVxuICAgIH0pKClcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgdGhlIFRocmVhZFBvb2wgZm9yIGZ1cnRoZXIgdGFzayBxdWV1ZWluZywgdGhlIFRocmVhZFBvb2wncyBjb21wbGV0aW9uIGNhbiBiZSBhd2FpdGVkIGFmdGUnciBpdCdzIGNhbGxlZFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgdGhpcy5fY2xvc2VkID0gdHJ1ZVxuICAgIHRoaXMuX3F1ZXVlZFRhc2tzLmNsb3NlKCkgLy8gTk9URTogTk8gQVdBSVRcbiAgICAvLyBUT0RPOiBhd2FpdCBjb21wbGV0aW9uXG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIHRoZSBUaHJlYWRQb29sLCBydW5zIGl0J3MgdGFza3MgYW5kIGF3YWl0cyB0aGVpciBjb21wbGV0aW9uXG4gICAqL1xuICBhc3luYyBydW5BbGxRdWV1ZWQoKTogUHJvbWlzZTxBcnJheTxSPj4ge1xuICAgIHRoaXMuY2xvc2UoKVxuICAgIGF3YWl0IHRoaXMucnVuKClcbiAgICByZXR1cm4gdGhpcy5fcmVzXG4gIH1cblxuICAvKipcbiAgICogQXdhaXRzIHRoZSBjbG9zaW5nIGFuZCBjb21wbGV0aW9uIG9mIGFsbCBUaHJlYWRQb29sIHRhc2tzXG4gICAqL1xuICBhc3luYyB3YWl0Q29tcGxldGUoKTogUHJvbWlzZTxBcnJheTxSPj4ge1xuICAgIGF3YWl0IHRoaXMuX2NvbXBsZXRlRXZlbnQud2FpdCgpXG4gICAgdGhpcy5fdGhyb3dVbmNhdWdodEVycm9ycygpXG4gICAgcmV0dXJuIHRoaXMuX3Jlc1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyB0aGUgVGhyZWFkUG9vbCBhbmQgYXdhaXRzIHRoZSBydW5uaW5nIGFuZCBjb21wbGV0aW9uIG9mIGFsbCBUaHJlYWRQb29sIHRhc2tzXG4gICAqL1xuICBhc3luYyBjbG9zZUFuZFdhaXRDb21wbGV0ZSgpOiBQcm9taXNlPEFycmF5PFI+PiB7XG4gICAgdGhpcy5jbG9zZSgpXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMud2FpdENvbXBsZXRlKClcbiAgfVxuXG4gIC8qKioqKioqKioqKioqKioqKiogcHJpdmF0ZXMgKioqKioqKioqKioqKioqKioqL1xuXG4gIF90aHJvd1VuY2F1Z2h0RXJyb3JzKCkgeyAgIFxuICAgIGlmICh0aGlzLl91bmNhdWdodEVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXh0ZW5kZWRFcnJvcihgRXJyb3JzIHdlcmUgdGhyb3duIGR1cmluZyBleGVjdXRpb24gb2YgVGhyZWFkUG9vbGAsIHtcbiAgICAgICAgdGhyZWFkUG9vbE5hbWU6IHRoaXMuX29wdGlvbnMubmFtZSxcbiAgICAgICAgZXJyb3JDb3VudDogdGhpcy5fdW5jYXVnaHRFcnJvcnMubGVuZ3RoLFxuICAgICAgICBlcnJvck1lc3NhZ2VzOiB0aGlzLl91bmNhdWdodEVycm9ycy5tYXAoZSA9PiBlLm1lc3NhZ2UpLFxuICAgICAgICB1bmNhdWdodEVycm9yczogdGhpcy5fdW5jYXVnaHRFcnJvcnMsXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIF9ydW5UYXNrKHRhc2s6IFRhc2s8Uj4pIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5zdGFydGVkQ291bnQrK1xuICAgICAgYXdhaXQgdGFzay5mdW5jKClcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuX2Vycm9ySGFuZGxlcihlcnIpXG4gICAgICB9IGNhdGNoIChlcnIyKSB7XG4gICAgICAgIHRoaXMuX3VuY2F1Z2h0RXJyb3JzLnB1c2goZXJyMilcbiAgICAgICAgYXdhaXQgdGhpcy5fYWxsVGFza3NDb21wbGV0ZU9yU29tZUZhaWxlZEV2ZW50LnNpZ25hbCgpXG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuZW5kZWRDb3VudCsrICAgICAgICAgIFxuICAgICAgLy8gZmlyZSAncHJvZ3Jlc3MnIGV2ZW50XG4gICAgICB0aGlzLmVtaXQoJ3Byb2dyZXNzJywgeyBlbmRlZENvdW50OiB0aGlzLmVuZGVkQ291bnQgfSlcbiAgICAgIHRoaXMuX3RocmVhZHNTZW1hcGhvcmUuZXhpdCgpXG4gICAgICBpZiAodGhpcy5fdGhyZWFkc1NlbWFwaG9yZS50YWtlbkNvdW50ID09PSAwKSB7XG4gICAgICAgIHRoaXMuX2FsbFRhc2tzQ29tcGxldGVPclNvbWVGYWlsZWRFdmVudC5zaWduYWwoKVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19 |
\ | No newline at end of file |