Skip to content

Commit

Permalink
Merge branch 'main' into obj-compat-tests
Browse files Browse the repository at this point in the history
# Conflicts:
#	NATS.Client.sln
  • Loading branch information
mtmk committed Oct 30, 2023
2 parents 957ba86 + f26d41c commit b9a99d2
Show file tree
Hide file tree
Showing 65 changed files with 2,955 additions and 312 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ jobs:
- name: Test Object Store
run: dotnet test -c Debug --no-build --logger:"console;verbosity=normal" tests/NATS.Client.ObjectStore.Tests/NATS.Client.ObjectStore.Tests.csproj

- name: Test Services
run: dotnet test -c Debug --no-build --logger:"console;verbosity=normal" tests/NATS.Client.Services.Tests/NATS.Client.Services.Tests.csproj

memory_test:
name: memory test
strategy:
Expand Down
21 changes: 21 additions & 0 deletions NATS.Client.sln
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.ObjectStore", "sand
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nats.Client.Compat.ObjectStore", "tests\Nats.Client.Compat.ObjectStore\Nats.Client.Compat.ObjectStore.csproj", "{35578296-FF6C-4BA4-BEE5-C1A6E7DB7024}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NATS.Client.Services", "src\NATS.Client.Services\NATS.Client.Services.csproj", "{050C63EE-8F1C-4535-9C6C-E12E62A1FF1D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NATS.Client.Services.Tests", "tests\NATS.Client.Services.Tests\NATS.Client.Services.Tests.csproj", "{749CAE39-4C1E-4627-9E31-A36B987BC453}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Services", "sandbox\Example.Services\Example.Services.csproj", "{DD0AB72A-D6CD-4054-A9C9-0DCA3EDBA00F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.TlsFirst", "sandbox\Example.TlsFirst\Example.TlsFirst.csproj", "{88625045-978F-417F-9F51-A4E3A9718945}"
EndProject
Global
Expand Down Expand Up @@ -209,6 +215,18 @@ Global
{35578296-FF6C-4BA4-BEE5-C1A6E7DB7024}.Debug|Any CPU.Build.0 = Debug|Any CPU
{35578296-FF6C-4BA4-BEE5-C1A6E7DB7024}.Release|Any CPU.ActiveCfg = Release|Any CPU
{35578296-FF6C-4BA4-BEE5-C1A6E7DB7024}.Release|Any CPU.Build.0 = Release|Any CPU
{050C63EE-8F1C-4535-9C6C-E12E62A1FF1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{050C63EE-8F1C-4535-9C6C-E12E62A1FF1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{050C63EE-8F1C-4535-9C6C-E12E62A1FF1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{050C63EE-8F1C-4535-9C6C-E12E62A1FF1D}.Release|Any CPU.Build.0 = Release|Any CPU
{749CAE39-4C1E-4627-9E31-A36B987BC453}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{749CAE39-4C1E-4627-9E31-A36B987BC453}.Debug|Any CPU.Build.0 = Debug|Any CPU
{749CAE39-4C1E-4627-9E31-A36B987BC453}.Release|Any CPU.ActiveCfg = Release|Any CPU
{749CAE39-4C1E-4627-9E31-A36B987BC453}.Release|Any CPU.Build.0 = Release|Any CPU
{DD0AB72A-D6CD-4054-A9C9-0DCA3EDBA00F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD0AB72A-D6CD-4054-A9C9-0DCA3EDBA00F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD0AB72A-D6CD-4054-A9C9-0DCA3EDBA00F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD0AB72A-D6CD-4054-A9C9-0DCA3EDBA00F}.Release|Any CPU.Build.0 = Release|Any CPU
{88625045-978F-417F-9F51-A4E3A9718945}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88625045-978F-417F-9F51-A4E3A9718945}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88625045-978F-417F-9F51-A4E3A9718945}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -249,6 +267,9 @@ Global
{BB2F4EEE-1AB3-43F7-B004-6C9B3D52353E} = {C526E8AB-739A-48D7-8FC4-048978C9B650}
{51882883-A66E-4F95-A1AB-CFCBF71B4376} = {95A69671-16CA-4133-981C-CC381B7AAA30}
{35578296-FF6C-4BA4-BEE5-C1A6E7DB7024} = {C526E8AB-739A-48D7-8FC4-048978C9B650}
{050C63EE-8F1C-4535-9C6C-E12E62A1FF1D} = {4827B3EC-73D8-436D-AE2A-5E29AC95FD0C}
{749CAE39-4C1E-4627-9E31-A36B987BC453} = {C526E8AB-739A-48D7-8FC4-048978C9B650}
{DD0AB72A-D6CD-4054-A9C9-0DCA3EDBA00F} = {95A69671-16CA-4133-981C-CC381B7AAA30}
{88625045-978F-417F-9F51-A4E3A9718945} = {95A69671-16CA-4133-981C-CC381B7AAA30}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ NATS.NET V2 is a [NATS](https://nats.io) client for the modern [.NET](https://do
## Preview

The NATS.NET V2 client is in preview and not recommended for production use yet.
Codebase is still under heavy development and we currently implemented [Core NATS](https://docs.nats.io/nats-concepts/core-nats)
and basic [JetStream](https://docs.nats.io/nats-concepts/jetstream) features.
Codebase is still under development and we implemented majority of the NATS APIs
including [Core NATS](https://docs.nats.io/nats-concepts/core-nats), most of [JetStream](https://docs.nats.io/nats-concepts/jetstream) features, as well as main
features of Object Store, Key/Value Store and Services.

Please test and provide feedback:

Expand All @@ -30,6 +31,9 @@ Check out the [documentation](https://nats-io.github.io/nats.net.v2/) for guides
- **NATS.Client.Core**: [Core NATS](https://docs.nats.io/nats-concepts/core-nats)
- **NATS.Client.Hosting**: extension to configure DI container
- **NATS.Client.JetStream**: [JetStream](https://docs.nats.io/nats-concepts/jetstream)
- **NATS.Client.KeyValueStore**: [Key/Value Store](https://docs.nats.io/nats-concepts/jetstream/key-value-store)
- **NATS.Client.ObjectStore**: [Object Store](https://docs.nats.io/nats-concepts/jetstream/obj_store)
- **NATS.Client.Services**: [Services](https://docs.nats.io/using-nats/developer/services)

## Contributing

Expand Down
4 changes: 4 additions & 0 deletions docs/documentation/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ these docs. You can also create a Pull Request using the Edit on GitHub link on
[JetStream](jetstream/intro.md) is the built-in distributed persistence system built-in to the same NATS server binary.

[Key/Value Store](key-value-store/intro.md) is the built-in distributed persistent associative arrays built on top of JetStream.

[Object Store](object-store/intro.md) is the built-in distributed persistent objects of arbitrary size built on top of JetStream.

[Services](services/intro.md) is the services protocol built on top of core NATS enabling discovery and monitoring of services you develop.
103 changes: 103 additions & 0 deletions docs/documentation/object-store/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Object Store

[The Object Store](https://docs.nats.io/nats-concepts/jetstream/obj_store) is very similar to the Key Value Store in that you put and get data using a key.
The difference being that Object store allows for the storage of objects that can be of any size.

Under the covers Object Store is a client side construct that allows you to store and retrieve chunks of data
by a key using JetStream as the stream persistence engine. It's a simple, yet powerful way to store
and retrieve large data like files.

To be able to use Object Store you need to enable JetStream by running the server with `-js` flag e.g. `nats-server -js`.

## Object Store Quick Start

[Download the latest](https://nats.io/download/) `nats-server` for your platform and run it with JetStream enabled:

```shell
$ nats-server -js
```

Install `NATS.Client.ObjectStore` preview from Nuget.

Before we can do anything, we need an Object Store context:

```csharp
await using var nats = new NatsConnection();
var js = new NatsJSContext(nats);
var obj = new NatsObjContext(js);
```

Let's create our store first. In Object Store, a bucket is simply a storage for key/object pairs:

```csharp
var store = await obj.CreateObjectStore("test-bucket");
```

Now that we have a bucket in our stream, let's see its status using the [NATS command
line client](https://github.com/nats-io/natscli):

```shell
$ nats object ls
╭──────────────────────────────────────────────────────────────────────╮
│ Object Store Buckets │
├─────────────┬─────────────┬─────────────────────┬──────┬─────────────┤
│ Bucket │ Description │ Created │ Size │ Last Update │
├─────────────┼─────────────┼─────────────────────┼──────┼─────────────┤
│ test-bucket │ │ 2023-10-18 14:10:27 │ 0 B │ never │
╰─────────────┴─────────────┴─────────────────────┴──────┴─────────────╯
```

We can save objects in a bucket by putting them using a key, which is `my/random/data.bin` in our case. We can also retrieve the
saved value by its key:

```csharp
await store.PutAsync("my/random/data.bin", File.OpenRead("data.bin"));

await store.GetAsync("my/random/data.bin", File.OpenWrite("data_copy.bin"));
```

We can also confirm that our value is persisted by using the NATS command line:

```shell
$ nats object info test-bucket my/random/data.bin
Object information for test-bucket > my/random/data.bin

Size: 10 MiB
Modification Time: 18 Oct 23 14:54 +0000
Chunks: 80
Digest: SHA-256 d34334673e4e2b2300c09550faa5e2b6d0f04245a1d0b664454bb922da56
```

## Other Operations

### Get Info

We can get information about a key in a bucket:

```csharp
var metadata = await store.GetInfoAsync("my/random/data.bin");

Console.WriteLine("Metadata:");
Console.WriteLine($" Bucket: {metadata.Bucket}");
Console.WriteLine($" Name: {metadata.Name}");
Console.WriteLine($" Size: {metadata.Size}");
Console.WriteLine($" Time: {metadata.MTime}");
Console.WriteLine($" Chunks: {metadata.Chunks}");

// Outputs:
// Metadata:
// Bucket: test-bucket
// Name: my/random/data.bin
// Size: 10485760
// Time: 18/10/2023 15:13:22 +00:00
// Chunks: 80
```

### Delete

We can delete a key from a bucket:

```csharp
await store.DeleteAsync("my/random/data.bin");
```
102 changes: 102 additions & 0 deletions docs/documentation/services/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Services

[Services](https://docs.nats.io/using-nats/developer/services) is a protocol that provides first-class services support
for NATS clients and it's supported by NATS tooling. This services protocol is an agreement between clients and tooling and
doesn't require any special functionality from the NATS server or JetStream.

To be able to use Services you need to running the `nats-server`.

## Services Quick Start

[Download the latest](https://nats.io/download/) `nats-server` for your platform and run it:

```shell
$ nats-server
```

Install `NATS.Client.Services` preview from Nuget.

Before we can do anything, we need a Services context:

```csharp
await using var nats = new NatsConnection();
var svc = new NatsSvcContext(nats);
```

Let's create our first service:

```csharp
await using var testService = await svc.AddServiceAsync("test", "1.0.0");
```

Now that we have a service in our stream, let's see its status using the [NATS command
line client](https://github.com/nats-io/natscli) (make sure you have at least v0.1.1):

```shell
$ nats --version
0.1.1
```

```shell
$ nats micro info test
Service Information

Service: test (Bw6eqhVYs3dbNzZecuuFOV)
Description:
Version: 1.0.0

Endpoints:

Statistics for 0 Endpoint(s):
```

Now we can add endpoints to our service:

```csharp
await testService.AddEndPointAsync<int>(name: "divide42", handler: async m =>
{
if (m.Data == 0)
{
await m.ReplyErrorAsync(400, "Division by zero");
return;
}

await m.ReplyAsync(42 / m.Data);
});
```

We can also confirm that our endpoint is registered by using the NATS command line:

```shell
$ nats req divide42 2
11:34:03 Sending request on "divide42"
11:34:03 Received with rtt 9.5823ms
21

$ nats micro stats test
╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮
test Service Statistics │
├────────────────────────┬──────────┬──────────┬─────────────┬────────┬─────────────────┬──────────────┤
│ ID │ Endpoint │ Requests │ Queue Group │ Errors │ Processing Time │ Average Time │
├────────────────────────┼──────────┼──────────┼─────────────┼────────┼─────────────────┼──────────────┤
│ RH6q9Y6qM8em8m6lG2yN34 │ divide42 │ 1 │ q │ 0 │ 1ms │ 1ms │
├────────────────────────┼──────────┼──────────┼─────────────┼────────┼─────────────────┼──────────────┤
│ │ │ 1 │ │ 0 │ 1MS │ 1MS │
╰────────────────────────┴──────────┴──────────┴─────────────┴────────┴─────────────────┴──────────────╯
```

## Groups

A group is a collection of endpoints. These are optional and can provide a logical association between endpoints
as well as an optional common subject prefix for all endpoints.

You can group your endpoints optionally in different [queue groups](https://docs.nats.io/nats-concepts/core-nats/queue):

```csharp
var grp1 = await testService.AddGroupAsync("grp1");

await grp1.AddEndPointAsync<int>(name: "ep1", handler: async m =>
{
// handle message
});
```
3 changes: 3 additions & 0 deletions docs/documentation/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@
- name: Key/Value Store
href: key-value-store/intro.md

- name: Object Store
href: object-store/intro.md

- name: Updating Documentation
href: update-docs.md
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ The NATS.NET V2 client is in preview and not recommended for production use yet.
- [x] Core NATS
- [x] JetStream initial support
- [x] KV initial support
- [ ] Object Store initial support
- [x] Object Store initial support
- [x] Service API initial support
- [ ] .NET 8.0 support (e.g. Native AOT)
- [ ] Beta phase

Expand Down
Loading

0 comments on commit b9a99d2

Please sign in to comment.