This repository has been archived by the owner on Mar 31, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBucket.js
79 lines (54 loc) · 1.6 KB
/
Bucket.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
const wait = (t) => new Promise(resolve => setTimeout(resolve, t))
class Bucket {
constructor (id, manager) {
this.id = id
this.manager = manager
this.working = false
this.queue = []
this.remaining = -1
this.reset = -1
}
_resetTimer () {
this.manager.buckets._resetTimer(this.id)
}
add (req) {
this.queue.push(req)
this.run()
}
async run (next) {
if (!next && this.working) return
const req = this.queue.shift()
if (!req) {
this.working = false
return
}
this.working = true
this._resetTimer()
if (this.manager.global) {
await this.manager.global
} else if (this.remaining <= 0 && Date.now() < this.reset) {
await wait(this.reset + 500 - Date.now())
}
const { res, json } = await this.manager.request(req)
const date = new Date(res.headers.get('Date'))
const retryAfter = Number(res.headers.get('Retry-After'))
const remaining = res.headers.get('X-RateLimit-Remaining')
const reset = Number(res.headers.get('X-RateLimit-Reset'))
this.remaining = remaining ? Number(remaining) : 1
this.reset = reset ? (new Date(reset * 1000).getTime() - (date.getTime() - Date.now())) : Date.now()
const global = Boolean(res.headers.get('X-RateLimit-Global'))
if (global) {
this.manager.global = wait(retryAfter)
await this.manager.global
this.manager.global = null
}
if (res.status === 429) {
this.queue.unshift(req)
await wait(retryAfter)
} else {
req.resolve(json)
}
this.run(true) // run next item
}
}
module.exports = Bucket