mirror of
https://github.com/coder/coder.git
synced 2026-09-21 20:51:01 +08:00
refactor(coderd/x/chatd): insert chats directly as pending on creation (#23888)
Previously, `CreateChat` inserted the `chats` row with the DB default status (`waiting`), then updated it to `pending` in the same transaction via `setChatPendingWithStore`. This wasted two extra queries per chat creation (`GetChatByID` + `UpdateChatStatus`) and rewrote the same row immediately after inserting it. Now `CreateChat` passes the status directly to `InsertChat`, so the row is written once in its final create-time state. The `setChatPendingWithStore` helper is removed entirely. `InsertChat` now requires an explicit `status` parameter at all callsites instead of relying on a DB column default. ## Motivation On an experimental branch we're trialing firing all chatd notifications from plpgsql triggers. The old two-step insert made that awkward: in an `AFTER INSERT` trigger, `NEW` only contained the insert-time row (`waiting`), not the final committed state (`pending`). To emit the correct event payload the trigger had to be deferred and re-read the row from `chats` at commit time. With this change, `NEW` already contains the correct row to publish — no deferred trigger, no extra `SELECT`, simpler and cheaper trigger logic. That said, this seems like a worthwhile change regardless of the trigger experiment: writing the final row state once removes unnecessary DB work on every chat creation and makes the create path easier to reason about.
This commit is contained in:
@@ -721,7 +721,9 @@ func (s *MethodTestSuite) TestChats() {
|
||||
check.Args(threshold).Asserts(rbac.ResourceChat, policy.ActionRead).Returns(chats)
|
||||
}))
|
||||
s.Run("InsertChat", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
arg := testutil.Fake(s.T(), faker, database.InsertChatParams{})
|
||||
arg := testutil.Fake(s.T(), faker, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
})
|
||||
chat := testutil.Fake(s.T(), faker, database.Chat{OwnerID: arg.OwnerID})
|
||||
dbm.EXPECT().InsertChat(gomock.Any(), arg).Return(chat, nil).AnyTimes()
|
||||
check.Args(arg).Asserts(rbac.ResourceChat.WithOwner(arg.OwnerID.String()), policy.ActionCreate).Returns(chat)
|
||||
|
||||
@@ -1285,6 +1285,7 @@ func TestGetAuthorizedChats(t *testing.T) {
|
||||
// Create 3 chats owned by owner.
|
||||
for i := range 3 {
|
||||
_, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: owner.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: fmt.Sprintf("owner chat %d", i+1),
|
||||
@@ -1295,6 +1296,7 @@ func TestGetAuthorizedChats(t *testing.T) {
|
||||
// Create 2 chats owned by member.
|
||||
for i := range 2 {
|
||||
_, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: member.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: fmt.Sprintf("member chat %d", i+1),
|
||||
@@ -1416,6 +1418,7 @@ func TestGetAuthorizedChats(t *testing.T) {
|
||||
})
|
||||
for i := range 7 {
|
||||
_, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: paginationUser.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: fmt.Sprintf("pagination chat %d", i+1),
|
||||
@@ -9472,6 +9475,7 @@ func TestInsertChatMessages(t *testing.T) {
|
||||
)
|
||||
|
||||
chat, err := store.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
LastModelConfigID: modelConfigA.ID,
|
||||
Title: "test-chat-" + uuid.NewString(),
|
||||
@@ -9641,6 +9645,7 @@ func TestGetChatMessagesForPromptByChatID(t *testing.T) {
|
||||
newChat := func(t *testing.T) database.Chat {
|
||||
t.Helper()
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: "test-chat-" + uuid.NewString(),
|
||||
@@ -10014,6 +10019,7 @@ func TestGetPRInsights(t *testing.T) {
|
||||
createChat := func(t *testing.T, store database.Store, userID, mcID uuid.UUID, title string) database.Chat {
|
||||
t.Helper()
|
||||
chat, err := store.InsertChat(context.Background(), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: userID,
|
||||
LastModelConfigID: mcID,
|
||||
Title: title,
|
||||
@@ -10149,6 +10155,7 @@ func TestGetPRInsights(t *testing.T) {
|
||||
createChildChat := func(t *testing.T, store database.Store, userID, mcID, parentID, rootID uuid.UUID, title string) database.Chat {
|
||||
t.Helper()
|
||||
chat, err := store.InsertChat(context.Background(), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: userID,
|
||||
LastModelConfigID: mcID,
|
||||
Title: title,
|
||||
@@ -10538,6 +10545,7 @@ func TestChatPinOrderQueries(t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: ownerID,
|
||||
LastModelConfigID: modelCfgID,
|
||||
Title: title,
|
||||
@@ -10718,6 +10726,7 @@ func TestChatLabels(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: owner.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: "labeled-chat",
|
||||
@@ -10740,6 +10749,7 @@ func TestChatLabels(t *testing.T) {
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: owner.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: "no-labels-chat",
|
||||
@@ -10755,6 +10765,7 @@ func TestChatLabels(t *testing.T) {
|
||||
ctx := testutil.Context(t, testutil.WaitMedium)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: owner.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: "update-labels-chat",
|
||||
@@ -10795,6 +10806,7 @@ func TestChatLabels(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: owner.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: "original-title",
|
||||
@@ -10831,6 +10843,7 @@ func TestChatLabels(t *testing.T) {
|
||||
labelsJSON, err := json.Marshal(tc.labels)
|
||||
require.NoError(t, err)
|
||||
_, err = db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: owner.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: tc.title,
|
||||
@@ -10916,6 +10929,7 @@ func TestChatHasUnread(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
chat, err := store.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: "test-chat-" + uuid.NewString(),
|
||||
|
||||
@@ -5707,6 +5707,7 @@ INSERT INTO chats (
|
||||
last_model_config_id,
|
||||
title,
|
||||
mode,
|
||||
status,
|
||||
mcp_server_ids,
|
||||
labels
|
||||
) VALUES (
|
||||
@@ -5719,8 +5720,9 @@ INSERT INTO chats (
|
||||
$7::uuid,
|
||||
$8::text,
|
||||
$9::chat_mode,
|
||||
COALESCE($10::uuid[], '{}'::uuid[]),
|
||||
COALESCE($11::jsonb, '{}'::jsonb)
|
||||
$10::chat_status,
|
||||
COALESCE($11::uuid[], '{}'::uuid[]),
|
||||
COALESCE($12::jsonb, '{}'::jsonb)
|
||||
)
|
||||
RETURNING
|
||||
id, owner_id, workspace_id, title, status, worker_id, started_at, heartbeat_at, created_at, updated_at, parent_chat_id, root_chat_id, last_model_config_id, archived, last_error, mode, mcp_server_ids, labels, build_id, agent_id, pin_order, last_read_message_id, last_injected_context
|
||||
@@ -5736,6 +5738,7 @@ type InsertChatParams struct {
|
||||
LastModelConfigID uuid.UUID `db:"last_model_config_id" json:"last_model_config_id"`
|
||||
Title string `db:"title" json:"title"`
|
||||
Mode NullChatMode `db:"mode" json:"mode"`
|
||||
Status ChatStatus `db:"status" json:"status"`
|
||||
MCPServerIDs []uuid.UUID `db:"mcp_server_ids" json:"mcp_server_ids"`
|
||||
Labels pqtype.NullRawMessage `db:"labels" json:"labels"`
|
||||
}
|
||||
@@ -5751,6 +5754,7 @@ func (q *sqlQuerier) InsertChat(ctx context.Context, arg InsertChatParams) (Chat
|
||||
arg.LastModelConfigID,
|
||||
arg.Title,
|
||||
arg.Mode,
|
||||
arg.Status,
|
||||
pq.Array(arg.MCPServerIDs),
|
||||
arg.Labels,
|
||||
)
|
||||
|
||||
@@ -392,6 +392,7 @@ INSERT INTO chats (
|
||||
last_model_config_id,
|
||||
title,
|
||||
mode,
|
||||
status,
|
||||
mcp_server_ids,
|
||||
labels
|
||||
) VALUES (
|
||||
@@ -404,6 +405,7 @@ INSERT INTO chats (
|
||||
@last_model_config_id::uuid,
|
||||
@title::text,
|
||||
sqlc.narg('mode')::chat_mode,
|
||||
@status::chat_status,
|
||||
COALESCE(@mcp_server_ids::uuid[], '{}'::uuid[]),
|
||||
COALESCE(sqlc.narg('labels')::jsonb, '{}'::jsonb)
|
||||
)
|
||||
|
||||
@@ -495,6 +495,7 @@ func TestPostChats(t *testing.T) {
|
||||
wantResetsAt := enableDailyChatUsageLimit(ctx, t, db, 100)
|
||||
|
||||
existingChat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "existing-limit-chat",
|
||||
@@ -547,6 +548,7 @@ func TestListChats(t *testing.T) {
|
||||
memberClientRaw, member := coderdtest.CreateAnotherUser(t, client.Client, firstUser.OrganizationID, rbac.RoleAgentsAccess())
|
||||
memberClient := codersdk.NewExperimentalClient(memberClientRaw)
|
||||
memberDBChat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: member.ID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "member chat only",
|
||||
@@ -627,6 +629,7 @@ func TestListChats(t *testing.T) {
|
||||
memberClientRaw, member := coderdtest.CreateAnotherUser(t, client.Client, firstUser.OrganizationID)
|
||||
memberClient := codersdk.NewExperimentalClient(memberClientRaw)
|
||||
_, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: member.ID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "member chat",
|
||||
@@ -941,6 +944,7 @@ func TestWatchChats(t *testing.T) {
|
||||
|
||||
// Insert a chat and a diff status row.
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "diff status watch test",
|
||||
@@ -1068,6 +1072,7 @@ func TestWatchChats(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
childOne, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "watch child 1",
|
||||
@@ -1077,6 +1082,7 @@ func TestWatchChats(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
childTwo, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "watch child 2",
|
||||
@@ -2207,6 +2213,7 @@ func TestArchiveChat(t *testing.T) {
|
||||
|
||||
// Insert child chats directly via the database.
|
||||
child1, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "child 1",
|
||||
@@ -2216,6 +2223,7 @@ func TestArchiveChat(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
child2, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "child 2",
|
||||
@@ -2322,6 +2330,7 @@ func TestUnarchiveChat(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
child1, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "child 1",
|
||||
@@ -2331,6 +2340,7 @@ func TestUnarchiveChat(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
child2, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "child 2",
|
||||
@@ -3661,6 +3671,7 @@ func TestInterruptChat(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "interrupt route test",
|
||||
@@ -3740,6 +3751,7 @@ func TestRegenerateChatTitle(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "chat with update denied",
|
||||
@@ -3848,6 +3860,7 @@ func TestRegenerateChatTitle(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "chat with lock held",
|
||||
@@ -3888,6 +3901,7 @@ func TestRegenerateChatTitle(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "pending chat without worker",
|
||||
@@ -4004,6 +4018,7 @@ func TestGetChatDiffStatus(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
noCachedStatusChat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "get diff status route no cache",
|
||||
@@ -4016,6 +4031,7 @@ func TestGetChatDiffStatus(t *testing.T) {
|
||||
require.Nil(t, noCachedChat.DiffStatus)
|
||||
|
||||
cachedStatusChat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "get diff status route cached",
|
||||
@@ -4122,6 +4138,7 @@ func TestGetChatDiffContents(t *testing.T) {
|
||||
user := coderdtest.CreateFirstUser(t, client.Client)
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "diff contents with cached repository reference",
|
||||
@@ -4218,6 +4235,7 @@ func TestDeleteChatQueuedMessage(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "delete queued message route test",
|
||||
@@ -4269,6 +4287,7 @@ func TestDeleteChatQueuedMessage(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "delete queued invalid id",
|
||||
@@ -4303,6 +4322,7 @@ func TestPromoteChatQueuedMessage(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "promote queued message route test",
|
||||
@@ -4373,6 +4393,7 @@ func TestPromoteChatQueuedMessage(t *testing.T) {
|
||||
enableDailyChatUsageLimit(ctx, t, db, 100)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "promote queued usage limit",
|
||||
@@ -4447,6 +4468,7 @@ func TestPromoteChatQueuedMessage(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "promote queued invalid id",
|
||||
@@ -5029,6 +5051,7 @@ func seedChatCostFixture(t *testing.T) chatCostTestFixture {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: firstUser.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "test chat",
|
||||
@@ -5146,6 +5169,7 @@ func TestChatCostSummary_AdminDrilldown(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(seedCtx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: member.ID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "member chat",
|
||||
@@ -5214,6 +5238,7 @@ func TestChatCostUsers(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
adminChat, err := db.InsertChat(dbauthz.AsSystemRestricted(seedCtx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: firstUser.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "admin chat",
|
||||
@@ -5241,6 +5266,7 @@ func TestChatCostUsers(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
memberChat, err := db.InsertChat(dbauthz.AsSystemRestricted(seedCtx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: member.ID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "member chat",
|
||||
@@ -5324,6 +5350,7 @@ func TestChatCostSummary_DateRange(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(seedCtx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: firstUser.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "date range test",
|
||||
@@ -5389,6 +5416,7 @@ func TestChatCostSummary_UnpricedMessages(t *testing.T) {
|
||||
modelConfig := createChatModelConfig(t, client)
|
||||
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: firstUser.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: "unpriced test",
|
||||
@@ -6455,6 +6483,7 @@ func TestGetChatsByWorkspace(t *testing.T) {
|
||||
// Helper to insert a chat linked to a workspace.
|
||||
insertChat := func(ctx context.Context, title string, workspaceID uuid.UUID) database.Chat {
|
||||
chat, err := db.InsertChat(dbauthz.AsSystemRestricted(ctx), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.UserID,
|
||||
LastModelConfigID: modelConfig.ID,
|
||||
Title: title,
|
||||
|
||||
@@ -62,6 +62,7 @@ func TestChatParam(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
chat, err := db.InsertChat(context.Background(), database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: ownerID,
|
||||
WorkspaceID: uuid.NullUUID{},
|
||||
ParentChatID: uuid.NullUUID{},
|
||||
|
||||
+5
-32
@@ -851,7 +851,10 @@ func (p *Server) CreateChat(ctx context.Context, opts CreateOptions) (database.C
|
||||
LastModelConfigID: opts.ModelConfigID,
|
||||
Title: opts.Title,
|
||||
Mode: opts.ChatMode,
|
||||
MCPServerIDs: opts.MCPServerIDs,
|
||||
// Chats created with an initial user message start pending.
|
||||
// Waiting is reserved for idle chats with no pending work.
|
||||
Status: database.ChatStatusPending,
|
||||
MCPServerIDs: opts.MCPServerIDs,
|
||||
Labels: pqtype.NullRawMessage{
|
||||
RawMessage: labelsJSON,
|
||||
Valid: true,
|
||||
@@ -920,10 +923,7 @@ func (p *Server) CreateChat(ctx context.Context, opts CreateOptions) (database.C
|
||||
return xerrors.Errorf("insert initial chat messages: %w", err)
|
||||
}
|
||||
|
||||
chat, err = setChatPendingWithStore(ctx, tx, insertedChat.ID)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("set chat pending: %w", err)
|
||||
}
|
||||
chat = insertedChat
|
||||
|
||||
if !chat.RootChatID.Valid && !chat.ParentChatID.Valid {
|
||||
chat.RootChatID = uuid.NullUUID{UUID: chat.ID, Valid: true}
|
||||
@@ -1997,33 +1997,6 @@ func (p *Server) RefreshStatus(ctx context.Context, chatID uuid.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setChatPendingWithStore(
|
||||
ctx context.Context,
|
||||
store database.Store,
|
||||
chatID uuid.UUID,
|
||||
) (database.Chat, error) {
|
||||
chat, err := store.GetChatByID(ctx, chatID)
|
||||
if err != nil {
|
||||
return database.Chat{}, xerrors.Errorf("get chat: %w", err)
|
||||
}
|
||||
if chat.Status == database.ChatStatusPending {
|
||||
return chat, nil
|
||||
}
|
||||
|
||||
updatedChat, err := store.UpdateChatStatus(ctx, database.UpdateChatStatusParams{
|
||||
ID: chat.ID,
|
||||
Status: database.ChatStatusPending,
|
||||
WorkerID: uuid.NullUUID{},
|
||||
StartedAt: sql.NullTime{},
|
||||
HeartbeatAt: sql.NullTime{},
|
||||
LastError: sql.NullString{},
|
||||
})
|
||||
if err != nil {
|
||||
return database.Chat{}, xerrors.Errorf("set chat pending: %w", err)
|
||||
}
|
||||
return updatedChat, nil
|
||||
}
|
||||
|
||||
func (p *Server) setChatWaiting(ctx context.Context, chatID uuid.UUID) (database.Chat, error) {
|
||||
var updatedChat database.Chat
|
||||
err := p.db.InTx(func(tx database.Store) error {
|
||||
|
||||
@@ -908,6 +908,7 @@ func TestCreateChatRejectsWhenUsageLimitReached(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
existingChat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
Title: "existing-limit-chat",
|
||||
LastModelConfigID: model.ID,
|
||||
@@ -1198,6 +1199,7 @@ func TestInterruptAutoPromotionIgnoresLaterUsageLimitIncrease(t *testing.T) {
|
||||
require.NotNil(t, laterQueuedResult.QueuedMessage)
|
||||
|
||||
spendChat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
WorkspaceID: uuid.NullUUID{},
|
||||
ParentChatID: uuid.NullUUID{},
|
||||
@@ -1448,6 +1450,7 @@ func TestRecoverStaleChatsPeriodically(t *testing.T) {
|
||||
// to running with a heartbeat in the past.
|
||||
deadWorkerID := uuid.New()
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
Title: "stale-recovery-periodic",
|
||||
LastModelConfigID: model.ID,
|
||||
@@ -1493,6 +1496,7 @@ func TestRecoverStaleChatsPeriodically(t *testing.T) {
|
||||
// This tests the periodic recovery, not just the startup one.
|
||||
deadWorkerID2 := uuid.New()
|
||||
chat2, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
Title: "stale-recovery-periodic-2",
|
||||
LastModelConfigID: model.ID,
|
||||
@@ -1531,6 +1535,7 @@ func TestNewReplicaRecoversStaleChatFromDeadReplica(t *testing.T) {
|
||||
// heartbeat (well beyond the stale threshold).
|
||||
deadReplicaID := uuid.New()
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
Title: "orphaned-chat",
|
||||
LastModelConfigID: model.ID,
|
||||
@@ -1573,6 +1578,7 @@ func TestWaitingChatsAreNotRecoveredAsStale(t *testing.T) {
|
||||
// Create a chat in waiting status — this should NOT be touched
|
||||
// by stale recovery.
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
Title: "waiting-chat",
|
||||
LastModelConfigID: model.ID,
|
||||
@@ -1615,6 +1621,7 @@ func TestUpdateChatStatusPersistsLastError(t *testing.T) {
|
||||
user, model := seedChatDependencies(ctx, t, db)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
Title: "error-persisted",
|
||||
LastModelConfigID: model.ID,
|
||||
|
||||
@@ -1482,6 +1482,7 @@ func TestNulEscapeRoundTrip(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
LastModelConfigID: model.ID,
|
||||
Title: "nul-roundtrip-test",
|
||||
@@ -1978,6 +1979,7 @@ func TestMediaToolResultRoundTrip(t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
chat, chatErr := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
LastModelConfigID: model.ID,
|
||||
Title: "media-roundtrip-" + callID,
|
||||
|
||||
@@ -35,6 +35,7 @@ func TestStartWorkspace(t *testing.T) {
|
||||
modelCfg := seedModelConfig(ctx, t, db, user.ID)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: "test-no-workspace",
|
||||
@@ -77,6 +78,7 @@ func TestStartWorkspace(t *testing.T) {
|
||||
ws := wsResp.Workspace
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
WorkspaceID: uuid.NullUUID{UUID: ws.ID, Valid: true},
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
@@ -155,6 +157,7 @@ func TestStartWorkspace(t *testing.T) {
|
||||
require.NotEqual(t, uuid.Nil, preferredAgentID)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
WorkspaceID: uuid.NullUUID{UUID: ws.ID, Valid: true},
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
@@ -214,6 +217,7 @@ func TestStartWorkspace(t *testing.T) {
|
||||
ws := wsResp.Workspace
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
WorkspaceID: uuid.NullUUID{UUID: ws.ID, Valid: true},
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
@@ -276,6 +280,7 @@ func TestStartWorkspace(t *testing.T) {
|
||||
ws := wsResp.Workspace
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
WorkspaceID: uuid.NullUUID{UUID: ws.ID, Valid: true},
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
@@ -332,6 +337,7 @@ func TestStartWorkspace(t *testing.T) {
|
||||
ws := wsResp.Workspace
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
WorkspaceID: uuid.NullUUID{UUID: ws.ID, Valid: true},
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
@@ -400,6 +406,7 @@ func TestStartWorkspace(t *testing.T) {
|
||||
ws := wsResp.Workspace
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
WorkspaceID: uuid.NullUUID{UUID: ws.ID, Valid: true},
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
|
||||
@@ -977,6 +977,7 @@ func TestWorker(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
LastModelConfigID: modelCfg.ID,
|
||||
Title: "integration-test",
|
||||
|
||||
@@ -140,6 +140,7 @@ func seedWaitingChat(
|
||||
t.Helper()
|
||||
|
||||
chat, err := db.InsertChat(ctx, database.InsertChatParams{
|
||||
Status: database.ChatStatusWaiting,
|
||||
OwnerID: user.ID,
|
||||
LastModelConfigID: model.ID,
|
||||
Title: title,
|
||||
|
||||
Reference in New Issue
Block a user