Skip to content

Commit b797376

Browse files
committed
Base chat retention cleanup on updated-at instead of created-at
1 parent 5ae8b06 commit b797376

4 files changed

Lines changed: 26 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
- Skip redundant MCP `tool/serverUpdated` notification after prompts/resources listing when the server has none.
6+
- Chat retention (`chatRetentionDays`) now considers when the chat was last updated instead of when it was created, keeping old but still active chats.
67

78
## 0.154.0
89

docs/config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@
5858
},
5959
"chatRetentionDays": {
6060
"type": "integer",
61-
"description": "Number of days to keep old chats and tool call output cache before cleanup. Set to 0 to disable cleanup entirely.",
62-
"markdownDescription": "Number of days to keep old chats and tool call output cache before cleanup. Set to `0` to disable cleanup entirely.",
61+
"description": "Number of days to keep chats (since last update) and tool call output cache before cleanup. Set to 0 to disable cleanup entirely.",
62+
"markdownDescription": "Number of days to keep chats (since last update) and tool call output cache before cleanup. Set to `0` to disable cleanup entirely.",
6363
"default": 14
6464
},
6565
"agent": {

src/eca/db.clj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,8 @@
801801
false)))
802802

803803
(defn cleanup-old-chats!
804-
"Deletes chats older than retention-days: removes them from memory and their
804+
"Deletes chats not updated for retention-days (falling back to `:created-at`
805+
when `:updated-at` is missing): removes them from memory and their
805806
per-chat cache files, then refreshes the chats index once. When
806807
retention-days is non-positive, cleanup is disabled."
807808
[db* metrics retention-days]
@@ -813,16 +814,16 @@
813814
(fn [chats]
814815
(into {}
815816
(filter (fn [[id chat]]
816-
(let [created-at (:created-at chat)]
817-
(if (and created-at (< created-at cutoff))
817+
(let [recency (or (:updated-at chat) (:created-at chat))]
818+
(if (and recency (< recency cutoff))
818819
(do (swap! removed-ids* conj id) false)
819820
true))))
820821
chats)))
821822
(when-let [removed-ids (not-empty @removed-ids*)]
822823
;; Tombstone the ids so the index merge-on-write does not resurrect
823824
;; them from an index file shared with another live server.
824825
(swap! db* update :deleted-chat-ids (fnil into #{}) removed-ids)
825-
(logger/info logger-tag (str "Cleaned up " (count removed-ids) " chat(s) older than " retention-days " days"))
826+
(logger/info logger-tag (str "Cleaned up " (count removed-ids) " chat(s) not updated for " retention-days " days"))
826827
(let [db @db*
827828
workspaces (db-workspaces db)]
828829
(doseq [chat-id removed-ids]

test/eca/db_test.clj

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,24 +458,38 @@
458458
"recent-chat" {:id "recent-chat"
459459
:created-at two-days-ago
460460
:messages [{:role "user" :content "hello"}]}
461+
"old-but-active" {:id "old-but-active"
462+
:created-at fifteen-days-ago
463+
:updated-at two-days-ago
464+
:messages [{:role "user" :content "hi again"}]}
465+
"stale-updated" {:id "stale-updated"
466+
:created-at fifteen-days-ago
467+
:updated-at fifteen-days-ago
468+
:messages [{:role "user" :content "bye"}]}
461469
"no-timestamp" {:id "no-timestamp"
462470
:messages [{:role "user" :content "hey"}]}}})]
463-
(doseq [id ["old-chat" "recent-chat" "no-timestamp"]]
471+
(doseq [id ["old-chat" "recent-chat" "old-but-active" "stale-updated" "no-timestamp"]]
464472
(db/save-chat! @db* id nil))
465-
(testing "deletes old chats (memory + file), keeps recent and chats without created-at"
473+
(testing "deletes stale chats (memory + file), keeps recently updated and chats without timestamps"
466474
(db/cleanup-old-chats! db* nil 14)
467475
(is (nil? (get-in @db* [:chats "old-chat"]))
468476
"Chat older than 14 days should be removed")
469477
(is (some? (get-in @db* [:chats "recent-chat"]))
470478
"Chat newer than 14 days should be kept")
479+
(is (some? (get-in @db* [:chats "old-but-active"]))
480+
"Chat created long ago but updated recently should be kept")
481+
(is (nil? (get-in @db* [:chats "stale-updated"]))
482+
"Chat not updated for more than 14 days should be removed")
471483
(is (some? (get-in @db* [:chats "no-timestamp"]))
472484
"Chat without created-at should be kept")
473-
(is (= #{"old-chat"} (:deleted-chat-ids @db*))
485+
(is (= #{"old-chat" "stale-updated"} (:deleted-chat-ids @db*))
474486
"Removed chat ids are tombstoned so index merges cannot resurrect them")
475487
(is (not (fs/exists? (chat-cache-file workspaces "old-chat")))
476488
"old chat's cache file is deleted")
489+
(is (not (fs/exists? (chat-cache-file workspaces "stale-updated")))
490+
"stale chat's cache file is deleted")
477491
(is (fs/exists? (chat-cache-file workspaces "recent-chat")))
478-
(is (= #{"recent-chat" "no-timestamp"} (set (keys (read-index workspaces)))))))
492+
(is (= #{"recent-chat" "old-but-active" "no-timestamp"} (set (keys (read-index workspaces)))))))
479493
(finally (fs/delete-tree tmpdir))))))
480494

481495
(deftest cleanup-old-chats-no-op-test

0 commit comments

Comments
 (0)