Skip to content

Commit f173c72

Browse files
Compress for cdb output files
1 parent 857d344 commit f173c72

File tree

4 files changed

+47
-33
lines changed

4 files changed

+47
-33
lines changed

nexus_engine/nexus_engine/Internal/CdbSession.cs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Diagnostics;
2-
using System.IO.Compression;
32
using System.Text;
43

54
using Nexus.Config;
@@ -559,26 +558,21 @@ private async Task CompressCdbLogIfAvailableAsync()
559558

560559
var cdbLogFilePath = GetCdbSessionBasedLogPath(SessionId);
561560

562-
if (!File.Exists(cdbLogFilePath))
561+
if (!m_FileSystem.FileExists(cdbLogFilePath))
563562
{
564563
return;
565564
}
566565

567566
var compressedPath = $"{cdbLogFilePath}.gz";
568567

569-
if (File.Exists(compressedPath))
568+
if (m_FileSystem.FileExists(compressedPath))
570569
{
571570
return;
572571
}
573572

574-
using (var sourceStream = new FileStream(cdbLogFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
575-
using (var destinationStream = new FileStream(compressedPath, FileMode.Create, FileAccess.Write, FileShare.None))
576-
using (var gzipStream = new GZipStream(destinationStream, CompressionLevel.Optimal))
577-
{
578-
await sourceStream.CopyToAsync(gzipStream).ConfigureAwait(false);
579-
}
573+
await m_FileSystem.CompressToGZipAsync(cdbLogFilePath, compressedPath).ConfigureAwait(false);
580574

581-
File.Delete(cdbLogFilePath);
575+
m_FileSystem.DeleteFile(cdbLogFilePath);
582576

583577
m_Logger.Info("Compressed CDB log for session {SessionId} to {CompressedPath}", SessionId, compressedPath);
584578
}

nexus_external_apis/FileSystem/FileSystem.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.IO.Compression;
2+
13
namespace Nexus.External.Apis.FileSystem;
24

35
/// <summary>
@@ -207,4 +209,19 @@ public void ProbeRead(string path)
207209
Span<byte> buffer = stackalloc byte[1];
208210
_ = stream.Read(buffer);
209211
}
212+
213+
/// <summary>
214+
/// Compresses the specified source file into GZip format at the specified destination path.
215+
/// </summary>
216+
/// <param name="sourceFilePath">The path of the file to compress.</param>
217+
/// <param name="destinationFilePath">The path where the compressed file should be created.</param>
218+
/// <param name="cancellationToken">The cancellation token for the operation.</param>
219+
/// <returns>A task representing the asynchronous compression operation.</returns>
220+
public async Task CompressToGZipAsync(string sourceFilePath, string destinationFilePath, CancellationToken cancellationToken = default)
221+
{
222+
using var sourceStream = File.OpenRead(sourceFilePath);
223+
using var destinationStream = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
224+
using var gzipStream = new GZipStream(destinationStream, CompressionLevel.Optimal);
225+
await sourceStream.CopyToAsync(gzipStream, cancellationToken).ConfigureAwait(false);
226+
}
210227
}

nexus_external_apis/FileSystem/IFileSystem.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,13 @@ public interface IFileSystem
145145
/// </summary>
146146
/// <param name="path">The file path to probe.</param>
147147
void ProbeRead(string path);
148+
149+
/// <summary>
150+
/// Compresses the specified source file into GZip format at the specified destination path.
151+
/// </summary>
152+
/// <param name="sourceFilePath">The path of the file to compress.</param>
153+
/// <param name="destinationFilePath">The path where the compressed file should be created.</param>
154+
/// <param name="cancellationToken">The cancellation token for the operation.</param>
155+
/// <returns>A task representing the asynchronous compression operation.</returns>
156+
Task CompressToGZipAsync(string sourceFilePath, string destinationFilePath, CancellationToken cancellationToken = default);
148157
}

unittests/nexus_engine/nexus_engine_unittests/Internal/CdbSessionTests.cs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,22 +1388,19 @@ public async Task InitializeAsync_WhenInitializationFails_DisposesSession()
13881388
}
13891389

13901390
/// <summary>
1391-
/// Verifies that disposing the session compresses the CDB log file and deletes the original log.
1391+
/// Verifies that disposing the session requests GZip compression of the CDB log file and deletes the original log via the file system abstraction.
13921392
/// </summary>
13931393
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
13941394
[Fact]
13951395
public async Task DisposeAsync_CompressesCdbLog_AndDeletesOriginalLog()
13961396
{
13971397
// Arrange
13981398
var originalConfig = LogManager.Configuration;
1399-
var tempRoot = Path.Combine(Path.GetTempPath(), "MCPNexusCdbCompressionTests", Guid.NewGuid().ToString("N"));
1400-
var logsDirectory = Path.Combine(tempRoot, "Logs");
1401-
_ = Directory.CreateDirectory(logsDirectory);
14021399

14031400
try
14041401
{
14051402
var config = new LoggingConfiguration();
1406-
var mainLogPath = Path.Combine(logsDirectory, "main.log");
1403+
const string mainLogPath = "C:\\logs\\main.log";
14071404
var fileTarget = new FileTarget("mainFile")
14081405
{
14091406
FileName = mainLogPath,
@@ -1412,42 +1409,39 @@ public async Task DisposeAsync_CompressesCdbLog_AndDeletesOriginalLog()
14121409
config.AddRuleForAllLevels(fileTarget);
14131410
LogManager.Configuration = config;
14141411

1415-
var accessor = new CdbSessionTestAccessor(m_Settings.Object, m_MockFileSystem.Object, m_MockProcessManager.Object);
1412+
var fileSystem = new Mock<IFileSystem>();
1413+
var processManager = m_MockProcessManager;
1414+
1415+
var accessor = new CdbSessionTestAccessor(m_Settings.Object, fileSystem.Object, processManager.Object);
14161416

14171417
var sessionId = "session-compress";
14181418
var sessionIdProperty = typeof(CdbSession).GetProperty("SessionId", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
14191419
sessionIdProperty!.SetValue(accessor, sessionId);
14201420

14211421
var getLogPathMethod = typeof(CdbSession).GetMethod("GetCdbSessionBasedLogPath", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
14221422
var logPath = (string)getLogPathMethod!.Invoke(accessor, new object[] { sessionId })!;
1423+
var compressedPath = $"{logPath}.gz";
14231424

1424-
var logDirectory = Path.GetDirectoryName(logPath);
1425-
if (!string.IsNullOrEmpty(logDirectory))
1426-
{
1427-
_ = Directory.CreateDirectory(logDirectory);
1428-
}
1425+
_ = fileSystem.Setup(fs => fs.FileExists(logPath))
1426+
.Returns(true);
1427+
_ = fileSystem.Setup(fs => fs.FileExists(compressedPath))
1428+
.Returns(false);
1429+
1430+
_ = fileSystem.Setup(fs => fs.CompressToGZipAsync(logPath, compressedPath, It.IsAny<CancellationToken>()))
1431+
.Returns(Task.CompletedTask);
14291432

1430-
const string logContent = "cdb log content";
1431-
File.WriteAllText(logPath, logContent);
1433+
_ = fileSystem.Setup(fs => fs.DeleteFile(logPath));
14321434

14331435
// Act
14341436
await accessor.DisposeAsync();
14351437

14361438
// Assert
1437-
var compressedPath = $"{logPath}.gz";
1438-
_ = File.Exists(logPath).Should().BeFalse();
1439-
_ = File.Exists(compressedPath).Should().BeTrue();
1440-
var compressedFileInfo = new FileInfo(compressedPath);
1441-
_ = compressedFileInfo.Length.Should().BeGreaterThan(0);
1439+
fileSystem.Verify(fs => fs.CompressToGZipAsync(logPath, compressedPath, It.IsAny<CancellationToken>()), Times.Once);
1440+
fileSystem.Verify(fs => fs.DeleteFile(logPath), Times.Once);
14421441
}
14431442
finally
14441443
{
14451444
LogManager.Configuration = originalConfig;
1446-
1447-
if (Directory.Exists(tempRoot))
1448-
{
1449-
Directory.Delete(tempRoot, true);
1450-
}
14511445
}
14521446
}
14531447
}

0 commit comments

Comments
 (0)