|
53 | 53 |
|
54 | 54 | localWorkers sync.Map // workers created by this node |
55 | 55 | workerStreams sync.Map // worker streams indexed by ID |
| 56 | + workerAckStreams sync.Map // streams for worker acks indexed by ID |
56 | 57 | pendingJobChannels sync.Map // channels used to send DispatchJob results, nil if event is requeued |
57 | 58 | pendingEvents sync.Map // pending events indexed by sender and event IDs |
58 | 59 |
|
@@ -218,6 +219,7 @@ func AddNode(ctx context.Context, poolName string, rdb *redis.Client, opts ...No |
218 | 219 | shutdownMap: wsm, |
219 | 220 | tickerMap: tm, |
220 | 221 | workerStreams: sync.Map{}, |
| 222 | + workerAckStreams: sync.Map{}, |
221 | 223 | pendingJobChannels: sync.Map{}, |
222 | 224 | pendingEvents: sync.Map{}, |
223 | 225 | poolStream: poolStream, |
@@ -682,7 +684,7 @@ func (node *Node) ackWorkerEvent(ctx context.Context, ev *streaming.Event) { |
682 | 684 | // dispatched the job. |
683 | 685 | if pending.EventName == evStartJob { |
684 | 686 | _, nodeID := unmarshalJobKeyAndNodeID(pending.Payload) |
685 | | - stream, err := streaming.NewStream(nodeStreamName(node.PoolName, nodeID), node.rdb, soptions.WithStreamLogger(node.logger)) |
| 687 | + stream, err := node.getOrCreateWorkerAckStream(ctx, nodeID) |
686 | 688 | if err != nil { |
687 | 689 | node.logger.Error(fmt.Errorf("ackWorkerEvent: failed to create node event stream %q: %w", nodeStreamName(node.PoolName, nodeID), err)) |
688 | 690 | return |
@@ -1111,6 +1113,29 @@ func (node *Node) workerStream(_ context.Context, id string) (*streaming.Stream, |
1111 | 1113 | return val.(*streaming.Stream), nil |
1112 | 1114 | } |
1113 | 1115 |
|
| 1116 | +// getOrCreateWorkerAckStream gets or creates a stream for worker acks |
| 1117 | +func (node *Node) getOrCreateWorkerAckStream(ctx context.Context, nodeID string) (*streaming.Stream, error) { |
| 1118 | + if val, ok := node.workerAckStreams.Load(nodeID); ok { |
| 1119 | + return val.(*streaming.Stream), nil |
| 1120 | + } |
| 1121 | + |
| 1122 | + stream, err := streaming.NewStream( |
| 1123 | + nodeStreamName(node.PoolName, nodeID), |
| 1124 | + node.rdb, |
| 1125 | + soptions.WithStreamLogger(node.logger), |
| 1126 | + ) |
| 1127 | + if err != nil { |
| 1128 | + return nil, err |
| 1129 | + } |
| 1130 | + |
| 1131 | + actual, loaded := node.workerAckStreams.LoadOrStore(nodeID, stream) |
| 1132 | + if loaded { |
| 1133 | + // Another goroutine created the stream first, just discard our local reference |
| 1134 | + return actual.(*streaming.Stream), nil |
| 1135 | + } |
| 1136 | + return stream, nil |
| 1137 | +} |
| 1138 | + |
1114 | 1139 | // cleanup removes the worker from all pool maps. |
1115 | 1140 | func (node *Node) cleanupWorker(ctx context.Context, id string) { |
1116 | 1141 | if _, err := node.workerMap.Delete(ctx, id); err != nil { |
|
0 commit comments