This is an automated email from the ASF dual-hosted git repository.
maciej pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/master by this push:
new bdf0b2e3f feat(csharp): implement get_snapshot method in C# SDK (#2698)
bdf0b2e3f is described below
commit bdf0b2e3fda3cde5d065a1768ea98b965afcc780
Author: Atharva Lade <[email protected]>
AuthorDate: Sun Feb 8 13:11:57 2026 -0600
feat(csharp): implement get_snapshot method in C# SDK (#2698)
---
.../Iggy_SDK.Tests.Integration/SystemTests.cs | 17 +++++++++++++++
.../csharp/Iggy_SDK/Contracts/Tcp/TcpContracts.cs | 15 +++++++++++++
.../csharp/Iggy_SDK/Enums/SnapshotCompression.cs | 12 +++++------
.../csharp/Iggy_SDK/Enums/SystemSnapshotType.cs | 14 ++++++------
foreign/csharp/Iggy_SDK/IggyClient/IIggySystem.cs | 16 ++++++++++++++
.../Implementations/HttpMessageStream.cs | 25 ++++++++++++++++++++++
.../IggyClient/Implementations/TcpMessageStream.cs | 11 ++++++++++
7 files changed, 97 insertions(+), 13 deletions(-)
diff --git a/foreign/csharp/Iggy_SDK.Tests.Integration/SystemTests.cs
b/foreign/csharp/Iggy_SDK.Tests.Integration/SystemTests.cs
index 5bb7acd78..3cc9a446c 100644
--- a/foreign/csharp/Iggy_SDK.Tests.Integration/SystemTests.cs
+++ b/foreign/csharp/Iggy_SDK.Tests.Integration/SystemTests.cs
@@ -181,6 +181,23 @@ public class SystemTests
await Should.NotThrowAsync(Fixture.Clients[protocol].PingAsync());
}
+ [Test]
+ [DependsOn(nameof(Ping_Should_Pong))]
+
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
+ public async Task GetSnapshot_Should_Return_ValidZipData(Protocol protocol)
+ {
+ var snapshot = await Fixture.Clients[protocol].GetSnapshotAsync(
+ SnapshotCompression.Deflated,
+ [SystemSnapshotType.Test]);
+
+ snapshot.ShouldNotBeNull();
+ snapshot.Length.ShouldBeGreaterThan(0);
+
+ // Verify it's a valid ZIP archive by checking the ZIP magic bytes
(PK\x03\x04)
+ snapshot[0].ShouldBe((byte)'P');
+ snapshot[1].ShouldBe((byte)'K');
+ }
+
// [Test]
// [DependsOn(nameof(Ping_Should_Pong))]
//
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
diff --git a/foreign/csharp/Iggy_SDK/Contracts/Tcp/TcpContracts.cs
b/foreign/csharp/Iggy_SDK/Contracts/Tcp/TcpContracts.cs
index 1a0da05f2..9764d196e 100644
--- a/foreign/csharp/Iggy_SDK/Contracts/Tcp/TcpContracts.cs
+++ b/foreign/csharp/Iggy_SDK/Contracts/Tcp/TcpContracts.cs
@@ -837,6 +837,21 @@ internal static class TcpContracts
};
}
+ internal static byte[] GetSnapshot(SnapshotCompression compression,
IList<SystemSnapshotType> snapshotTypes)
+ {
+ // Binary format: [compression_code: u8] [types_count: u8]
[type_code_1: u8] [type_code_2: u8] ...
+ var length = 1 + 1 + snapshotTypes.Count;
+ Span<byte> bytes = stackalloc byte[length];
+ bytes[0] = (byte)compression;
+ bytes[1] = (byte)snapshotTypes.Count;
+ for (var i = 0; i < snapshotTypes.Count; i++)
+ {
+ bytes[2 + i] = (byte)snapshotTypes[i];
+ }
+
+ return bytes.ToArray();
+ }
+
internal static byte[] DeleteOffset(Identifier streamId, Identifier
topicId, Consumer consumer, uint? partitionId)
{
Span<byte> bytes =
diff --git a/foreign/csharp/Iggy_SDK/Enums/SnapshotCompression.cs
b/foreign/csharp/Iggy_SDK/Enums/SnapshotCompression.cs
index dcb853556..b3a475a1c 100644
--- a/foreign/csharp/Iggy_SDK/Enums/SnapshotCompression.cs
+++ b/foreign/csharp/Iggy_SDK/Enums/SnapshotCompression.cs
@@ -23,20 +23,20 @@ namespace Apache.Iggy.Enums;
public enum SnapshotCompression
{
/// Store the file as is
- Stored,
+ Stored = 1,
/// Compress the file using Deflate
- Deflated,
+ Deflated = 2,
/// Compress the file using BZIP2
- Bzip2,
+ Bzip2 = 3,
/// Compress the file using ZStandard
- Zstd,
+ Zstd = 4,
/// Compress the file using LZMA
- Lzma,
+ Lzma = 5,
/// Compress the file using XZ
- Xz
+ Xz = 6
}
diff --git a/foreign/csharp/Iggy_SDK/Enums/SystemSnapshotType.cs
b/foreign/csharp/Iggy_SDK/Enums/SystemSnapshotType.cs
index 51c0e9db0..56c1b28d3 100644
--- a/foreign/csharp/Iggy_SDK/Enums/SystemSnapshotType.cs
+++ b/foreign/csharp/Iggy_SDK/Enums/SystemSnapshotType.cs
@@ -23,23 +23,23 @@ namespace Apache.Iggy.Enums;
public enum SystemSnapshotType
{
/// Overview of the filesystem.
- FilesystemOverview,
+ FilesystemOverview = 1,
/// List of currently running processes.
- ProcessList,
+ ProcessList = 2,
/// Resource usage statistics of the system.
- ResourceUsage,
+ ResourceUsage = 3,
/// Test snapshot type for development purposes.
- Test,
+ Test = 4,
/// Server logs
- ServerLogs,
+ ServerLogs = 5,
/// Server configuration
- ServerConfig,
+ ServerConfig = 6,
/// Everything
- All
+ All = 100
}
diff --git a/foreign/csharp/Iggy_SDK/IggyClient/IIggySystem.cs
b/foreign/csharp/Iggy_SDK/IggyClient/IIggySystem.cs
index 79c4460e1..32acfcec8 100644
--- a/foreign/csharp/Iggy_SDK/IggyClient/IIggySystem.cs
+++ b/foreign/csharp/Iggy_SDK/IggyClient/IIggySystem.cs
@@ -16,6 +16,7 @@
// under the License.
using Apache.Iggy.Contracts;
+using Apache.Iggy.Enums;
namespace Apache.Iggy.IggyClient;
@@ -90,4 +91,19 @@ public interface IIggySystem
/// <param name="token">The cancellation token to cancel the
operation.</param>
/// <returns>A task representing the asynchronous operation.</returns>
Task PingAsync(CancellationToken token = default);
+
+ /// <summary>
+ /// Captures and packages the current system state as a snapshot.
+ /// </summary>
+ /// <remarks>
+ /// The snapshot is returned as raw bytes of a ZIP archive. The
contents depend on
+ /// the requested snapshot types (filesystem overview, process list,
resource usage, etc.).
+ /// Authentication is required.
+ /// </remarks>
+ /// <param name="compression">The compression method to use for the
snapshot archive.</param>
+ /// <param name="snapshotTypes">The types of system information to include
in the snapshot.</param>
+ /// <param name="token">The cancellation token to cancel the
operation.</param>
+ /// <returns>A task that represents the asynchronous operation and returns
the snapshot as raw bytes of a ZIP archive.</returns>
+ Task<byte[]> GetSnapshotAsync(SnapshotCompression compression,
IList<SystemSnapshotType> snapshotTypes,
+ CancellationToken token = default);
}
diff --git
a/foreign/csharp/Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs
b/foreign/csharp/Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs
index 73db25c1d..fc293a39f 100644
--- a/foreign/csharp/Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs
+++ b/foreign/csharp/Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs
@@ -455,6 +455,31 @@ public class HttpMessageStream : IIggyClient
}
}
+ /// <inheritdoc />
+ public async Task<byte[]> GetSnapshotAsync(SnapshotCompression compression,
+ IList<SystemSnapshotType> snapshotTypes, CancellationToken token =
default)
+ {
+ // Rust serde uses default derive (PascalCase) for these enums, not
snake_case.
+ // We use .ToString() to produce PascalCase names matching Rust's
serde expectations.
+ var request = new
+ {
+ compression = compression.ToString(),
+ snapshot_types = snapshotTypes.Select(t => t.ToString()).ToList()
+ };
+ var json = JsonSerializer.Serialize(request, _jsonSerializerOptions);
+ var data = new StringContent(json, Encoding.UTF8, "application/json");
+
+ var response = await _httpClient.PostAsync("/snapshot", data, token);
+
+ if (response.IsSuccessStatusCode)
+ {
+ return await response.Content.ReadAsByteArrayAsync(token);
+ }
+
+ await HandleResponseAsync(response);
+ return [];
+ }
+
/// <inheritdoc />
public Task ConnectAsync(CancellationToken token = default)
{
diff --git
a/foreign/csharp/Iggy_SDK/IggyClient/Implementations/TcpMessageStream.cs
b/foreign/csharp/Iggy_SDK/IggyClient/Implementations/TcpMessageStream.cs
index 1d7c665a6..a952338f2 100644
--- a/foreign/csharp/Iggy_SDK/IggyClient/Implementations/TcpMessageStream.cs
+++ b/foreign/csharp/Iggy_SDK/IggyClient/Implementations/TcpMessageStream.cs
@@ -535,6 +535,17 @@ public sealed class TcpMessageStream : IIggyClient
await SendWithResponseAsync(payload, token);
}
+ /// <inheritdoc />
+ public async Task<byte[]> GetSnapshotAsync(SnapshotCompression compression,
+ IList<SystemSnapshotType> snapshotTypes, CancellationToken token =
default)
+ {
+ var message = TcpContracts.GetSnapshot(compression, snapshotTypes);
+ var payload = new byte[4 + BufferSizes.INITIAL_BYTES_LENGTH +
message.Length];
+ TcpMessageStreamHelpers.CreatePayload(payload, message,
CommandCodes.GET_SNAPSHOT_CODE);
+
+ return await SendWithResponseAsync(payload, token);
+ }
+
/// <inheritdoc />
public async Task ConnectAsync(CancellationToken token = default)
{