Skip to content

Commit b6ef935

Browse files
add new possibility to turn off the RAG resolve by prompt
fix RAG for Playwright
1 parent 07341d0 commit b6ef935

File tree

23 files changed

+641
-272
lines changed

23 files changed

+641
-272
lines changed

Bellatrix.LLM/services/LocatorCacheService.cs

Lines changed: 124 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -14,113 +14,182 @@
1414
// <note>This file is part of an academic research project exploring autonomous test agents using LLMs and Semantic Kernel.
1515
// The architecture and agent logic are original contributions by Anton Angelov, forming the foundation for a PhD dissertation.
1616
// Please cite or credit appropriately if reusing in academic or commercial work.</note>
17-
1817
using Bellatrix.KeyVault;
1918
using Bellatrix.LLM.Cache;
2019
using Bellatrix.LLM.Settings;
2120
using System.Collections.Concurrent;
2221

2322
namespace Bellatrix.LLM;
24-
25-
/// <summary>
26-
/// A shared locator cache service for AI-assisted test automation.
27-
/// It stores and retrieves XPath selectors for natural language instructions,
28-
/// scoped by application location (e.g., URL or screen ID).
29-
/// Useful for enabling cross-platform support (Web, Android, iOS, Desktop).
30-
/// </summary>
3123
public static class LocatorCacheService
3224
{
25+
// In-memory cache for selectors. Key is a composite: {location}|{instruction}
3326
private static readonly ConcurrentDictionary<string, string> _cache = new();
27+
28+
// Project name (to support scoping and multi-project setups)
3429
private static readonly string _project;
30+
31+
// EF DbContext for persistent locator cache (can be null if DB unavailable)
3532
private static readonly LocatorCacheDbContext _db;
3633

34+
// Flag that disables DB calls if connection fails, so tests never fail due to DB outage
35+
private static bool _dbAvailable = true;
36+
37+
// Static constructor runs once on first use. Attempts to initialize cache DB and fill in-memory cache.
3738
static LocatorCacheService()
3839
{
39-
var settings = ConfigurationService.GetSection<LargeLanguageModelsSettings>();
40-
var connectionString = SecretsResolver.GetSecret(() => settings.LocalCacheConnectionString);
41-
_db = new LocatorCacheDbContext(connectionString);
42-
_project = settings.LocalCacheProjectName;
43-
44-
var entries = _db.LocatorCache
45-
.Where(x => x.Project == _project)
46-
.ToList();
47-
48-
foreach (var entry in entries)
40+
try
41+
{
42+
// Read settings and secrets for DB connection
43+
var settings = ConfigurationService.GetSection<LargeLanguageModelsSettings>();
44+
var connectionString = SecretsResolver.GetSecret(() => settings.LocalCacheConnectionString);
45+
_db = new LocatorCacheDbContext(connectionString);
46+
_project = settings.LocalCacheProjectName;
47+
48+
// Read all entries from DB for this project and preload in-memory cache
49+
var entries = _db.LocatorCache
50+
.Where(x => x.Project == _project)
51+
.ToList();
52+
53+
foreach (var entry in entries)
54+
{
55+
_cache.TryAdd($"{entry.AppLocation}|{entry.Instruction}", entry.XPath);
56+
}
57+
}
58+
catch (Exception ex)
4959
{
50-
_cache.TryAdd($"{entry.AppLocation}|{entry.Instruction}", entry.XPath);
60+
_dbAvailable = false;
61+
// If DB is down, only warn; continue using in-memory cache (never fail test)
62+
Logger.LogWarning($"⚠️ WARNING! [LocatorCacheService] Cache DB unavailable. Running in in-memory mode. Details: {ex.Message}");
5163
}
5264
}
5365

5466
/// <summary>
55-
/// Attempts to retrieve a cached XPath for the given instruction and location.
67+
/// Retrieves a cached XPath selector (from in-memory cache only).
68+
/// DB is not queried at runtime for reads; only at startup.
5669
/// </summary>
57-
/// <param name="location">The app location (URL, screen ID, etc.)</param>
58-
/// <param name="instruction">The natural language instruction used for element lookup.</param>
59-
/// <returns>The XPath selector if cached, otherwise null.</returns>
6070
public static string TryGetCached(string location, string instruction)
6171
{
6272
var key = $"{location}|{instruction}";
6373
return _cache.TryGetValue(key, out var xpath) ? xpath : null;
6474
}
6575

6676
/// <summary>
67-
/// Removes the cached entry (if any) for the given instruction and location.
77+
/// Removes an entry from both in-memory cache and DB (if available).
78+
/// If DB is down, only affects in-memory cache and logs warning.
6879
/// </summary>
69-
/// <param name="location">The app location.</param>
70-
/// <param name="instruction">The instruction key to remove.</param>
7180
public static void Remove(string location, string instruction)
7281
{
7382
var key = $"{location}|{instruction}";
7483
_cache.TryRemove(key, out _);
7584

76-
var dbEntry = _db.LocatorCache.FirstOrDefault(x =>
77-
x.Project == _project && x.AppLocation == location && x.Instruction == instruction);
78-
79-
if (dbEntry != null)
85+
if (_dbAvailable)
8086
{
81-
_db.LocatorCache.Remove(dbEntry);
82-
_db.SaveChanges();
87+
try
88+
{
89+
var dbEntry = _db.LocatorCache.FirstOrDefault(x =>
90+
x.Project == _project && x.AppLocation == location && x.Instruction == instruction);
91+
92+
if (dbEntry != null)
93+
{
94+
_db.LocatorCache.Remove(dbEntry);
95+
_db.SaveChanges();
96+
}
97+
}
98+
catch (Exception ex)
99+
{
100+
_dbAvailable = false;
101+
// Logs only, does NOT throw, keeps test running
102+
Logger.LogWarning($"⚠️ WARNING! [LocatorCacheService] Failed to remove from DB. Details: {ex.Message}");
103+
}
83104
}
84105
}
85106

86107
/// <summary>
87-
/// Updates or inserts a new cached XPath selector for a given instruction and location.
108+
/// Updates or inserts a selector in the cache for a given instruction and location.
109+
/// Always updates in-memory cache, and tries to persist in DB if available.
110+
/// If DB fails, disables DB and logs warning; does NOT throw.
88111
/// </summary>
89-
/// <param name="location">The app location.</param>
90-
/// <param name="instruction">The natural language instruction used for lookup.</param>
91-
/// <param name="xpath">The XPath selector to store.</param>
92112
public static void Update(string location, string instruction, string xpath)
93113
{
94114
var key = $"{location}|{instruction}";
95115
_cache[key] = xpath;
96116

97-
var existing = _db.LocatorCache.FirstOrDefault(x =>
98-
x.Project == _project && x.AppLocation == location && x.Instruction == instruction);
99-
100-
if (existing != null)
117+
if (_dbAvailable)
101118
{
102-
existing.XPath = xpath;
103-
existing.LastValidated = DateTime.UtcNow;
104-
_db.LocatorCache.Update(existing);
119+
try
120+
{
121+
var existing = _db.LocatorCache.FirstOrDefault(x =>
122+
x.Project == _project && x.AppLocation == location && x.Instruction == instruction);
123+
124+
if (existing != null)
125+
{
126+
existing.XPath = xpath;
127+
existing.LastValidated = DateTime.UtcNow;
128+
_db.LocatorCache.Update(existing);
129+
}
130+
else
131+
{
132+
var entry = new LocatorCacheEntry
133+
{
134+
Project = _project,
135+
AppLocation = location,
136+
Instruction = instruction,
137+
XPath = xpath
138+
};
139+
_db.LocatorCache.Add(entry);
140+
}
141+
_db.SaveChanges();
142+
}
143+
catch (Exception ex)
144+
{
145+
_dbAvailable = false;
146+
Logger.LogWarning($"⚠️ WARNING! [LocatorCacheService] Failed to update DB. Details: {ex.Message}");
147+
}
105148
}
106-
else
149+
}
150+
151+
/// <summary>
152+
/// Removes all selectors for the current project from both memory and persistent storage.
153+
/// If DB is down, only clears in-memory cache.
154+
/// </summary>
155+
public static void RemoveAllLocators()
156+
{
157+
_cache.Clear();
158+
159+
if (_dbAvailable)
107160
{
108-
var entry = new LocatorCacheEntry
161+
try
109162
{
110-
Project = _project,
111-
AppLocation = location,
112-
Instruction = instruction,
113-
XPath = xpath
114-
};
115-
_db.LocatorCache.Add(entry);
163+
var allEntries = _db.LocatorCache
164+
.Where(x => x.Project == _project)
165+
.ToList();
166+
167+
if (allEntries.Count > 0)
168+
{
169+
_db.LocatorCache.RemoveRange(allEntries);
170+
_db.SaveChanges();
171+
}
172+
}
173+
catch (Exception ex)
174+
{
175+
_dbAvailable = false;
176+
Logger.LogWarning($"⚠️ WARNING! [LocatorCacheService] Failed to clear DB. Details: {ex.Message}");
177+
}
116178
}
117-
118-
_db.SaveChanges();
119179
}
120180

181+
/// <summary>
182+
/// Disposes the DB context. Logs and swallows any exceptions.
183+
/// </summary>
121184
public static void Dispose()
122185
{
123-
_db?.Dispose();
186+
try
187+
{
188+
_db?.Dispose();
189+
}
190+
catch (Exception ex)
191+
{
192+
Logger.LogWarning($"⚠️ WARNING! [LocatorCacheService] Error on dispose. Details: {ex.Message}");
193+
}
124194
}
125195
}
126-

0 commit comments

Comments
 (0)