Skip to content

Commit fd1bfbf

Browse files
Refactor CslaCodeTool to use async file and search ops
Refactored CslaCodeTool methods to use asynchronous programming patterns for file I/O and search operations. Converted key methods (PerformWordSearch, PerformSemanticSearch, FindVersionSpecificFiles) to async versions, updated file reads to use File.ReadAllTextAsync, and wrapped Directory.GetFiles in Task.Run. Updated all call sites to await async methods, improving scalability and responsiveness for concurrent and high-load scenarios.
1 parent 7fd9f17 commit fd1bfbf

1 file changed

Lines changed: 20 additions & 16 deletions

File tree

csla-mcp-server/Tools/CslaCodeTool.cs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,14 @@ public async Task<string> Search(
138138
}
139139

140140
// Create tasks for parallel execution
141-
var wordSearchTask = Task.Run(() => PerformWordSearch(allFiles, searchTerms, version.Value));
142-
var semanticSearchTask = Task.Run(() => PerformSemanticSearch(message, version));
141+
var wordSearchTask = PerformWordSearchAsync(allFiles, searchTerms, version.Value);
142+
var semanticSearchTask = PerformSemanticSearchAsync(message, version);
143143

144144
// Wait for both tasks to complete
145-
Task.WaitAll(wordSearchTask, semanticSearchTask);
145+
await Task.WhenAll(wordSearchTask, semanticSearchTask);
146146

147-
var wordMatches = wordSearchTask.Result;
148-
var semanticMatches = semanticSearchTask.Result;
147+
var wordMatches = await wordSearchTask;
148+
var semanticMatches = await semanticSearchTask;
149149

150150
// Create consolidated results
151151
var consolidatedResults = ConsolidateSearchResults(semanticMatches, wordMatches);
@@ -225,7 +225,7 @@ private List<ConsolidatedSearchResult> ConsolidateSearchResults(List<SemanticMat
225225
return sortedResults;
226226
}
227227

228-
private List<SearchResult> PerformWordSearch(IEnumerable<string> allFiles, List<string> searchTerms, int version)
228+
private async Task<List<SearchResult>> PerformWordSearchAsync(IEnumerable<string> allFiles, List<string> searchTerms, int version)
229229
{
230230
logger.LogInformation("[CslaCodeTool.PerformWordSearch] Starting word search for version {Version}", version);
231231
var results = new List<SearchResult>();
@@ -243,7 +243,7 @@ private List<SearchResult> PerformWordSearch(IEnumerable<string> allFiles, List<
243243
if (!isCommon && !isMatchingVersion)
244244
continue;
245245

246-
var content = File.ReadAllText(file);
246+
var content = await File.ReadAllTextAsync(file);
247247
// Document length as number of word tokens
248248
var docLength = GetDocumentLength(content);
249249
candidateDocs.Add((relativePath.Replace("\\", "/"), content, docLength));
@@ -365,15 +365,15 @@ private List<SearchResult> NormalizeWordSearchResults(List<SearchResult> results
365365
return normalizedResults;
366366
}
367367

368-
private List<SemanticMatch> PerformSemanticSearch(string message, int? version)
368+
private async Task<List<SemanticMatch>> PerformSemanticSearchAsync(string message, int? version)
369369
{
370370
logger.LogInformation("[CslaCodeTool.PerformSemanticSearch] Starting semantic search for version {Version}", version);
371371
var semanticMatches = new List<SemanticMatch>();
372372

373373
if (VectorStore != null && VectorStore.IsReady())
374374
{
375375
logger.LogInformation("[CslaCodeTool.PerformSemanticSearch] Performing semantic search");
376-
var semanticResults = VectorStore.SearchAsync(message, version, topK: 10).GetAwaiter().GetResult();
376+
var semanticResults = await VectorStore.SearchAsync(message, version, topK: 10);
377377
semanticMatches = semanticResults.Select(r => new SemanticMatch
378378
{
379379
FileName = r.FileName,
@@ -493,15 +493,15 @@ private static int CountWordOccurrences(string content, string searchTerm)
493493

494494
if (File.Exists(filePath))
495495
{
496-
var content = File.ReadAllText(filePath);
496+
var content = await File.ReadAllTextAsync(filePath);
497497
logger.LogInformation("[CslaCodeTool.Fetch] Successfully read file '{FileName}' ({Length} characters)", fileName, content.Length);
498498
return content;
499499
}
500500
else
501501
{
502502
// File not found at exact path - check if there are version-specific alternatives
503503
var fileNameOnly = Path.GetFileName(fileName);
504-
var matchingFiles = FindVersionSpecificFiles(fileNameOnly);
504+
var matchingFiles = await FindVersionSpecificFilesAsync(fileNameOnly);
505505

506506
if (matchingFiles.Count > 1)
507507
{
@@ -518,7 +518,7 @@ private static int CountWordOccurrences(string content, string searchTerm)
518518
{
519519
// Single match found in a version-specific folder
520520
var matchedFilePath = Path.Combine(CodeSamplesPath, matchingFiles[0]);
521-
var content = File.ReadAllText(matchedFilePath);
521+
var content = await File.ReadAllTextAsync(matchedFilePath);
522522
logger.LogInformation("[CslaCodeTool.Fetch] Found single version-specific file '{FileName}', returning content ({Length} characters)", matchingFiles[0], content.Length);
523523
return content;
524524
}
@@ -551,16 +551,20 @@ private static int CountWordOccurrences(string content, string searchTerm)
551551
/// Searches for files with the given name across all version-specific subdirectories.
552552
/// Returns a list of relative paths (e.g., "v10/Command.md", "v9/Command.md").
553553
/// </summary>
554-
private List<string> FindVersionSpecificFiles(string fileName)
554+
private async Task<List<string>> FindVersionSpecificFilesAsync(string fileName)
555555
{
556556
var results = new List<string>();
557557

558558
try
559559
{
560560
// Get all .cs and .md files in the code samples directory
561-
var allFiles = Directory.GetFiles(CodeSamplesPath, "*.*", SearchOption.AllDirectories)
562-
.Where(f => f.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) ||
563-
f.EndsWith(".md", StringComparison.OrdinalIgnoreCase));
561+
// Note: Directory.GetFiles is synchronous and doesn't have an async alternative
562+
// Running on thread pool to avoid blocking
563+
var allFiles = await Task.Run(() =>
564+
Directory.GetFiles(CodeSamplesPath, "*.*", SearchOption.AllDirectories)
565+
.Where(f => f.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) ||
566+
f.EndsWith(".md", StringComparison.OrdinalIgnoreCase))
567+
.ToList());
564568

565569
// Find files that match the requested file name
566570
foreach (var file in allFiles)

0 commit comments

Comments
 (0)