diff --git a/MeetingAssistant.Tests/WorkflowRulesEditorTests.cs b/MeetingAssistant.Tests/WorkflowRulesEditorTests.cs index 29d063c..5e1dda7 100644 --- a/MeetingAssistant.Tests/WorkflowRulesEditorTests.cs +++ b/MeetingAssistant.Tests/WorkflowRulesEditorTests.cs @@ -155,15 +155,18 @@ public sealed class WorkflowRulesEditorTests new MeetingAssistantOptions(), logDirectory: root); + using var provider = new MeetingAssistantFileLoggerProvider(root); + provider.CreateLogger("Test").LogInformation("locked needle"); + var tail = await tools.ReadLogs(tail: 2); - var range = await tools.ReadLogs(from: 2, to: 2); + var range = await tools.ReadLogs(from: 1, to: 1); var search = await tools.SearchLogs("needle"); - Assert.DoesNotContain("first line", tail); - Assert.Contains("second needle", tail); - Assert.Equal("second needle", range.Trim()); - Assert.Contains("meeting-assistant.log:2 second needle", search); - Assert.Contains("meeting-assistant.log.1:1 rotated needle", search); + Assert.Contains("locked needle", tail); + Assert.Contains("locked needle", search); + Assert.Contains("locked needle", range); + Assert.Contains("meeting-assistant.log:1", search); + Assert.Contains("meeting-assistant.log.2:1 rotated needle", search); } [Fact] diff --git a/MeetingAssistant/AgentFileToolContent.cs b/MeetingAssistant/AgentFileToolContent.cs index cd63437..ff20a3b 100644 --- a/MeetingAssistant/AgentFileToolContent.cs +++ b/MeetingAssistant/AgentFileToolContent.cs @@ -189,7 +189,7 @@ internal static class AgentFileToolContent var limit = Math.Clamp(maxMatches, 1, 1000); foreach (var source in sources) { - var lines = File.ReadAllLines(source.Path); + var lines = ReadAllLinesShared(source.Path); for (var index = 0; index < lines.Length; index++) { if (regex.IsMatch(lines[index])) @@ -211,6 +211,30 @@ internal static class AgentFileToolContent return ""; } } + + public static async Task ReadAllTextSharedAsync(string path) + { + await using var stream = new FileStream( + path, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite | FileShare.Delete, + bufferSize: 4096, + useAsync: true); + using var reader = new StreamReader(stream); + return await reader.ReadToEndAsync(); + } + + private static string[] ReadAllLinesShared(string path) + { + using var stream = new FileStream( + path, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite | FileShare.Delete); + using var reader = new StreamReader(stream); + return SplitLines(reader.ReadToEnd()).ToArray(); + } } internal sealed record AgentFileSearchSource(string Path, string DisplayPath); diff --git a/MeetingAssistant/Workflow/WorkflowRulesEditorTools.cs b/MeetingAssistant/Workflow/WorkflowRulesEditorTools.cs index 8224958..d7dcc13 100644 --- a/MeetingAssistant/Workflow/WorkflowRulesEditorTools.cs +++ b/MeetingAssistant/Workflow/WorkflowRulesEditorTools.cs @@ -166,7 +166,7 @@ public sealed class WorkflowRulesEditorTools return $"Log file was not found: {logFile ?? MeetingAssistantLogFiles.CurrentLogFileName}"; } - var content = await File.ReadAllTextAsync(path); + var content = await AgentFileToolContent.ReadAllTextSharedAsync(path); if (from.HasValue || to.HasValue) { return AgentFileToolContent.ReadLines(content, from, to);