diff --git a/src/NATS.Client.KeyValueStore/INatsKVContext.cs b/src/NATS.Client.KeyValueStore/INatsKVContext.cs
index cdf371037..2ceb0b3e7 100644
--- a/src/NATS.Client.KeyValueStore/INatsKVContext.cs
+++ b/src/NATS.Client.KeyValueStore/INatsKVContext.cs
@@ -52,6 +52,17 @@ public interface INatsKVContext
/// Server responded with an error.
ValueTask UpdateStoreAsync(NatsKVConfig config, CancellationToken cancellationToken = default);
+ ///
+ /// Creates a new Key Value Store if it doesn't exist or update if the store already exists.
+ ///
+ /// Key Value Store configuration
+ /// A used to cancel the API call.
+ /// Key Value Store
+ /// There was an issue with configuration
+ /// There was an issue retrieving the response.
+ /// Server responded with an error.
+ ValueTask CreateOrUpdateStoreAsync(NatsKVConfig config, CancellationToken cancellationToken = default);
+
///
/// Delete a Key Value Store
///
diff --git a/src/NATS.Client.KeyValueStore/NatsKVContext.cs b/src/NATS.Client.KeyValueStore/NatsKVContext.cs
index 9cbbdbc6b..646f03b01 100644
--- a/src/NATS.Client.KeyValueStore/NatsKVContext.cs
+++ b/src/NATS.Client.KeyValueStore/NatsKVContext.cs
@@ -76,6 +76,18 @@ public async ValueTask UpdateStoreAsync(NatsKVConfig config, Cance
return new NatsKVStore(config.Bucket, JetStreamContext, stream);
}
+ ///
+ public async ValueTask CreateOrUpdateStoreAsync(NatsKVConfig config, CancellationToken cancellationToken = default)
+ {
+ ValidateBucketName(config.Bucket);
+
+ var streamConfig = NatsKVContext.CreateStreamConfig(config);
+
+ var stream = await JetStreamContext.CreateOrUpdateStreamAsync(streamConfig, cancellationToken);
+
+ return new NatsKVStore(config.Bucket, JetStreamContext, stream);
+ }
+
///
public ValueTask DeleteStoreAsync(string bucket, CancellationToken cancellationToken = default)
{
diff --git a/tests/NATS.Client.KeyValueStore.Tests/KeyValueContextTest.cs b/tests/NATS.Client.KeyValueStore.Tests/KeyValueContextTest.cs
index 65d941ac1..438229d34 100644
--- a/tests/NATS.Client.KeyValueStore.Tests/KeyValueContextTest.cs
+++ b/tests/NATS.Client.KeyValueStore.Tests/KeyValueContextTest.cs
@@ -46,6 +46,54 @@ public async Task Update_store_test()
updatedStatus.Info.Config.Description.Should().Be(natsKVConfig.Description);
}
+ [Fact]
+ public async Task Create_store_via_create_or_update_store_test()
+ {
+ const string expectedBuketName = "kv1";
+ const string expectedDescription = "description";
+
+ var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
+ var cancellationToken = cts.Token;
+
+ await using var server = NatsServer.StartJS();
+ await using var nats = server.CreateClientConnection();
+
+ var js = new NatsJSContext(nats);
+ var kv = new NatsKVContext(js);
+
+ var natsKVConfig = new NatsKVConfig(expectedBuketName) { Description = expectedDescription };
+ var store = await kv.CreateOrUpdateStoreAsync(natsKVConfig, cancellationToken);
+ var status = await store.GetStatusAsync(cancellationToken);
+
+ status.Bucket.Should().Be(expectedBuketName);
+ status.Info.Config.Description.Should().Be(expectedDescription);
+ }
+
+ [Fact]
+ public async Task Update_store_via_create_or_update_store_test()
+ {
+ var buketName = "kv1";
+ var expectedDescription = "Updated description";
+
+ var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
+ var cancellationToken = cts.Token;
+
+ await using var server = NatsServer.StartJS();
+ await using var nats = server.CreateClientConnection();
+
+ var js = new NatsJSContext(nats);
+ var kv = new NatsKVContext(js);
+
+ var store = await kv.CreateStoreAsync(buketName, cancellationToken);
+ var status = await store.GetStatusAsync(cancellationToken);
+ status.Info.Config.Description.Should().BeNull();
+
+ var natsKVConfig = new NatsKVConfig(buketName) { Description = expectedDescription };
+ await kv.CreateOrUpdateStoreAsync(natsKVConfig, cancellationToken);
+ var updatedStatus = await store.GetStatusAsync(cancellationToken);
+ updatedStatus.Info.Config.Description.Should().Be(natsKVConfig.Description);
+ }
+
[Fact]
public async Task Delete_store_test()
{