mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(coderd): fix TestPatchChat/Title flake by waiting for chat to settle (#24572)
## Problem `TestPatchChat/Title/Rename` and `TestPatchChat/Title/TrimsWhitespace` fail intermittently on `test-go-pg` with: ``` PATCH .../api/experimental/chats/<id>: unexpected status code 409: Title regeneration already in progress for this chat. ``` `createChat` persists a chat with `ChatStatusPending` and signals the daemon wake loop. If the `UpdateChat` PATCH arrives before the daemon transitions the chat past `Pending`/`Running`, the handler's `acquireManualTitleLock` returns a 409. Whether the PATCH wins the race is timing-dependent under PG + `-parallel` load. Sibling subtests `PreservesUpdatedAt` and `NoOpWhenTitleUnchanged` already wait for the chat to leave `Pending`/`Running` before renaming, which is why they do not flake. ## Fix Add a `waitChatSettled` helper closure in `TestPatchChat` that polls `client.GetChat` until the chat status leaves `Pending`/`Running`. Call it in the 4 subtests that issue a valid rename immediately after `createChat`: - `Title/Rename` (originally reported flake) - `Title/TrimsWhitespace` (originally reported flake) - `Title/LengthBoundaries` (latent flake in valid-rename cases) - `Title/PublishesWatchEvent` (latent flake, goroutine silently 409s) No handler, daemon, or SDK changes. The 409 is intentional production behavior; this is a pure test-side timing fix. Refs coder/internal#1480
This commit is contained in:
@@ -3973,6 +3973,22 @@ func TestPatchChat(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
return db2sdk.Chat(dbChat, nil, nil)
|
||||
}
|
||||
|
||||
// waitChatSettled polls the chat until its background title-generation
|
||||
// daemon has left the Pending/Running state. Without this, an immediate
|
||||
// UpdateChat can hit a 409 (title regeneration in progress).
|
||||
waitChatSettled := func(ctx context.Context, t *testing.T, client *codersdk.ExperimentalClient, chatID uuid.UUID) {
|
||||
t.Helper()
|
||||
require.Eventually(t, func() bool {
|
||||
c, err := client.GetChat(ctx, chatID)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return c.Status != codersdk.ChatStatusPending &&
|
||||
c.Status != codersdk.ChatStatusRunning
|
||||
}, testutil.WaitShort, testutil.IntervalFast)
|
||||
}
|
||||
|
||||
t.Run("PlanMode", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -4244,6 +4260,8 @@ func TestPatchChat(t *testing.T) {
|
||||
|
||||
chat := createChat(ctx, t, client, firstUser.OrganizationID, "original title")
|
||||
|
||||
waitChatSettled(ctx, t, client, chat.ID)
|
||||
|
||||
err := client.UpdateChat(ctx, chat.ID, codersdk.UpdateChatRequest{
|
||||
Title: ptr.Ref("renamed title"),
|
||||
})
|
||||
@@ -4263,6 +4281,8 @@ func TestPatchChat(t *testing.T) {
|
||||
|
||||
chat := createChat(ctx, t, client, firstUser.OrganizationID, "before trim")
|
||||
|
||||
waitChatSettled(ctx, t, client, chat.ID)
|
||||
|
||||
err := client.UpdateChat(ctx, chat.ID, codersdk.UpdateChatRequest{
|
||||
Title: ptr.Ref(" padded title "),
|
||||
})
|
||||
@@ -4360,6 +4380,8 @@ func TestPatchChat(t *testing.T) {
|
||||
_ = createChatModelConfig(t, client)
|
||||
|
||||
chat := createChat(ctx, t, client, firstUser.OrganizationID, "boundary baseline")
|
||||
waitChatSettled(ctx, t, client, chat.ID)
|
||||
|
||||
err := client.UpdateChat(ctx, chat.ID, codersdk.UpdateChatRequest{
|
||||
Title: ptr.Ref(tc.title),
|
||||
})
|
||||
@@ -4471,6 +4493,8 @@ func TestPatchChat(t *testing.T) {
|
||||
|
||||
chat := createChat(ctx, t, client, firstUser.OrganizationID, "announce me")
|
||||
|
||||
waitChatSettled(ctx, t, client, chat.ID)
|
||||
|
||||
conn, err := client.Dial(ctx, "/api/experimental/chats/watch", nil)
|
||||
require.NoError(t, err)
|
||||
defer conn.Close(websocket.StatusNormalClosure, "done")
|
||||
|
||||
Reference in New Issue
Block a user