88 "testing"
99 "time"
1010
11+ apiintegrations "github.com/onllm-dev/onwatch/v2/internal/api_integrations"
1112 "github.com/onllm-dev/onwatch/v2/internal/store"
1213)
1314
@@ -24,7 +25,7 @@ func TestAPIIntegrationsIngestAgent_ScanFile_PartialLineAndCompletion(t *testing
2425 t .Fatalf ("WriteFile: %v" , err )
2526 }
2627
27- ag := NewAPIIntegrationsIngestAgent (st , dir , slog .Default ())
28+ ag := NewAPIIntegrationsIngestAgent (st , dir , 0 , slog .Default ())
2829 if err := ag .scanFile (path ); err != nil {
2930 t .Fatalf ("scanFile(1): %v" , err )
3031 }
@@ -73,7 +74,7 @@ func TestAPIIntegrationsIngestAgent_ScanFile_InvalidLineCreatesAlert(t *testing.
7374 t .Fatalf ("WriteFile: %v" , err )
7475 }
7576
76- ag := NewAPIIntegrationsIngestAgent (st , dir , slog .Default ())
77+ ag := NewAPIIntegrationsIngestAgent (st , dir , 0 , slog .Default ())
7778 if err := ag .scanFile (path ); err != nil {
7879 t .Fatalf ("scanFile: %v" , err )
7980 }
@@ -108,7 +109,7 @@ func TestAPIIntegrationsIngestAgent_ScanFile_DedupAndTruncation(t *testing.T) {
108109 t .Fatalf ("WriteFile: %v" , err )
109110 }
110111
111- ag := NewAPIIntegrationsIngestAgent (st , dir , slog .Default ())
112+ ag := NewAPIIntegrationsIngestAgent (st , dir , 0 , slog .Default ())
112113 if err := ag .scanFile (path ); err != nil {
113114 t .Fatalf ("scanFile(1): %v" , err )
114115 }
@@ -157,7 +158,7 @@ func TestAPIIntegrationsIngestAgent_Run_ProcessesMultipleFiles(t *testing.T) {
157158 }
158159 }
159160
160- ag := NewAPIIntegrationsIngestAgent (st , dir , slog .Default ())
161+ ag := NewAPIIntegrationsIngestAgent (st , dir , 0 , slog .Default ())
161162 ag .SetInterval (10 * time .Millisecond )
162163 ctx , cancel := context .WithCancel (context .Background ())
163164 done := make (chan struct {})
@@ -177,3 +178,47 @@ func TestAPIIntegrationsIngestAgent_Run_ProcessesMultipleFiles(t *testing.T) {
177178 t .Fatalf ("summary=%+v" , summary )
178179 }
179180}
181+
182+ func TestAPIIntegrationsIngestAgent_Scan_PrunesExpiredDatabaseRows (t * testing.T ) {
183+ st , err := store .New (":memory:" )
184+ if err != nil {
185+ t .Fatalf ("New: %v" , err )
186+ }
187+ defer st .Close ()
188+
189+ oldEvent := `{"ts":"2025-12-01T12:00:00Z","integration":"notes","provider":"openai","model":"gpt-4.1-mini","prompt_tokens":2,"completion_tokens":1}`
190+ parsedOld , err := apiintegrations .ParseUsageEventLine ([]byte (oldEvent ), "/tmp/api-integrations/notes.jsonl" )
191+ if err != nil {
192+ t .Fatalf ("ParseUsageEventLine(old): %v" , err )
193+ }
194+ if _ , err := st .InsertAPIIntegrationUsageEvent (parsedOld ); err != nil {
195+ t .Fatalf ("InsertAPIIntegrationUsageEvent(old): %v" , err )
196+ }
197+
198+ dir := t .TempDir ()
199+ path := filepath .Join (dir , "notes.jsonl" )
200+ newLine := `{"ts":"2026-04-03T12:00:00Z","integration":"notes","provider":"openai","model":"gpt-4.1-mini","prompt_tokens":3,"completion_tokens":2}` + "\n "
201+ if err := os .WriteFile (path , []byte (newLine ), 0o600 ); err != nil {
202+ t .Fatalf ("WriteFile: %v" , err )
203+ }
204+
205+ ag := NewAPIIntegrationsIngestAgent (st , dir , 24 * time .Hour , slog .Default ())
206+ ag .pruneInterval = time .Millisecond
207+ if err := ag .pruneExpiredUsageEvents (); err != nil {
208+ t .Fatalf ("pruneExpiredUsageEvents: %v" , err )
209+ }
210+ if err := ag .scanFile (path ); err != nil {
211+ t .Fatalf ("scanFile: %v" , err )
212+ }
213+
214+ events , err := st .QueryAPIIntegrationUsageRange (time .Date (2025 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ), time .Date (2026 , 5 , 1 , 0 , 0 , 0 , 0 , time .UTC ))
215+ if err != nil {
216+ t .Fatalf ("QueryAPIIntegrationUsageRange: %v" , err )
217+ }
218+ if len (events ) != 1 {
219+ t .Fatalf ("events=%+v" , events )
220+ }
221+ if events [0 ].Timestamp .Format (time .RFC3339 ) != "2026-04-03T12:00:00Z" {
222+ t .Fatalf ("expected retained new event, got %+v" , events [0 ])
223+ }
224+ }
0 commit comments