Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/NATS.Client.ObjectStore/Models/ObjectMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ public record ObjectMetadata
public string? Nuid { get; set; }

/// <summary>
/// Max chunk size
/// The size of the object in bytes.
/// It only includes the size of the object itself, not the metadata.
/// </summary>
[JsonPropertyName("size")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int Size { get; set; }
public ulong Size { get; set; }

/// <summary>
/// Modified timestamp
Expand All @@ -53,7 +54,7 @@ public record ObjectMetadata
/// </summary>
[JsonPropertyName("chunks")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int Chunks { get; set; }
public uint Chunks { get; set; }

@mtmk mtmk Oct 4, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turns out this one is not align with the spec either (ADR-20)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have long (int 64) in both java and .net v1. ADR has uint32 so I think this is fine.


/// <summary>
/// Object digest
Expand Down
10 changes: 5 additions & 5 deletions src/NATS.Client.ObjectStore/NatsObjStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public async ValueTask<ObjectMetadata> GetAsync(string key, Stream stream, bool

string digest;
var chunks = 0;
var size = 0;
ulong size = 0;
using (var sha256 = SHA256.Create())
{
#if NETSTANDARD2_0
Expand All @@ -107,7 +107,7 @@ public async ValueTask<ObjectMetadata> GetAsync(string key, Stream stream, bool
{
using var memoryOwner = msg.Data;
chunks++;
size += memoryOwner.Memory.Length;
size += (ulong)memoryOwner.Memory.Length;
#if NETSTANDARD2_0
var segment = memoryOwner.DangerousGetArray();
await hashedStream.WriteAsync(segment.Array, segment.Offset, segment.Count, cancellationToken);
Expand Down Expand Up @@ -182,8 +182,8 @@ public async ValueTask<ObjectMetadata> PutAsync(ObjectMetadata meta, Stream stre
meta.Options.MaxChunkSize = DefaultChunkSize;
}

var size = 0;
var chunks = 0;
ulong size = 0;
uint chunks = 0;
var chunkSize = meta.Options.MaxChunkSize.Value;

string digest;
Expand Down Expand Up @@ -250,7 +250,7 @@ public async ValueTask<ObjectMetadata> PutAsync(ObjectMetadata meta, Stream stre

if (currentChunkSize > 0)
{
size += currentChunkSize;
size += (ulong)currentChunkSize;
chunks++;
}

Expand Down
45 changes: 40 additions & 5 deletions tests/NATS.Client.ObjectStore.Tests/ObjectStoreTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@

Assert.Equal($"SHA-256={sha}", data.Digest);
Assert.Equal(chunks, data.Chunks);
Assert.Equal(size, data.Size);
Assert.Equal((ulong)size, data.Size);
}

// buffer with smaller last chunk
Expand All @@ -102,7 +102,7 @@

Assert.Equal($"SHA-256={sha}", data.Digest);
Assert.Equal(chunks, data.Chunks);
Assert.Equal(size, data.Size);
Assert.Equal((ulong)size, data.Size);
}

// Object name checks
Expand Down Expand Up @@ -195,7 +195,7 @@
await store.PutAsync("k1", new byte[] { 65, 66, 67 }, cancellationToken);

var info = await store.GetInfoAsync("k1", cancellationToken: cancellationToken);
Assert.Equal(3, info.Size);
Assert.Equal(3UL, info.Size);

var bytes = await store.GetBytesAsync("k1", cancellationToken);
Assert.Equal(bytes, new byte[] { 65, 66, 67 });
Expand All @@ -207,8 +207,8 @@

var info2 = await store.GetInfoAsync("k1", showDeleted: true, cancellationToken: cancellationToken);
Assert.True(info2.Deleted);
Assert.Equal(0, info2.Size);
Assert.Equal(0, info2.Chunks);
Assert.Equal(0UL, info2.Size);
Assert.Equal(0U, info2.Chunks);
Assert.Equal(string.Empty, info2.Digest);

// Put again
Expand Down Expand Up @@ -622,4 +622,39 @@
await b1.GetBytesAsync("name1", cancellationToken: cancellationToken);
});
}

[Fact]
public async Task Metadata_field_types_match_spec()
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var cancellationToken = cts.Token;

await using var server = await NatsServerProcess.StartAsync();
await using var nats = new NatsConnection(new NatsOpts { Url = server.Url });
var js = new NatsJSContext(nats);
var obj = new NatsObjContext(js);

var store = await obj.CreateObjectStoreAsync(new NatsObjConfig("b1"), cancellationToken);

// Test that Size property is ulong (uint64 in NATS spec)
var metadata = new ObjectMetadata { Name = "test" };
metadata.Size = ulong.MaxValue; // Should compile without error
Assert.Equal(18446744073709551615UL, metadata.Size);

// Test that Chunks property is uint (uint32 in NATS spec)
metadata.Chunks = uint.MaxValue; // Should compile without error
Assert.Equal(4294967295U, metadata.Chunks);

// Test with actual object metadata from store
await store.PutAsync("k1", new byte[] { 1, 2, 3 }, cancellationToken: cancellationToken);
var info = await store.GetInfoAsync("k1", cancellationToken: cancellationToken);

// Verify Size is ulong
ulong size = info.Size; // Should compile without error

Check warning on line 653 in tests/NATS.Client.ObjectStore.Tests/ObjectStoreTest.cs

View workflow job for this annotation

GitHub Actions / check

use 'var' instead of explicit type

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since using large files won't be possible I just check the type here.

Assert.Equal(3UL, size);

// Verify Chunks is uint
uint chunks = info.Chunks; // Should compile without error

Check warning on line 657 in tests/NATS.Client.ObjectStore.Tests/ObjectStoreTest.cs

View workflow job for this annotation

GitHub Actions / check

use 'var' instead of explicit type
Assert.Equal(1U, chunks);
}
}
2 changes: 1 addition & 1 deletion tests/NATS.Client.ObjectStore.Tests/WatcherTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public async Task Watcher_test()
{
count++;
signal.Pulse();
Assert.Equal(count, info.Size);
Assert.Equal((ulong)count, info.Size);
if (count == 3)
break;
}
Expand Down
Loading