-
Notifications
You must be signed in to change notification settings - Fork 927
/
readytracker.go
126 lines (97 loc) · 3.14 KB
/
readytracker.go
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package bot
import (
"sync"
"github.com/botlabs-gg/yagpdb/v2/bot/eventsystem"
)
// ReadyTracker tracks process shards and initial readies/resumes, aswell as sending out events
var ReadyTracker = &readyTracker{}
type readyTracker struct {
receivedReadyOrResume []bool
allProcessShards []bool
totalShardCount int
mu sync.RWMutex
}
func (r *readyTracker) initTotalShardCount(count int) {
r.mu.Lock()
defer r.mu.Unlock()
r.totalShardCount = count
r.receivedReadyOrResume = make([]bool, count)
r.allProcessShards = make([]bool, count)
}
func (r *readyTracker) shardsAdded(shardIDs ...int) {
r.mu.Lock()
defer r.mu.Unlock()
for _, v := range shardIDs {
r.allProcessShards[v] = true
}
go eventsystem.QueueEventNonDiscord(eventsystem.NewEventData(nil, eventsystem.EventYagShardsAdded, shardIDs))
}
func (r *readyTracker) handleReadyOrResume(evt *eventsystem.EventData) {
s := evt.Session
r.mu.Lock()
defer r.mu.Unlock()
alreadyReady := r.receivedReadyOrResume[s.ShardID]
if alreadyReady {
return
}
r.receivedReadyOrResume[s.ShardID] = true
go eventsystem.QueueEventNonDiscord(eventsystem.NewEventData(evt.Session, eventsystem.EventYagShardReady, s.ShardID))
}
func (r *readyTracker) shardRemoved(shardID int) {
r.mu.Lock()
defer r.mu.Unlock()
r.receivedReadyOrResume[shardID] = false
r.allProcessShards[shardID] = false
go eventsystem.QueueEventNonDiscord(eventsystem.NewEventData(nil, eventsystem.EventYagShardRemoved, shardID))
}
// IsShardOnProcess returns true if the provided shard is on this process
func (r *readyTracker) IsShardOnProcess(shardID int) bool {
r.mu.RLock()
defer r.mu.RUnlock()
if r.totalShardCount <= shardID {
return false
}
return r.allProcessShards[shardID]
}
// IsShardReady returns true if the provided shard is ready
func (r *readyTracker) IsShardReady(shardID int) bool {
r.mu.RLock()
defer r.mu.RUnlock()
if r.totalShardCount <= shardID {
return false
}
return r.receivedReadyOrResume[shardID]
}
func (r *readyTracker) GetProcessShards() []int {
r.mu.RLock()
defer r.mu.RUnlock()
shards := make([]int, 0, totalShardCount)
for s, active := range r.allProcessShards {
if active {
shards = append(shards, s)
}
}
return shards
}
// IsGuildOnProcess returns true if the provided guild is on this process
func (r *readyTracker) IsGuildOnProcess(guildID int64) bool {
r.mu.RLock()
defer r.mu.RUnlock()
if r.totalShardCount == 0 {
return false
}
shardID := GuildShardID(int64(r.totalShardCount), guildID)
return r.allProcessShards[shardID]
}
// IsGuildShardReady returns true if the shard for the specified guild is ready
// note: it does not make sure that the guild create has been received for this guild
// it may still be unavailable in the state, but the shard has received a ready or resum
func (r *readyTracker) IsGuildShardReady(guildID int64) bool {
r.mu.RLock()
defer r.mu.RUnlock()
if r.totalShardCount == 0 {
return false
}
shardID := GuildShardID(int64(r.totalShardCount), guildID)
return r.receivedReadyOrResume[shardID]
}