StreamChat streams chat updates in real time. The returned channel includes initial snapshot events first, followed by live updates. Callers must close the returned io.Closer to release the websocket connection when done.
(ctx context.Context, chatID uuid.UUID, opts *StreamChatOptions)
| 2831 | // live updates. Callers must close the returned io.Closer to release the |
| 2832 | // websocket connection when done. |
| 2833 | func (c *ExperimentalClient) StreamChat(ctx context.Context, chatID uuid.UUID, opts *StreamChatOptions) (<-chan ChatStreamEvent, io.Closer, error) { |
| 2834 | path := fmt.Sprintf("/api/experimental/chats/%s/stream", chatID) |
| 2835 | if opts != nil && opts.AfterID != nil { |
| 2836 | path += fmt.Sprintf("?after_id=%d", *opts.AfterID) |
| 2837 | } |
| 2838 | |
| 2839 | conn, err := c.Dial( |
| 2840 | ctx, |
| 2841 | path, |
| 2842 | &websocket.DialOptions{CompressionMode: websocket.CompressionDisabled}, |
| 2843 | ) |
| 2844 | if err != nil { |
| 2845 | return nil, nil, err |
| 2846 | } |
| 2847 | conn.SetReadLimit(1 << 22) // 4MiB |
| 2848 | |
| 2849 | streamCtx, streamCancel := context.WithCancel(ctx) |
| 2850 | events := make(chan ChatStreamEvent, 128) |
| 2851 | |
| 2852 | send := func(event ChatStreamEvent) bool { |
| 2853 | if event.ChatID == uuid.Nil { |
| 2854 | event.ChatID = chatID |
| 2855 | } |
| 2856 | select { |
| 2857 | case <-streamCtx.Done(): |
| 2858 | return false |
| 2859 | case events <- event: |
| 2860 | return true |
| 2861 | } |
| 2862 | } |
| 2863 | |
| 2864 | go func() { |
| 2865 | defer close(events) |
| 2866 | defer streamCancel() |
| 2867 | defer func() { |
| 2868 | _ = conn.Close(websocket.StatusNormalClosure, "") |
| 2869 | }() |
| 2870 | |
| 2871 | for { |
| 2872 | var batch []ChatStreamEvent |
| 2873 | if err := wsjson.Read(streamCtx, conn, &batch); err != nil { |
| 2874 | if streamCtx.Err() != nil { |
| 2875 | return |
| 2876 | } |
| 2877 | switch websocket.CloseStatus(err) { |
| 2878 | case websocket.StatusNormalClosure, websocket.StatusGoingAway: |
| 2879 | return |
| 2880 | } |
| 2881 | _ = send(ChatStreamEvent{ |
| 2882 | Type: ChatStreamEventTypeError, |
| 2883 | Error: &ChatError{ |
| 2884 | Message: fmt.Sprintf("read chat stream: %v", err), |
| 2885 | }, |
| 2886 | }) |
| 2887 | return |
| 2888 | } |
| 2889 | |
| 2890 | for _, event := range batch { |