···
130
-
// stop all subscribers first
131
-
for _, sub := range j.subscribers {
132
-
if sub.running && sub.cancel != nil {
134
-
sub.running = false
// calculate how many subscribers we need
totalDids := len(j.cfg.WantedDids)
subscribersNeeded := (totalDids + j.maxDidsPerSubscriber - 1) / j.maxDidsPerSubscriber // ceiling division
142
-
// create or reuse subscribers as needed
143
-
j.subscribers = j.subscribers[:0]
134
+
// first case: no subscribers yet; create all needed subscribers
135
+
if len(j.subscribers) == 0 {
136
+
for i := range subscribersNeeded {
137
+
startIdx := i * j.maxDidsPerSubscriber
138
+
endIdx := min((i+1)*j.maxDidsPerSubscriber, totalDids)
145
-
for i := range subscribersNeeded {
140
+
subscriberDids := j.cfg.WantedDids[startIdx:endIdx]
143
+
subCfg.WantedDids = subscriberDids
145
+
ident := fmt.Sprintf("%s-%d", j.baseIdent, i)
146
+
subscriber := &JetstreamSubscriber{
147
+
dids: subscriberDids,
150
+
j.subscribers = append(j.subscribers, subscriber)
152
+
j.subscriberWg.Add(1)
153
+
go j.startSubscriber(subscriber, &subCfg)
158
+
// second case: we have more subscribers than needed, stop extra subscribers
159
+
if len(j.subscribers) > subscribersNeeded {
160
+
for i := subscribersNeeded; i < len(j.subscribers); i++ {
161
+
sub := j.subscribers[i]
162
+
if sub.running && sub.cancel != nil {
164
+
sub.running = false
167
+
j.subscribers = j.subscribers[:subscribersNeeded]
170
+
// third case: we need more subscribers
171
+
if len(j.subscribers) < subscribersNeeded {
172
+
existingCount := len(j.subscribers)
173
+
// Create additional subscribers
174
+
for i := existingCount; i < subscribersNeeded; i++ {
175
+
startIdx := i * j.maxDidsPerSubscriber
176
+
endIdx := min((i+1)*j.maxDidsPerSubscriber, totalDids)
178
+
subscriberDids := j.cfg.WantedDids[startIdx:endIdx]
181
+
subCfg.WantedDids = subscriberDids
183
+
ident := fmt.Sprintf("%s-%d", j.baseIdent, i)
184
+
subscriber := &JetstreamSubscriber{
185
+
dids: subscriberDids,
188
+
j.subscribers = append(j.subscribers, subscriber)
190
+
j.subscriberWg.Add(1)
191
+
go j.startSubscriber(subscriber, &subCfg)
195
+
// fourth case: update existing subscribers with new wantedDids
196
+
for i := 0; i < subscribersNeeded && i < len(j.subscribers); i++ {
startIdx := i * j.maxDidsPerSubscriber
endIdx := min((i+1)*j.maxDidsPerSubscriber, totalDids)
199
+
newDids := j.cfg.WantedDids[startIdx:endIdx]
149
-
subscriberDids := j.cfg.WantedDids[startIdx:endIdx]
201
+
// if the dids for this subscriber have changed, restart it
202
+
sub := j.subscribers[i]
203
+
if !didSlicesEqual(sub.dids, newDids) {
204
+
j.l.Info("subscriber DIDs changed, updating",
205
+
"subscriber", sub.ident,
206
+
"old_count", len(sub.dids),
207
+
"new_count", len(newDids))
152
-
subCfg.WantedDids = subscriberDids
209
+
if sub.running && sub.cancel != nil {
211
+
sub.running = false
154
-
ident := fmt.Sprintf("%s-%d", j.baseIdent, i)
155
-
subscriber := &JetstreamSubscriber{
156
-
dids: subscriberDids,
215
+
subCfg.WantedDids = newDids
219
+
j.subscriberWg.Add(1)
220
+
go j.startSubscriber(sub, &subCfg)
159
-
j.subscribers = append(j.subscribers, subscriber)
161
-
j.subscriberWg.Add(1)
162
-
go j.startSubscriber(subscriber, &subCfg)
225
+
func didSlicesEqual(a, b []string) bool {
226
+
if len(a) != len(b) {
230
+
aMap := make(map[string]struct{}, len(a))
231
+
for _, did := range a {
232
+
aMap[did] = struct{}{}
235
+
for _, did := range b {
236
+
if _, exists := aMap[did]; !exists {
// startSubscriber initializes and starts a single subscriber