Tell him when an expired clarify question is dropped

Vikunja #382. A parked clarifying question past its TTL was discarded
silently on read; now she says the old request is gone and the newly
spoken words are still routed as a fresh utterance.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGeSZxh1DCtRxmFVSYVGvJ
This commit is contained in:
kami
2026-07-31 12:51:47 +04:00
parent dc70a5a7ab
commit 214a4032cf
5 changed files with 124 additions and 13 deletions
+15
View File
@@ -100,6 +100,21 @@ func (s *ClarifyStore) Get(id string, now time.Time) *PendingQuestion {
return q
}
// TakeExpired reports whether a question was parked here but its TTL ran out,
// and drops it. Get drops such a question silently, which leaves the user
// thinking his request is still alive — the caller uses this to tell him it is
// gone before treating his words as a fresh utterance.
func (s *ClarifyStore) TakeExpired(id string, now time.Time) bool {
s.mu.Lock()
defer s.mu.Unlock()
q, ok := s.questions[id]
if !ok || !q.IsExpired(now) {
return false
}
delete(s.questions, id)
return true
}
func (s *ClarifyStore) Delete(id string) {
s.mu.Lock()
delete(s.questions, id)
+22
View File
@@ -60,6 +60,28 @@ func TestClarifyStoreGetPutDelete(t *testing.T) {
}
}
// TestClarifyStoreTakeExpired — TakeExpired reports (and drops) only a question
// whose TTL ran out.
func TestClarifyStoreTakeExpired(t *testing.T) {
s := NewClarifyStore(time.Minute)
if s.TakeExpired("voice", base) {
t.Fatal("nothing parked ⇒ nothing expired")
}
s.Put("voice", &PendingQuestion{Missing: []Slot{SlotTime}, Asked: base, TTL: time.Minute})
if s.TakeExpired("voice", base.Add(30*time.Second)) {
t.Fatal("a live question must not report as expired")
}
if s.Get("voice", base.Add(30*time.Second)) == nil {
t.Fatal("a live question must survive TakeExpired")
}
if !s.TakeExpired("voice", base.Add(2*time.Minute)) {
t.Fatal("a stale question must report as expired")
}
if s.TakeExpired("voice", base.Add(2*time.Minute)) {
t.Fatal("TakeExpired must drop the question, so the second call is false")
}
}
func TestNewClarifyStoreDefaultTTL(t *testing.T) {
s := NewClarifyStore(0)
q := &PendingQuestion{Asked: base}