fix(coderd): strip injected context from chat watch events (#26397)

Chat watch events publish through Postgres NOTIFY, so embedding the full
REST chat payload can exceed the payload limit when
`last_injected_context` grows. Strip `LastInjectedContext` from watch
payloads, matching the existing `Files` omission, while keeping
`DiffStatus` populated for `diff_status_change` events and leaving `GET
/chats/{id}` unchanged.

A previous attempt in #26368 introduced a separate summary type for
watch events. This avoids making that API change prematurely: one large
optional field is not enough reason to split the shared `Chat` shape by
endpoint, so this keeps the existing type and omits the heavy detail
field from pubsub payloads.

Closes CODAGT-501
This commit is contained in:
Ethan
2026-06-16 22:08:50 +10:00
committed by GitHub
parent 62288782fc
commit e345e061f2
3 changed files with 43 additions and 39 deletions
+15 -9
View File
@@ -3493,23 +3493,29 @@ func (p *Server) publishChatPubsubEvents(chats []database.Chat, kind codersdk.Ch
}
}
// chatWatchEventSDKChat builds the chat embedded in ChatWatchEvent
// notifications. These payloads travel through PostgreSQL NOTIFY, so
// omit fields that can grow large and that watch consumers already read
// from the REST chat endpoint.
func chatWatchEventSDKChat(chat database.Chat, diffStatus *codersdk.ChatDiffStatus) codersdk.Chat {
sdkChat := db2sdk.Chat(chat, nil, nil)
sdkChat.Files = nil
sdkChat.LastInjectedContext = nil
if diffStatus != nil {
sdkChat.DiffStatus = diffStatus
}
return sdkChat
}
// publishChatPubsubEvent broadcasts a chat lifecycle event via PostgreSQL
// pubsub so that all replicas can push updates to watching clients.
func (p *Server) publishChatPubsubEvent(chat database.Chat, kind codersdk.ChatWatchEventKind, diffStatus *codersdk.ChatDiffStatus) {
if p.pubsub == nil {
return
}
// diffStatus is applied below. File metadata is intentionally
// omitted from pubsub events to avoid an extra DB query per
// publish. Clients must merge pubsub updates, not replace
// cached file metadata.
sdkChat := db2sdk.Chat(chat, nil, nil)
if diffStatus != nil {
sdkChat.DiffStatus = diffStatus
}
event := codersdk.ChatWatchEvent{
Kind: kind,
Chat: sdkChat,
Chat: chatWatchEventSDKChat(chat, diffStatus),
}
payload, err := json.Marshal(event)
if err != nil {
+1 -2
View File
@@ -12,7 +12,6 @@ import (
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/db2sdk"
coderdpubsub "github.com/coder/coder/v2/coderd/pubsub"
"github.com/coder/coder/v2/coderd/x/chatd/chatdebug"
"github.com/coder/coder/v2/coderd/x/chatd/chatprompt"
@@ -514,7 +513,7 @@ func (s *taskStarter) publishWatchWithRetry(
func publishChatWatchEvent(pubsub chatWorkerPubsub, chat database.Chat, kind codersdk.ChatWatchEventKind) error {
event := codersdk.ChatWatchEvent{
Kind: kind,
Chat: db2sdk.Chat(chat, nil, nil),
Chat: chatWatchEventSDKChat(chat, nil),
}
payload, err := json.Marshal(event)
if err != nil {