-
Notifications
You must be signed in to change notification settings - Fork 0
[Repo Assist] perf: push winners count limit to DB query and cache prompt files #499
Description
🤖 This PR was created by Repo Assist, an automated AI assistant.
Summary
Two targeted performance improvements identified during a routine codebase review:
1. WinnersService: limit applied at the database layer
Before: all winners rows were fetched into memory, then .Take(count) applied in-process.
After: count is passed into the query, so the LIMIT clause is pushed to the database.
Additionally, .AsNoTracking() is added for the read-only query — EF Core won't create change-tracking proxies, reducing memory allocations and GC pressure per request.
2. prompt_loader.py: cache prompt files with lru_cache
load_prompt reads and parses a YAML file on every call. For a production chatbot, the same prompt files are loaded on every request. Adding @lru_cache(maxsize=10) means the file I/O and YAML parsing happen once per unique (prompt_name, prompts_dir) pair.
Trade-offs
lru_cacheonload_promptmeans prompt file changes require a service restart to take effect. Acceptable for a Docker/Aspire deployment model where restarts are cheap.AsNoTracking()only applies to the read path — no write operations affected.
Test Status
- .NET build: changes are backward-compatible (method signatures changed but all callers are within the same class)
- Python:
lru_cacheis stdlib — no new dependencies - Infrastructure: this is a read-service, no migrations needed
Generated by Repo Assist · ◷
To install this agentic workflow, run
gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f
Note
This was originally intended as a pull request, but GitHub Actions is not permitted to create or approve pull requests in this repository.
The changes have been pushed to branch repo-assist/improve-perf-asnotracking-lru-cache-1f6995db1c2d51e7-cec4b5efd1592c5e.
To fix the permissions issue, go to Settings → Actions → General and enable Allow GitHub Actions to create and approve pull requests.
Show patch preview (96 of 96 lines)
From 3fb81018d6658d2085f72c976b958ba375bf3e8c Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Wed, 11 Mar 2026 13:23:09 +0000
Subject: [PATCH] perf: push Take/count to DB query and cache prompt files
- WinnersService: fetch winners-count flag first, then pass the limit
directly to GetAllDatabaseWinnersAsync so EF Core applies Take() at
the SQL layer instead of loading all rows then discarding most of them
- WinnersService: add .AsNoTracking() on the read-only DB query to
avoid unnecessary change-tracking overhead
- prompt_loader: add @lru_cache(maxsize=10) to load_prompt so each
.prompt.yml file is read from disk and parsed only once per process
lifetime instead of on every chat request
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
src/Garage.ApiService/Services/WinnersService.cs | 16 ++++++++--------
src/Garage.ChatService/prompt_loader.py | 5 +++++
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/src/Garage.ApiService/Services/WinnersService.cs b/src/Garage.ApiService/Services/WinnersService.cs
index e1862da..61485e3 100644
--- a/src/Garage.ApiService/Services/WinnersService.cs
+++ b/src/Garage.ApiService/Services/WinnersService.cs
@@ -20,21 +20,21 @@ public class WinnersService(
.SetTargetingKey(Guid.NewGuid().ToString())
.Build();
- var winners = await featureClient.GetBooleanValueAsync("enable-database-winners", false, evaluationContext)
- ? await GetAllDatabaseWinnersAsync()
- : await GetAllJsonWinnersAsync();
-
var count = await featureClient.GetIntegerDetailsAsync("winners-count", 5, evaluationContext);
- return winners.Take(count.Value);
+ return await featureClient.GetBooleanValueAsync("enable-database-winners", false, evaluationContext)
+ ? await GetAllDatabaseWinnersAsync(count.Value)
+ : await GetAllJsonWinnersAsync(count.Value)
... (truncated)