subscribeToStream registers a subscriber to the per-chat in-memory stream and returns a snapshot of currently in-progress message_part events plus the current retry phase, the live subscriber channel, and a cancel func. Parts that were claimed by a committed durable assistant message (committedMess
(chatID uuid.UUID)
| 4666 | // so re-delivering their constituent parts here would render the |
| 4667 | // same content twice. |
| 4668 | func (p *Server) subscribeToStream(chatID uuid.UUID) ( |
| 4669 | []codersdk.ChatStreamEvent, |
| 4670 | *codersdk.ChatStreamRetry, |
| 4671 | <-chan codersdk.ChatStreamEvent, |
| 4672 | func(), |
| 4673 | ) { |
| 4674 | state := p.getOrCreateStreamState(chatID) |
| 4675 | state.mu.Lock() |
| 4676 | snapshot := snapshotBufferLocked(state.buffer) |
| 4677 | var currentRetry *codersdk.ChatStreamRetry |
| 4678 | if state.currentRetry != nil { |
| 4679 | retryCopy := *state.currentRetry |
| 4680 | currentRetry = &retryCopy |
| 4681 | } |
| 4682 | id := uuid.New() |
| 4683 | ch := make(chan codersdk.ChatStreamEvent, 128) |
| 4684 | state.subscribers[id] = ch |
| 4685 | state.mu.Unlock() |
| 4686 | |
| 4687 | cancel := func() { |
| 4688 | state.mu.Lock() |
| 4689 | // Remove the subscriber but do not close the channel. |
| 4690 | // publishToStream copies subscriber references under |
| 4691 | // the per-chat lock then sends outside; closing here |
| 4692 | // races with that send and can panic. The channel |
| 4693 | // becomes unreachable once removed and will be GC'd. |
| 4694 | delete(state.subscribers, id) |
| 4695 | p.cleanupStreamIfIdle(chatID, state) |
| 4696 | state.mu.Unlock() |
| 4697 | } |
| 4698 | |
| 4699 | return snapshot, currentRetry, ch, cancel |
| 4700 | } |
| 4701 | |
| 4702 | // getOrCreateStreamState returns the per-chat stream state, |
| 4703 | // creating one atomically if it doesn't exist. The returned |