Skip to content

Conversation

@Ayyanaruto
Copy link
Contributor

@Ayyanaruto Ayyanaruto commented Oct 21, 2025

Based on discussion #8315 Implement asynchronous initialization for the autocomplete cache and refine eviction logic to optimize performance and memory usage. This update ensures a more efficient handling of cached entries with SQLite persistence.


Summary by cubic

Initialize the autocomplete cache asynchronously and move lookups to an in-memory LRU with periodic SQLite persistence. This improves startup, speeds up cache hits, and tightens eviction for better memory usage.

  • New Features
    • Async singleton cache initialization that loads existing entries and starts a 30s flush timer.
    • In-memory longest-prefix matching with validation; timestamps updated on access.
    • LRU eviction in memory when capacity is exceeded, marking evicted keys for deletion.
    • Periodic flush persists dirty entries in a single transaction (upsert/delete) under a mutex, with graceful error handling.
    • CompletionProvider now awaits the cache on demand and disposes it cleanly via close().
    • Added comprehensive tests for cache operations, eviction, persistence, timer behavior, and resource cleanup.

@Ayyanaruto Ayyanaruto requested a review from a team as a code owner October 21, 2025 10:25
@Ayyanaruto Ayyanaruto requested review from sestinj and removed request for a team October 21, 2025 10:25
@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Oct 21, 2025
@Ayyanaruto Ayyanaruto changed the title Enhance autocomplete cache with async initialization and improved eviction logic feat: Enhance autocomplete cache with async initialization and improved eviction logic Oct 21, 2025
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 3 files

Prompt for AI agents (all 3 issues)

Understand the root cause of the following 3 issues and fix them.


<file name="core/autocomplete/util/AutocompleteLruCache.ts">

<violation number="1" location="core/autocomplete/util/AutocompleteLruCache.ts:218">
After close(), we need to clear the singleton so future get() calls reinitialize a fresh cache; otherwise callers receive an instance whose DB connection is already closed and whose flush timer never restarts.</violation>
</file>

<file name="core/autocomplete/util/AutocompleteLruCache.test.ts">

<violation number="1" location="core/autocomplete/util/AutocompleteLruCache.test.ts:4">
Mocking `async-mutex` removes the real Mutex implementation, so `cache.put` fails when it tries to call `this.mutex.acquire()`.</violation>

<violation number="2" location="core/autocomplete/util/AutocompleteLruCache.test.ts:638">
`jest.doMock(&quot;sqlite&quot;, …)` runs after AutocompleteLruCache imported `open`, leaving `open` as the default auto-mock and causing `AutocompleteLruCache.get()` to crash with an undefined database handle.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

* Gracefully shuts down the cache.
* Stops the flush timer, persists pending changes, and closes database connection.
*/
async close() {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After close(), we need to clear the singleton so future get() calls reinitialize a fresh cache; otherwise callers receive an instance whose DB connection is already closed and whose flush timer never restarts.

Prompt for AI agents
Address the following comment on core/autocomplete/util/AutocompleteLruCache.ts at line 218:

<comment>After close(), we need to clear the singleton so future get() calls reinitialize a fresh cache; otherwise callers receive an instance whose DB connection is already closed and whose flush timer never restarts.</comment>

<file context>
@@ -1,121 +1,227 @@
+   * Gracefully shuts down the cache.
+   * Stops the flush timer, persists pending changes, and closes database connection.
+   */
+  async close() {
+    if (this.flushTimer) {
+      clearInterval(this.flushTimer);
</file context>

✅ Addressed in 52ebf5d


it("should return same instance on multiple calls", async () => {
const mockOpen = jest.fn().mockResolvedValue(mockDb);
jest.doMock("sqlite", () => ({ open: mockOpen }));
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jest.doMock("sqlite", …) runs after AutocompleteLruCache imported open, leaving open as the default auto-mock and causing AutocompleteLruCache.get() to crash with an undefined database handle.

Prompt for AI agents
Address the following comment on core/autocomplete/util/AutocompleteLruCache.test.ts at line 638:

<comment>`jest.doMock(&quot;sqlite&quot;, …)` runs after AutocompleteLruCache imported `open`, leaving `open` as the default auto-mock and causing `AutocompleteLruCache.get()` to crash with an undefined database handle.</comment>

<file context>
@@ -0,0 +1,646 @@
+
+    it(&quot;should return same instance on multiple calls&quot;, async () =&gt; {
+      const mockOpen = jest.fn().mockResolvedValue(mockDb);
+      jest.doMock(&quot;sqlite&quot;, () =&gt; ({ open: mockOpen }));
+
+      const instance1 = await AutocompleteLruCache.get();
</file context>
Fix with Cubic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be working to me correctly

import AutocompleteLruCache from "./AutocompleteLruCache";

// Mock the external dependencies before importing
jest.mock("async-mutex");
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mocking async-mutex removes the real Mutex implementation, so cache.put fails when it tries to call this.mutex.acquire().

Prompt for AI agents
Address the following comment on core/autocomplete/util/AutocompleteLruCache.test.ts at line 4:

<comment>Mocking `async-mutex` removes the real Mutex implementation, so `cache.put` fails when it tries to call `this.mutex.acquire()`.</comment>

<file context>
@@ -0,0 +1,646 @@
+import AutocompleteLruCache from &quot;./AutocompleteLruCache&quot;;
+
+// Mock the external dependencies before importing
+jest.mock(&quot;async-mutex&quot;);
+jest.mock(&quot;sqlite&quot;);
+jest.mock(&quot;sqlite3&quot;);
</file context>

✅ Addressed in 52ebf5d

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant