@discordeno/rest 21.0.1-next.f6ea699 → 22.0.0-beta.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/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/invalidBucket.d.ts.map +1 -0
- package/dist/invalidBucket.js +82 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +1623 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +154 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +621 -0
- package/dist/{types/types.d.ts → types.d.ts} +9 -7
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/{types/typings → typings}/routes.d.ts +3 -3
- package/dist/typings/routes.d.ts.map +1 -0
- package/dist/typings/routes.js +3 -0
- package/package.json +15 -22
- package/dist/cjs/index.cjs +0 -25
- package/dist/cjs/invalidBucket.cjs +0 -86
- package/dist/cjs/manager.cjs +0 -1643
- package/dist/cjs/queue.cjs +0 -164
- package/dist/cjs/routes.cjs +0 -630
- package/dist/cjs/types.cjs +0 -6
- package/dist/cjs/typings/routes.cjs +0 -6
- package/dist/esm/index.js +0 -8
- package/dist/esm/invalidBucket.js +0 -82
- package/dist/esm/manager.js +0 -1601
- package/dist/esm/queue.js +0 -154
- package/dist/esm/routes.js +0 -620
- package/dist/esm/types.js +0 -3
- package/dist/esm/typings/routes.js +0 -3
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/invalidBucket.d.ts.map +0 -1
- package/dist/types/manager.d.ts.map +0 -1
- package/dist/types/queue.d.ts.map +0 -1
- package/dist/types/routes.d.ts.map +0 -1
- package/dist/types/types.d.ts.map +0 -1
- package/dist/types/typings/routes.d.ts.map +0 -1
- /package/dist/{types/index.d.ts → index.d.ts} +0 -0
- /package/dist/{types/invalidBucket.d.ts → invalidBucket.d.ts} +0 -0
- /package/dist/{types/manager.d.ts → manager.d.ts} +0 -0
- /package/dist/{types/queue.d.ts → queue.d.ts} +0 -0
- /package/dist/{types/routes.d.ts → routes.d.ts} +0 -0
package/dist/cjs/queue.cjs
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "Queue", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return Queue;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _utils = require("@discordeno/utils");
|
|
12
|
-
let Queue = class Queue {
|
|
13
|
-
constructor(rest, options){
|
|
14
|
-
/** Amount of requests that have are remaining. Defaults to 1. */ this.remaining = 1;
|
|
15
|
-
/** Max requests for this this. Defaults to 1. */ this.max = 1;
|
|
16
|
-
/** The time that discord allows to make the max number of requests. Defaults to 0 */ this.interval = 0;
|
|
17
|
-
/** The requests that are currently pending. */ this.waiting = [];
|
|
18
|
-
/** The requests that are currently pending. */ this.pending = [];
|
|
19
|
-
/** Whether or not the waiting queue is already processing. */ this.processing = false;
|
|
20
|
-
/** Whether or not the pending queue is already processing. */ this.processingPending = false;
|
|
21
|
-
/** Whether the first request is pending. */ this.firstRequest = false;
|
|
22
|
-
/** When requests started being made to determine when the interval will reset it. */ this.frozenAt = 0;
|
|
23
|
-
/** The time in milliseconds to wait before deleting this queue if it is empty. Defaults to 60000(one minute). */ this.deleteQueueDelay = 60000;
|
|
24
|
-
this.rest = rest;
|
|
25
|
-
this.url = options.url;
|
|
26
|
-
this.identifier = options.identifier;
|
|
27
|
-
if (options.interval) this.interval = options.interval;
|
|
28
|
-
if (options.max) this.max = options.max;
|
|
29
|
-
if (options.remaining) this.remaining = options.remaining;
|
|
30
|
-
if (options.timeoutId) this.timeoutId = options.timeoutId;
|
|
31
|
-
if (options.deleteQueueDelay) this.deleteQueueDelay = options.deleteQueueDelay;
|
|
32
|
-
}
|
|
33
|
-
/** Check if there is any remaining requests that are allowed. */ isRequestAllowed() {
|
|
34
|
-
return this.remaining > 0;
|
|
35
|
-
}
|
|
36
|
-
/** Pauses the execution until a request is allowed to be made. */ async waitUntilRequestAvailable() {
|
|
37
|
-
return await new Promise(async (resolve)=>{
|
|
38
|
-
// If whatever amount of requests is left is more than the safety margin, allow the request
|
|
39
|
-
if (this.isRequestAllowed()) {
|
|
40
|
-
// this.remaining++;
|
|
41
|
-
resolve();
|
|
42
|
-
} else {
|
|
43
|
-
this.waiting.push(resolve);
|
|
44
|
-
await this.processWaiting();
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
/** Process the queue of requests waiting to be handled. */ async processWaiting() {
|
|
49
|
-
// If already processing, that loop will handle all waiting requests.
|
|
50
|
-
if (this.processing) return;
|
|
51
|
-
// Mark as processing so other loops don't start
|
|
52
|
-
this.processing = true;
|
|
53
|
-
while(this.waiting.length > 0){
|
|
54
|
-
this.rest.logger.debug(`[Queue] ${this.queueType} ${this.url} process waiting while loop ran.`);
|
|
55
|
-
if (this.isRequestAllowed()) {
|
|
56
|
-
// Resolve the next item in the queue
|
|
57
|
-
this.waiting.shift()?.();
|
|
58
|
-
} else {
|
|
59
|
-
await (0, _utils.delay)(1000);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// Mark as false so next pending request can be triggered by new loop.
|
|
63
|
-
this.processing = false;
|
|
64
|
-
}
|
|
65
|
-
/** Process the queue of all requests pending to be sent. */ async processPending() {
|
|
66
|
-
// If already processing, that loop will handle all pending requests.
|
|
67
|
-
if (this.processingPending || !this.pending.length) return;
|
|
68
|
-
// Mark as processing so other loops don't start
|
|
69
|
-
this.processingPending = true;
|
|
70
|
-
while(this.pending.length > 0){
|
|
71
|
-
this.rest.logger.debug(`Queue ${this.queueType} ${this.url} process pending while loop ran with ${this.pending.length}.`);
|
|
72
|
-
if (!this.firstRequest && !this.isRequestAllowed()) {
|
|
73
|
-
const now = Date.now();
|
|
74
|
-
const future = this.frozenAt + this.interval;
|
|
75
|
-
await (0, _utils.delay)(future > now ? future - now : 1000);
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
const request = this.pending[0];
|
|
79
|
-
if (request) {
|
|
80
|
-
const basicURL = this.rest.simplifyUrl(request.route, request.method);
|
|
81
|
-
// If this url is still rate limited, try again
|
|
82
|
-
const urlResetIn = this.rest.checkRateLimits(basicURL, this.identifier);
|
|
83
|
-
if (urlResetIn) await (0, _utils.delay)(urlResetIn);
|
|
84
|
-
// IF A BUCKET EXISTS, CHECK THE BUCKET'S RATE LIMITS
|
|
85
|
-
const bucketResetIn = request.bucketId ? this.rest.checkRateLimits(request.bucketId, this.identifier) : false;
|
|
86
|
-
if (bucketResetIn) await (0, _utils.delay)(bucketResetIn);
|
|
87
|
-
this.firstRequest = false;
|
|
88
|
-
this.remaining--;
|
|
89
|
-
if (this.remaining === 0 && this.interval !== 0) {
|
|
90
|
-
this.timeoutId ??= setTimeout(()=>{
|
|
91
|
-
this.remaining = this.max;
|
|
92
|
-
this.timeoutId = undefined;
|
|
93
|
-
}, this.interval);
|
|
94
|
-
}
|
|
95
|
-
// Remove from queue, we are executing it.
|
|
96
|
-
this.pending.shift();
|
|
97
|
-
// Check if this request is able to be made globally
|
|
98
|
-
await this.rest.invalidBucket.waitUntilRequestAvailable();
|
|
99
|
-
await this.rest.sendRequest(request)// Should be handled in sendRequest, this catch just prevents bots from dying
|
|
100
|
-
.catch(()=>null);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
this.rest.logger.debug(`Queue ${this.queueType} ${this.url} process pending while loop exited with ${this.pending.length}.`);
|
|
104
|
-
// Mark as false so next pending request can be triggered by new loop.
|
|
105
|
-
this.processingPending = false;
|
|
106
|
-
this.cleanup();
|
|
107
|
-
}
|
|
108
|
-
handleCompletedRequest(headers) {
|
|
109
|
-
if (headers.max === 0) {
|
|
110
|
-
this.remaining++;
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
if (!this.frozenAt) this.frozenAt = Date.now();
|
|
114
|
-
if (headers.interval !== undefined) this.interval = headers.interval;
|
|
115
|
-
if (headers.remaining !== undefined) this.remaining = headers.remaining;
|
|
116
|
-
if (this.remaining <= 1) {
|
|
117
|
-
this.timeoutId ??= setTimeout(()=>{
|
|
118
|
-
this.remaining = this.max;
|
|
119
|
-
this.timeoutId = undefined;
|
|
120
|
-
}, headers.interval);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
/** Checks if a request is available and adds it to the queue. Also triggers queue processing if not already processing. */ async makeRequest(options) {
|
|
124
|
-
await this.waitUntilRequestAvailable();
|
|
125
|
-
this.pending.push(options);
|
|
126
|
-
this.processPending();
|
|
127
|
-
}
|
|
128
|
-
/** Cleans up the queue by checking if there is nothing left and removing it. */ cleanup() {
|
|
129
|
-
if (!this.isQueueClearable()) {
|
|
130
|
-
this.processPending();
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
this.rest.logger.debug(`[Queue] ${this.queueType} ${this.url}. Delaying delete for ${this.deleteQueueDelay}ms`);
|
|
134
|
-
// Delete in a minute giving a bit of time to allow new requests that may reuse this queue
|
|
135
|
-
clearTimeout(this.deleteQueueTimeout);
|
|
136
|
-
this.deleteQueueTimeout = setTimeout(()=>{
|
|
137
|
-
if (!this.isQueueClearable()) {
|
|
138
|
-
this.rest.logger.debug(`[Queue] ${this.queueType} ${this.url}. is not clearable. Restarting processing of queue.`);
|
|
139
|
-
this.processPending();
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
this.rest.logger.debug(`[Queue] ${this.queueType} ${this.url}. Deleting`);
|
|
143
|
-
if (this.timeoutId) clearTimeout(this.timeoutId);
|
|
144
|
-
// No requests have been requested for this queue so we nuke this queue
|
|
145
|
-
this.rest.queues.delete(`${this.identifier}${this.url}`);
|
|
146
|
-
this.rest.logger.debug(`[Queue] ${this.queueType} ${this.url}. Deleted! Remaining: (${this.rest.queues.size})`, [
|
|
147
|
-
...this.rest.queues.values()
|
|
148
|
-
].map((queue)=>`${queue.queueType}${queue.url}`));
|
|
149
|
-
}, this.deleteQueueDelay);
|
|
150
|
-
}
|
|
151
|
-
/** Simply checks if the queue is able to be cleared or it has requests pending. */ isQueueClearable() {
|
|
152
|
-
if (this.firstRequest) return false;
|
|
153
|
-
if (this.waiting.length > 0) return false;
|
|
154
|
-
if (this.pending.length > 0) return false;
|
|
155
|
-
if (this.processing) return false;
|
|
156
|
-
if (this.processingPending) return false;
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
get queueType() {
|
|
160
|
-
return this.identifier.slice(0, this.identifier.indexOf(' '));
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9xdWV1ZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBkZWxheSB9IGZyb20gJ0BkaXNjb3JkZW5vL3V0aWxzJ1xuaW1wb3J0IHR5cGUgeyBSZXN0TWFuYWdlciwgU2VuZFJlcXVlc3RPcHRpb25zIH0gZnJvbSAnLi90eXBlcy5qcydcblxuZXhwb3J0IGNsYXNzIFF1ZXVlIHtcbiAgLyoqIFRoZSByZXN0IG1hbmFnZXIgKi9cbiAgcmVzdDogUmVzdE1hbmFnZXJcbiAgLyoqIEFtb3VudCBvZiByZXF1ZXN0cyB0aGF0IGhhdmUgYXJlIHJlbWFpbmluZy4gRGVmYXVsdHMgdG8gMS4gKi9cbiAgcmVtYWluaW5nOiBudW1iZXIgPSAxXG4gIC8qKiBNYXggcmVxdWVzdHMgZm9yIHRoaXMgdGhpcy4gRGVmYXVsdHMgdG8gMS4gKi9cbiAgbWF4OiBudW1iZXIgPSAxXG4gIC8qKiBUaGUgdGltZSB0aGF0IGRpc2NvcmQgYWxsb3dzIHRvIG1ha2UgdGhlIG1heCBudW1iZXIgb2YgcmVxdWVzdHMuIERlZmF1bHRzIHRvIDAgKi9cbiAgaW50ZXJ2YWw6IG51bWJlciA9IDBcbiAgLyoqIHRpbWVyIHRvIHJlc2V0IHRvIDAgKi9cbiAgdGltZW91dElkOiBOb2RlSlMuVGltZW91dCB8IHVuZGVmaW5lZFxuICAvKiogVGhlIHJlcXVlc3RzIHRoYXQgYXJlIGN1cnJlbnRseSBwZW5kaW5nLiAqL1xuICB3YWl0aW5nOiBBcnJheTwodmFsdWU6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPikgPT4gdm9pZD4gPSBbXVxuICAvKiogVGhlIHJlcXVlc3RzIHRoYXQgYXJlIGN1cnJlbnRseSBwZW5kaW5nLiAqL1xuICBwZW5kaW5nOiBTZW5kUmVxdWVzdE9wdGlvbnNbXSA9IFtdXG4gIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgd2FpdGluZyBxdWV1ZSBpcyBhbHJlYWR5IHByb2Nlc3NpbmcuICovXG4gIHByb2Nlc3Npbmc6IGJvb2xlYW4gPSBmYWxzZVxuICAvKiogV2hldGhlciBvciBub3QgdGhlIHBlbmRpbmcgcXVldWUgaXMgYWxyZWFkeSBwcm9jZXNzaW5nLiAqL1xuICBwcm9jZXNzaW5nUGVuZGluZzogYm9vbGVhbiA9IGZhbHNlXG4gIC8qKiBXaGV0aGVyIHRoZSBmaXJzdCByZXF1ZXN0IGlzIHBlbmRpbmcuICovXG4gIGZpcnN0UmVxdWVzdDogYm9vbGVhbiA9IGZhbHNlXG4gIC8qKiBUaGUgdXJsIHRoYXQgYWxsIHRoZSByZXF1ZXN0cyBpbiB0aGlzIHF1ZXVlIGFyZSBzZW50IHRvLiAqL1xuICB1cmw6IHN0cmluZ1xuICAvKiogV2hlbiByZXF1ZXN0cyBzdGFydGVkIGJlaW5nIG1hZGUgdG8gZGV0ZXJtaW5lIHdoZW4gdGhlIGludGVydmFsIHdpbGwgcmVzZXQgaXQuICovXG4gIGZyb3plbkF0OiBudW1iZXIgPSAwXG4gIC8qKiBUaGUgdGltZSBpbiBtaWxsaXNlY29uZHMgdG8gd2FpdCBiZWZvcmUgZGVsZXRpbmcgdGhpcyBxdWV1ZSBpZiBpdCBpcyBlbXB0eS4gRGVmYXVsdHMgdG8gNjAwMDAob25lIG1pbnV0ZSkuICovXG4gIGRlbGV0ZVF1ZXVlRGVsYXk6IG51bWJlciA9IDYwMDAwXG4gIC8qKiBUaGUgdGltZW91dCBmb3IgdGhlIGRlbGV0aW9uIG9mIHRoaXMgcXVldWUgKi9cbiAgZGVsZXRlUXVldWVUaW1lb3V0PzogTm9kZUpTLlRpbWVvdXRcbiAgLyoqXG4gICAqIFRoZSBpZGVudGlmaWVyIGZvciB0aGlzIHJlcXVlc3QsIG1heSBiZSB0aGUgcmVxdWVzdCBhdXRob3JpemF0aW9uIG9yIGZhbGxiYWNrIHRvIHRoZSBib3QgYXV0aFxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBUaGlzIGlzIHVzZWQgdG8gZ2V0IHRoZSBpZGVudGlmeSB0aGlzIHF1ZXVlIGZyb20gdGhlIHF1ZXVlIG1hcHBpbmcgb2YgdGhlIHJlc3QgbWFuYWdlclxuICAgKi9cbiAgaWRlbnRpZmllcjogc3RyaW5nXG5cbiAgY29uc3RydWN0b3IocmVzdDogUmVzdE1hbmFnZXIsIG9wdGlvbnM6IFF1ZXVlT3B0aW9ucykge1xuICAgIHRoaXMucmVzdCA9IHJlc3RcbiAgICB0aGlzLnVybCA9IG9wdGlvbnMudXJsXG4gICAgdGhpcy5pZGVudGlmaWVyID0gb3B0aW9ucy5pZGVudGlmaWVyXG5cbiAgICBpZiAob3B0aW9ucy5pbnRlcnZhbCkgdGhpcy5pbnRlcnZhbCA9IG9wdGlvbnMuaW50ZXJ2YWxcbiAgICBpZiAob3B0aW9ucy5tYXgpIHRoaXMubWF4ID0gb3B0aW9ucy5tYXhcbiAgICBpZiAob3B0aW9ucy5yZW1haW5pbmcpIHRoaXMucmVtYWluaW5nID0gb3B0aW9ucy5yZW1haW5pbmdcbiAgICBpZiAob3B0aW9ucy50aW1lb3V0SWQpIHRoaXMudGltZW91dElkID0gb3B0aW9ucy50aW1lb3V0SWRcbiAgICBpZiAob3B0aW9ucy5kZWxldGVRdWV1ZURlbGF5KSB0aGlzLmRlbGV0ZVF1ZXVlRGVsYXkgPSBvcHRpb25zLmRlbGV0ZVF1ZXVlRGVsYXlcbiAgfVxuXG4gIC8qKiBDaGVjayBpZiB0aGVyZSBpcyBhbnkgcmVtYWluaW5nIHJlcXVlc3RzIHRoYXQgYXJlIGFsbG93ZWQuICovXG4gIGlzUmVxdWVzdEFsbG93ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVtYWluaW5nID4gMFxuICB9XG5cbiAgLyoqIFBhdXNlcyB0aGUgZXhlY3V0aW9uIHVudGlsIGEgcmVxdWVzdCBpcyBhbGxvd2VkIHRvIGJlIG1hZGUuICovXG4gIGFzeW5jIHdhaXRVbnRpbFJlcXVlc3RBdmFpbGFibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIGF3YWl0IG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlKSA9PiB7XG4gICAgICAvLyBJZiB3aGF0ZXZlciBhbW91bnQgb2YgcmVxdWVzdHMgaXMgbGVmdCBpcyBtb3JlIHRoYW4gdGhlIHNhZmV0eSBtYXJnaW4sIGFsbG93IHRoZSByZXF1ZXN0XG4gICAgICBpZiAodGhpcy5pc1JlcXVlc3RBbGxvd2VkKCkpIHtcbiAgICAgICAgLy8gdGhpcy5yZW1haW5pbmcrKztcbiAgICAgICAgcmVzb2x2ZSgpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLndhaXRpbmcucHVzaChyZXNvbHZlKVxuICAgICAgICBhd2FpdCB0aGlzLnByb2Nlc3NXYWl0aW5nKClcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqIFByb2Nlc3MgdGhlIHF1ZXVlIG9mIHJlcXVlc3RzIHdhaXRpbmcgdG8gYmUgaGFuZGxlZC4gKi9cbiAgYXN5bmMgcHJvY2Vzc1dhaXRpbmcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gSWYgYWxyZWFkeSBwcm9jZXNzaW5nLCB0aGF0IGxvb3Agd2lsbCBoYW5kbGUgYWxsIHdhaXRpbmcgcmVxdWVzdHMuXG4gICAgaWYgKHRoaXMucHJvY2Vzc2luZykgcmV0dXJuXG4gICAgLy8gTWFyayBhcyBwcm9jZXNzaW5nIHNvIG90aGVyIGxvb3BzIGRvbid0IHN0YXJ0XG4gICAgdGhpcy5wcm9jZXNzaW5nID0gdHJ1ZVxuXG4gICAgd2hpbGUgKHRoaXMud2FpdGluZy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnJlc3QubG9nZ2VyLmRlYnVnKGBbUXVldWVdICR7dGhpcy5xdWV1ZVR5cGV9ICR7dGhpcy51cmx9IHByb2Nlc3Mgd2FpdGluZyB3aGlsZSBsb29wIHJhbi5gKVxuICAgICAgaWYgKHRoaXMuaXNSZXF1ZXN0QWxsb3dlZCgpKSB7XG4gICAgICAgIC8vIFJlc29sdmUgdGhlIG5leHQgaXRlbSBpbiB0aGUgcXVldWVcbiAgICAgICAgdGhpcy53YWl0aW5nLnNoaWZ0KCk/LigpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBkZWxheSgxMDAwKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE1hcmsgYXMgZmFsc2Ugc28gbmV4dCBwZW5kaW5nIHJlcXVlc3QgY2FuIGJlIHRyaWdnZXJlZCBieSBuZXcgbG9vcC5cbiAgICB0aGlzLnByb2Nlc3NpbmcgPSBmYWxzZVxuICB9XG5cbiAgLyoqIFByb2Nlc3MgdGhlIHF1ZXVlIG9mIGFsbCByZXF1ZXN0cyBwZW5kaW5nIHRvIGJlIHNlbnQuICovXG4gIGFzeW5jIHByb2Nlc3NQZW5kaW5nKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIElmIGFscmVhZHkgcHJvY2Vzc2luZywgdGhhdCBsb29wIHdpbGwgaGFuZGxlIGFsbCBwZW5kaW5nIHJlcXVlc3RzLlxuICAgIGlmICh0aGlzLnByb2Nlc3NpbmdQZW5kaW5nIHx8ICF0aGlzLnBlbmRpbmcubGVuZ3RoKSByZXR1cm5cblxuICAgIC8vIE1hcmsgYXMgcHJvY2Vzc2luZyBzbyBvdGhlciBsb29wcyBkb24ndCBzdGFydFxuICAgIHRoaXMucHJvY2Vzc2luZ1BlbmRpbmcgPSB0cnVlXG5cbiAgICB3aGlsZSAodGhpcy5wZW5kaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucmVzdC5sb2dnZXIuZGVidWcoYFF1ZXVlICR7dGhpcy5xdWV1ZVR5cGV9ICR7dGhpcy51cmx9IHByb2Nlc3MgcGVuZGluZyB3aGlsZSBsb29wIHJhbiB3aXRoICR7dGhpcy5wZW5kaW5nLmxlbmd0aH0uYClcbiAgICAgIGlmICghdGhpcy5maXJzdFJlcXVlc3QgJiYgIXRoaXMuaXNSZXF1ZXN0QWxsb3dlZCgpKSB7XG4gICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KClcbiAgICAgICAgY29uc3QgZnV0dXJlID0gdGhpcy5mcm96ZW5BdCArIHRoaXMuaW50ZXJ2YWxcbiAgICAgICAgYXdhaXQgZGVsYXkoZnV0dXJlID4gbm93ID8gZnV0dXJlIC0gbm93IDogMTAwMClcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVxdWVzdCA9IHRoaXMucGVuZGluZ1swXVxuICAgICAgaWYgKHJlcXVlc3QpIHtcbiAgICAgICAgY29uc3QgYmFzaWNVUkwgPSB0aGlzLnJlc3Quc2ltcGxpZnlVcmwocmVxdWVzdC5yb3V0ZSwgcmVxdWVzdC5tZXRob2QpXG5cbiAgICAgICAgLy8gSWYgdGhpcyB1cmwgaXMgc3RpbGwgcmF0ZSBsaW1pdGVkLCB0cnkgYWdhaW5cbiAgICAgICAgY29uc3QgdXJsUmVzZXRJbiA9IHRoaXMucmVzdC5jaGVja1JhdGVMaW1pdHMoYmFzaWNVUkwsIHRoaXMuaWRlbnRpZmllcilcbiAgICAgICAgaWYgKHVybFJlc2V0SW4pIGF3YWl0IGRlbGF5KHVybFJlc2V0SW4pXG5cbiAgICAgICAgLy8gSUYgQSBCVUNLRVQgRVhJU1RTLCBDSEVDSyBUSEUgQlVDS0VUJ1MgUkFURSBMSU1JVFNcbiAgICAgICAgY29uc3QgYnVja2V0UmVzZXRJbiA9IHJlcXVlc3QuYnVja2V0SWQgPyB0aGlzLnJlc3QuY2hlY2tSYXRlTGltaXRzKHJlcXVlc3QuYnVja2V0SWQsIHRoaXMuaWRlbnRpZmllcikgOiBmYWxzZVxuICAgICAgICBpZiAoYnVja2V0UmVzZXRJbikgYXdhaXQgZGVsYXkoYnVja2V0UmVzZXRJbilcblxuICAgICAgICB0aGlzLmZpcnN0UmVxdWVzdCA9IGZhbHNlXG4gICAgICAgIHRoaXMucmVtYWluaW5nLS1cblxuICAgICAgICBpZiAodGhpcy5yZW1haW5pbmcgPT09IDAgJiYgdGhpcy5pbnRlcnZhbCAhPT0gMCkge1xuICAgICAgICAgIHRoaXMudGltZW91dElkID8/PSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtYWluaW5nID0gdGhpcy5tYXhcbiAgICAgICAgICAgIHRoaXMudGltZW91dElkID0gdW5kZWZpbmVkXG4gICAgICAgICAgfSwgdGhpcy5pbnRlcnZhbClcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbW92ZSBmcm9tIHF1ZXVlLCB3ZSBhcmUgZXhlY3V0aW5nIGl0LlxuICAgICAgICB0aGlzLnBlbmRpbmcuc2hpZnQoKVxuICAgICAgICAvLyBDaGVjayBpZiB0aGlzIHJlcXVlc3QgaXMgYWJsZSB0byBiZSBtYWRlIGdsb2JhbGx5XG4gICAgICAgIGF3YWl0IHRoaXMucmVzdC5pbnZhbGlkQnVja2V0LndhaXRVbnRpbFJlcXVlc3RBdmFpbGFibGUoKVxuXG4gICAgICAgIGF3YWl0IHRoaXMucmVzdFxuICAgICAgICAgIC5zZW5kUmVxdWVzdChyZXF1ZXN0KVxuICAgICAgICAgIC8vIFNob3VsZCBiZSBoYW5kbGVkIGluIHNlbmRSZXF1ZXN0LCB0aGlzIGNhdGNoIGp1c3QgcHJldmVudHMgYm90cyBmcm9tIGR5aW5nXG4gICAgICAgICAgLmNhdGNoKCgpID0+IG51bGwpXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5yZXN0LmxvZ2dlci5kZWJ1ZyhgUXVldWUgJHt0aGlzLnF1ZXVlVHlwZX0gJHt0aGlzLnVybH0gcHJvY2VzcyBwZW5kaW5nIHdoaWxlIGxvb3AgZXhpdGVkIHdpdGggJHt0aGlzLnBlbmRpbmcubGVuZ3RofS5gKVxuXG4gICAgLy8gTWFyayBhcyBmYWxzZSBzbyBuZXh0IHBlbmRpbmcgcmVxdWVzdCBjYW4gYmUgdHJpZ2dlcmVkIGJ5IG5ldyBsb29wLlxuICAgIHRoaXMucHJvY2Vzc2luZ1BlbmRpbmcgPSBmYWxzZVxuICAgIHRoaXMuY2xlYW51cCgpXG4gIH1cblxuICBoYW5kbGVDb21wbGV0ZWRSZXF1ZXN0KGhlYWRlcnM6IHsgbWF4PzogbnVtYmVyOyBpbnRlcnZhbD86IG51bWJlcjsgcmVtYWluaW5nPzogbnVtYmVyIH0pOiB2b2lkIHtcbiAgICBpZiAoaGVhZGVycy5tYXggPT09IDApIHtcbiAgICAgIHRoaXMucmVtYWluaW5nKytcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICghdGhpcy5mcm96ZW5BdCkgdGhpcy5mcm96ZW5BdCA9IERhdGUubm93KClcbiAgICBpZiAoaGVhZGVycy5pbnRlcnZhbCAhPT0gdW5kZWZpbmVkKSB0aGlzLmludGVydmFsID0gaGVhZGVycy5pbnRlcnZhbFxuICAgIGlmIChoZWFkZXJzLnJlbWFpbmluZyAhPT0gdW5kZWZpbmVkKSB0aGlzLnJlbWFpbmluZyA9IGhlYWRlcnMucmVtYWluaW5nXG5cbiAgICBpZiAodGhpcy5yZW1haW5pbmcgPD0gMSkge1xuICAgICAgdGhpcy50aW1lb3V0SWQgPz89IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnJlbWFpbmluZyA9IHRoaXMubWF4XG4gICAgICAgIHRoaXMudGltZW91dElkID0gdW5kZWZpbmVkXG4gICAgICB9LCBoZWFkZXJzLmludGVydmFsKVxuICAgIH1cbiAgfVxuXG4gIC8qKiBDaGVja3MgaWYgYSByZXF1ZXN0IGlzIGF2YWlsYWJsZSBhbmQgYWRkcyBpdCB0byB0aGUgcXVldWUuIEFsc28gdHJpZ2dlcnMgcXVldWUgcHJvY2Vzc2luZyBpZiBub3QgYWxyZWFkeSBwcm9jZXNzaW5nLiAqL1xuICBhc3luYyBtYWtlUmVxdWVzdChvcHRpb25zOiBTZW5kUmVxdWVzdE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLndhaXRVbnRpbFJlcXVlc3RBdmFpbGFibGUoKVxuICAgIHRoaXMucGVuZGluZy5wdXNoKG9wdGlvbnMpXG4gICAgdGhpcy5wcm9jZXNzUGVuZGluZygpXG4gIH1cblxuICAvKiogQ2xlYW5zIHVwIHRoZSBxdWV1ZSBieSBjaGVja2luZyBpZiB0aGVyZSBpcyBub3RoaW5nIGxlZnQgYW5kIHJlbW92aW5nIGl0LiAqL1xuICBjbGVhbnVwKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc1F1ZXVlQ2xlYXJhYmxlKCkpIHtcbiAgICAgIHRoaXMucHJvY2Vzc1BlbmRpbmcoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdGhpcy5yZXN0LmxvZ2dlci5kZWJ1ZyhgW1F1ZXVlXSAke3RoaXMucXVldWVUeXBlfSAke3RoaXMudXJsfS4gRGVsYXlpbmcgZGVsZXRlIGZvciAke3RoaXMuZGVsZXRlUXVldWVEZWxheX1tc2ApXG5cbiAgICAvLyBEZWxldGUgaW4gYSBtaW51dGUgZ2l2aW5nIGEgYml0IG9mIHRpbWUgdG8gYWxsb3cgbmV3IHJlcXVlc3RzIHRoYXQgbWF5IHJldXNlIHRoaXMgcXVldWVcbiAgICBjbGVhclRpbWVvdXQodGhpcy5kZWxldGVRdWV1ZVRpbWVvdXQpXG4gICAgdGhpcy5kZWxldGVRdWV1ZVRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmICghdGhpcy5pc1F1ZXVlQ2xlYXJhYmxlKCkpIHtcbiAgICAgICAgdGhpcy5yZXN0LmxvZ2dlci5kZWJ1ZyhgW1F1ZXVlXSAke3RoaXMucXVldWVUeXBlfSAke3RoaXMudXJsfS4gaXMgbm90IGNsZWFyYWJsZS4gUmVzdGFydGluZyBwcm9jZXNzaW5nIG9mIHF1ZXVlLmApXG4gICAgICAgIHRoaXMucHJvY2Vzc1BlbmRpbmcoKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgdGhpcy5yZXN0LmxvZ2dlci5kZWJ1ZyhgW1F1ZXVlXSAke3RoaXMucXVldWVUeXBlfSAke3RoaXMudXJsfS4gRGVsZXRpbmdgKVxuXG4gICAgICBpZiAodGhpcy50aW1lb3V0SWQpIGNsZWFyVGltZW91dCh0aGlzLnRpbWVvdXRJZClcblxuICAgICAgLy8gTm8gcmVxdWVzdHMgaGF2ZSBiZWVuIHJlcXVlc3RlZCBmb3IgdGhpcyBxdWV1ZSBzbyB3ZSBudWtlIHRoaXMgcXVldWVcbiAgICAgIHRoaXMucmVzdC5xdWV1ZXMuZGVsZXRlKGAke3RoaXMuaWRlbnRpZmllcn0ke3RoaXMudXJsfWApXG4gICAgICB0aGlzLnJlc3QubG9nZ2VyLmRlYnVnKFxuICAgICAgICBgW1F1ZXVlXSAke3RoaXMucXVldWVUeXBlfSAke3RoaXMudXJsfS4gRGVsZXRlZCEgUmVtYWluaW5nOiAoJHt0aGlzLnJlc3QucXVldWVzLnNpemV9KWAsXG4gICAgICAgIFsuLi50aGlzLnJlc3QucXVldWVzLnZhbHVlcygpXS5tYXAoKHF1ZXVlKSA9PiBgJHtxdWV1ZS5xdWV1ZVR5cGV9JHtxdWV1ZS51cmx9YCksXG4gICAgICApXG4gICAgfSwgdGhpcy5kZWxldGVRdWV1ZURlbGF5KVxuICB9XG5cbiAgLyoqIFNpbXBseSBjaGVja3MgaWYgdGhlIHF1ZXVlIGlzIGFibGUgdG8gYmUgY2xlYXJlZCBvciBpdCBoYXMgcmVxdWVzdHMgcGVuZGluZy4gKi9cbiAgaXNRdWV1ZUNsZWFyYWJsZSgpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5maXJzdFJlcXVlc3QpIHJldHVybiBmYWxzZVxuICAgIGlmICh0aGlzLndhaXRpbmcubGVuZ3RoID4gMCkgcmV0dXJuIGZhbHNlXG4gICAgaWYgKHRoaXMucGVuZGluZy5sZW5ndGggPiAwKSByZXR1cm4gZmFsc2VcbiAgICBpZiAodGhpcy5wcm9jZXNzaW5nKSByZXR1cm4gZmFsc2VcbiAgICBpZiAodGhpcy5wcm9jZXNzaW5nUGVuZGluZykgcmV0dXJuIGZhbHNlXG5cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgZ2V0IHF1ZXVlVHlwZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmlkZW50aWZpZXIuc2xpY2UoMCwgdGhpcy5pZGVudGlmaWVyLmluZGV4T2YoJyAnKSlcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXVlT3B0aW9ucyB7XG4gIC8qKiBIb3cgbWFueSByZXF1ZXN0cyBhcmUgcmVtYWluaW5nLiBEZWZhdWx0cyB0byAxICovXG4gIHJlbWFpbmluZz86IG51bWJlclxuICAvKiogTWF4IG51bWJlciBvZiByZXF1ZXN0cyBhbGxvd2VkIGluIHRoaXMgdGhpcy4gRGVmYXVsdHMgdG8gMS4gKi9cbiAgbWF4PzogbnVtYmVyXG4gIC8qKiBUaGUgdGltZSBpbiBtaWxsaXNlY29uZHMgdGhhdCBkaXNjb3JkIGFsbG93cyB0byBtYWtlIHRoZSBtYXggbnVtYmVyIG9mIGludmFsaWQgcmVxdWVzdHMuIERlZmF1bHRzIHRvIDAgKi9cbiAgaW50ZXJ2YWw/OiBudW1iZXJcbiAgLyoqIHRpbWVyIHRvIHJlc2V0IHRvIDAgKi9cbiAgdGltZW91dElkPzogTm9kZUpTLlRpbWVvdXRcbiAgLyoqIFRoZSB1cmwgdGhpcyBxdWV1ZSB3aWxsIGJlIGhhbmRsaW5nLiAqL1xuICB1cmw6IHN0cmluZ1xuICAvKiogVGhlIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRvIHdhaXQgYmVmb3JlIGRlbGV0aW5nIHRoaXMgcXVldWUgaWYgaXQgaXMgZW1wdHkuIERlZmF1bHRzIHRvIDYwMDAwKG9uZSBtaW51dGUpLiAqL1xuICBkZWxldGVRdWV1ZURlbGF5PzogbnVtYmVyXG4gIC8qKiBUaGUgYmFzZSBrZXkgdGhhdCBpZGVudGlmaWVzIHRoaXMgcXVldWUgaW4gdGhlIHJlc3QgbWFuYWdlciAqL1xuICBpZGVudGlmaWVyOiBzdHJpbmdcbn1cbiJdLCJuYW1lcyI6WyJRdWV1ZSIsInJlc3QiLCJvcHRpb25zIiwicmVtYWluaW5nIiwibWF4IiwiaW50ZXJ2YWwiLCJ3YWl0aW5nIiwicGVuZGluZyIsInByb2Nlc3NpbmciLCJwcm9jZXNzaW5nUGVuZGluZyIsImZpcnN0UmVxdWVzdCIsImZyb3plbkF0IiwiZGVsZXRlUXVldWVEZWxheSIsInVybCIsImlkZW50aWZpZXIiLCJ0aW1lb3V0SWQiLCJpc1JlcXVlc3RBbGxvd2VkIiwid2FpdFVudGlsUmVxdWVzdEF2YWlsYWJsZSIsIlByb21pc2UiLCJyZXNvbHZlIiwicHVzaCIsInByb2Nlc3NXYWl0aW5nIiwibGVuZ3RoIiwibG9nZ2VyIiwiZGVidWciLCJxdWV1ZVR5cGUiLCJzaGlmdCIsImRlbGF5IiwicHJvY2Vzc1BlbmRpbmciLCJub3ciLCJEYXRlIiwiZnV0dXJlIiwicmVxdWVzdCIsImJhc2ljVVJMIiwic2ltcGxpZnlVcmwiLCJyb3V0ZSIsIm1ldGhvZCIsInVybFJlc2V0SW4iLCJjaGVja1JhdGVMaW1pdHMiLCJidWNrZXRSZXNldEluIiwiYnVja2V0SWQiLCJzZXRUaW1lb3V0IiwidW5kZWZpbmVkIiwiaW52YWxpZEJ1Y2tldCIsInNlbmRSZXF1ZXN0IiwiY2F0Y2giLCJjbGVhbnVwIiwiaGFuZGxlQ29tcGxldGVkUmVxdWVzdCIsImhlYWRlcnMiLCJtYWtlUmVxdWVzdCIsImlzUXVldWVDbGVhcmFibGUiLCJjbGVhclRpbWVvdXQiLCJkZWxldGVRdWV1ZVRpbWVvdXQiLCJxdWV1ZXMiLCJkZWxldGUiLCJzaXplIiwidmFsdWVzIiwibWFw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
|