(t *testing.T)
| 3776 | } |
| 3777 | |
| 3778 | func TestRecoverStaleRequiresActionChat(t *testing.T) { |
| 3779 | t.Parallel() |
| 3780 | |
| 3781 | db, ps, rawDB := dbtestutil.NewDBWithSQLDB(t) |
| 3782 | |
| 3783 | ctx := testutil.Context(t, testutil.WaitLong) |
| 3784 | user, org, model := seedChatDependencies(t, db) |
| 3785 | |
| 3786 | // Use a very short stale threshold so the periodic recovery |
| 3787 | // kicks in quickly during the test. |
| 3788 | staleAfter := 500 * time.Millisecond |
| 3789 | |
| 3790 | // Create a chat and set it to requires_action to simulate a |
| 3791 | // client that disappeared while the chat was waiting for |
| 3792 | // dynamic tool results. |
| 3793 | chat := dbgen.Chat(t, db, database.Chat{ |
| 3794 | OrganizationID: org.ID, |
| 3795 | OwnerID: user.ID, |
| 3796 | Title: "stale-requires-action", |
| 3797 | LastModelConfigID: model.ID, |
| 3798 | }) |
| 3799 | |
| 3800 | _, err := db.UpdateChatStatus(ctx, database.UpdateChatStatusParams{ |
| 3801 | ID: chat.ID, |
| 3802 | Status: database.ChatStatusRequiresAction, |
| 3803 | }) |
| 3804 | require.NoError(t, err) |
| 3805 | |
| 3806 | // Backdate updated_at so the chat appears stale to the |
| 3807 | // recovery loop without needing time.Sleep. |
| 3808 | _, err = rawDB.ExecContext(ctx, |
| 3809 | "UPDATE chats SET updated_at = $1 WHERE id = $2", |
| 3810 | time.Now().Add(-time.Hour), chat.ID) |
| 3811 | require.NoError(t, err) |
| 3812 | |
| 3813 | logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}) |
| 3814 | server := chatd.New(chatd.Config{ |
| 3815 | Logger: logger, |
| 3816 | Database: db, |
| 3817 | ReplicaID: uuid.New(), |
| 3818 | Pubsub: ps, |
| 3819 | PendingChatAcquireInterval: testutil.WaitLong, |
| 3820 | InFlightChatStaleAfter: staleAfter, |
| 3821 | }) |
| 3822 | server.Start() |
| 3823 | t.Cleanup(func() { |
| 3824 | require.NoError(t, server.Close()) |
| 3825 | }) |
| 3826 | |
| 3827 | // The stale recovery should transition the requires_action |
| 3828 | // chat to error with the timeout message. |
| 3829 | var chatResult database.Chat |
| 3830 | require.Eventually(t, func() bool { |
| 3831 | chatResult, err = db.GetChatByID(ctx, chat.ID) |
| 3832 | if err != nil { |
| 3833 | return false |
| 3834 | } |
| 3835 | return chatResult.Status == database.ChatStatusError |
nothing calls this directly
no test coverage detected