Skip to content

Commit

Permalink
Documentation updates (#229)
Browse files Browse the repository at this point in the history
* Documentation updates

* Docs NATS core code includes

Also hidden internal classes.

* Docs update JS manage

* JS and KV docs updates

* Object store and serialization doc updates

* Make debug extensions internal

* Clarified ping and connect behaviour

* Mentioned Docker in docs and a typo fix
  • Loading branch information
mtmk authored Nov 23, 2023
1 parent 38d2f5f commit c9d5604
Show file tree
Hide file tree
Showing 43 changed files with 1,680 additions and 776 deletions.
7 changes: 7 additions & 0 deletions NATS.Client.sln
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NATS.Client.Serializers.Jso
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NATS.Net", "src\NATS.Net\NATS.Net.csproj", "{6A7B9B9F-BFA4-4A6D-9006-0AAF597FC6DD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NATS.Net.DocsExamples", "tests\NATS.Net.DocsExamples\NATS.Net.DocsExamples.csproj", "{389C05EB-A0B3-4097-8C1F-4D55818438CC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -261,6 +263,10 @@ Global
{6A7B9B9F-BFA4-4A6D-9006-0AAF597FC6DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A7B9B9F-BFA4-4A6D-9006-0AAF597FC6DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A7B9B9F-BFA4-4A6D-9006-0AAF597FC6DD}.Release|Any CPU.Build.0 = Release|Any CPU
{389C05EB-A0B3-4097-8C1F-4D55818438CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{389C05EB-A0B3-4097-8C1F-4D55818438CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{389C05EB-A0B3-4097-8C1F-4D55818438CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{389C05EB-A0B3-4097-8C1F-4D55818438CC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -306,6 +312,7 @@ Global
{9FCD9377-FE5F-4D94-BDCF-54427DB6487D} = {95A69671-16CA-4133-981C-CC381B7AAA30}
{5B4B30A5-941B-44F9-98C6-06F0BB2242AB} = {4827B3EC-73D8-436D-AE2A-5E29AC95FD0C}
{6A7B9B9F-BFA4-4A6D-9006-0AAF597FC6DD} = {4827B3EC-73D8-436D-AE2A-5E29AC95FD0C}
{389C05EB-A0B3-4097-8C1F-4D55818438CC} = {C526E8AB-739A-48D7-8FC4-048978C9B650}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8CBB7278-D093-448E-B3DE-B5991209A1AA}
Expand Down
11 changes: 8 additions & 3 deletions docs/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"disableGitFeatures": false,
"disableDefaultFilter": false,
"noRestore": false,
"namespaceLayout": "flattened",
"memberLayout": "samePage",
"namespaceLayout": "nested",
"memberLayout": "separatePages",
"allowCompilationErrors": false
}
],
Expand Down Expand Up @@ -51,6 +51,11 @@
],
"postProcessors": [],
"keepFileLink": false,
"disableGitFeatures": false
"disableGitFeatures": false,
"sitemap": {
"baseUrl": "https://nats-io.github.io/nats.net.v2",
"priority": 0.1,
"changefreq": "monthly"
}
}
}
58 changes: 8 additions & 50 deletions docs/documentation/core/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ of explanation, in a simplified sense you can think of Core NATS as the
[wire protocol](https://docs.nats.io/reference/reference-protocols/nats-protocol) defining a simple but powerful
pub/sub functionality and the concept of [Subject-Based Messaging](https://docs.nats.io/nats-concepts/subjects).

## Core NATS Quick Start
## Quick Start

[Download the latest](https://nats.io/download/) `nats-server` for your platform and run it without any arguments. `nats-server` will listen
on its default TCP port 4222.
Expand All @@ -15,70 +15,28 @@ on its default TCP port 4222.
$ nats-server
```

Install `NATS.Client.Core` preview from Nuget.
Install [NATS.Net](https://www.nuget.org/packages/NATS.Net)
and [NATS.Client.Serializers.Json](https://www.nuget.org/packages/NATS.Client.Serializers.Json) from Nuget.

Given that we have a plain class `Bar`, we can publish and subscribe to our `nats-server` sending
and receiving `Bar` objects:

```csharp
public record Bar
{
public int Id { get; set; }
public string Name { get; set; }
}
```
[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/IntroPage.cs#bar)]

Subscribe to all `bar` [related subjects](https://docs.nats.io/nats-concepts/subjects):

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

await foreach (var msg in nats.Subscription("bar.>"))
{
if (msg.Subject == "bar.exit")
break;

Console.WriteLine($"Received {msg.Subject}: {msg.Data}\n");
}
```
[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/IntroPage.cs#sub)]

Publish `Bar` objects to related `bar` [subjects](https://docs.nats.io/nats-concepts/subjects):
```csharp
await using var nats = new NatsConnection();

for (int i = 0; i < 10; i++)
{
Console.WriteLine($" Publishing {i}...");
await nats.PublishAsync<Bar>($"bar.baz.{i}", new Bar { Id = i, Name = "Baz" });
}

await nats.PublishAsync("bar.exit");
```
[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/IntroPage.cs#pub)]

## Logging

You should also hook your logger to `NatsConnection` to make sure all is working as expected or
to get help diagnosing any issues you might have:

```csharp
// First add Nuget package Microsoft.Extensions.Logging.Console
using Microsoft.Extensions.Logging;

using var loggerFactory = LoggerFactory.Create(configure: builder =>
{
builder
.SetMinimumLevel(LogLevel.Information)
.AddSimpleConsole(options =>
{
options.SingleLine = true;
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss.fff zzz ";
});
});

var opts = NatsOpts.Default with { LoggerFactory = loggerFactory };

await using var nats = new NatsConnection(otps);
```
(For this example you need to add [Microsoft.Extensions.Logging.Console](https://www.nuget.org/packages/Microsoft.Extensions.Logging.Console) from Nuget.)
[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/IntroPage.cs#logging)]

## What's Next

Expand Down
76 changes: 26 additions & 50 deletions docs/documentation/core/pub-sub.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,32 @@ NATS implements a publish-subscribe message distribution model for one-to-many c
A publisher sends a message on a subject and any active subscriber listening on that subject
receives the message.

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

var sub = Task.Run(async () =>
{
await foreach(var msg in nats.SubscribeAsync<int>("foo"))
{
Console.WriteLine($"Received {msg.Subject}: {msg.Data}\n");

if (msg.Data == -1)
break;
}
});

for (int i = 0; i < 10; i++)
{
Console.WriteLine($" Publishing {i}...");
await nats.PublishAsync<int>("foo", i);
await Task.Delay(1000);
}

await nats.PublishAsync<int>("foo", -1);

await sub;
```
[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/PubSubPage.cs#pubsub)]

## Subscriptions with Lower Level Control

The `SubscribeAsync()` method is a convenient way to subscribe to a subject and receive messages without much effort.
If you need more control over how subscription is handled, you can use the `SubscribeCoreAsync()` method instead.

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

await using sub = await nats.SubscribeAsync<int>("foo");

for (int i = 0; i < 10; i++)
{
Console.WriteLine($" Publishing {i}...");
await nats.PublishAsync<int>("foo", i);
}

await nats.PublishAsync<int>("foo", -1);

await foreach (var msg in sub.Msgs.ReadAllAsync())
{
Console.WriteLine($"Received {msg.Subject}: {msg.Data}\n");
if (msg.Data == -1)
break;
}

await sub.UnsubscribeAsync();
```
The
[`SubscribeAsync()`](xref:NATS.Client.Core.INatsConnection.SubscribeAsync``1(System.String,System.String,NATS.Client.Core.INatsDeserialize{``0},NATS.Client.Core.NatsSubOpts,System.Threading.CancellationToken))
method is a convenient way to subscribe to a subject and receive messages without much effort.
If you need more control over how subscription is handled, you can use the
[`SubscribeCoreAsync()`](xref:NATS.Client.Core.INatsConnection.SubscribeCoreAsync``1(System.String,System.String,NATS.Client.Core.INatsDeserialize{``0},NATS.Client.Core.NatsSubOpts,System.Threading.CancellationToken))
method instead.

[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/PubSubPage.cs#lowlevel)]

> [!NOTE]
> [`NatsConnection`](xref:NATS.Client.Core.NatsConnection) establishes the first server connection when the first call to subscribe or publish is made.
> This is why we call the `ConnectAsync()` method explicitly before subscribe or publishing any messages in the example above,
> making sure the subscription request is received by the server before any publish requests, avoiding potential race conditions
> of subscribe and publish method establishing the first connection.

> [!NOTE]
> [`PingAsync()`](xref:NATS.Client.Core.INatsConnection.PingAsync(System.Threading.CancellationToken)) is somewhat a
> special method in all NATS clients. It is used to send a ping to the server and
> receive a pong back while measuring the round trip time. Since it waits for the server to respond, as a side effect
> it also flushes the outgoing buffers.
>
> Remember that every [`NatsConnection`](xref:NATS.Client.Core.NatsConnection) instance is a single TCP connection
> and all the calls sent to the server are
> essentially serialized back to back after they're picked up from internal queues and buffers.
66 changes: 10 additions & 56 deletions docs/documentation/core/queue.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,77 +10,31 @@ Code below demonstrates multiple subscriptions on the same queue group,
receiving messages randomly distributed among them. This example also shows
how queue groups can be used to load balance responders:

```csharp
using NATS.Client.Core;

await using var nats = new NatsConnection();

var subs = new List<NatsSubBase>();
var replyTasks = new List<Task>();
var cts = new CancellationTokenSource();

for (int i = 0; i < 3; i++)
{
// Create three subscriptions all on the same queue group
// Create a background message loop for every subscription
var replyTaskId = i;
replyTasks.Add(Task.Run(async () =>
{
// Retrieve messages until unsubscribed
await foreach (var msg in nats.SubscribeAsync<int>("math.double", queueGroup: "maths-service", cancellationToken: cts.Token))
{
Console.WriteLine($"[{replyTaskId}] Received request: {msg.Data}");
await msg.ReplyAsync($"Answer is: {2 * msg.Data}");
}

Console.WriteLine($"[{replyTaskId}] Done");
}));
}

// Send a few requests
for (int i = 0; i < 10; i++)
{
var reply = await nats.RequestAsync<int, string>("math.double", i);
Console.WriteLine($"Reply: '{reply}'");
}

Console.WriteLine("Stopping...");

// Cancellation token will unsubcribe and complete the message loops
cts.Cancel();

// Make sure all tasks finished cleanly
await Task.WhenAll(replyTasks);

Console.WriteLine("Bye");
```
[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/QueuePage.cs#queue)]

Output should look similar to this:

```
[0] Received request: 0
```text
[1] Received request: 0
Reply: 'Answer is: 0'
[2] Received request: 1
Reply: 'Answer is: 2'
[1] Received request: 2
[2] Received request: 2
Reply: 'Answer is: 4'
[0] Received request: 3
[2] Received request: 3
Reply: 'Answer is: 6'
[0] Received request: 4
[2] Received request: 4
Reply: 'Answer is: 8'
[1] Received request: 5
Reply: 'Answer is: 10'
[2] Received request: 6
Reply: 'Answer is: 12'
[0] Received request: 5
[0] Received request: 7
Reply: 'Answer is: 14'
[1] Received request: 8
Reply: 'Answer is: 16'
[0] Received request: 9
[1] Received request: 9
Reply: 'Answer is: 18'
Stopping...
[2] Done
[0] Done
[1] Done
[2] Done
Bye
All done
```
19 changes: 2 additions & 17 deletions docs/documentation/core/req-rep.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,8 @@ A request is sent, and the application either waits on the response with a certa
or receives a response asynchronously.

Create a service that will be responding to requests:
```csharp
await using var nats = new NatsConnection();

await foreach (var msg in conn.SubscribeAsync<int>("math.double"))
{
Console.WriteLine($"Received request: {msg.Data}");

await msg.ReplyAsync($"Answer is: { 2 * msg.Data }");
}
```
[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/ReqRepPage.cs#sub)]

Reply to a request is asynchronously received using an _inbox_ subscription
behind the scenes:
```csharp
await using var nats = new NatsConnection();

var reply = await nats.RequestAsync<int, string>("math.double", 2);

Console.WriteLine($"Received reply: {reply}")
```
[!code-csharp[](../../../tests/NATS.Net.DocsExamples/Core/ReqRepPage.cs#reqrep)]
Loading

0 comments on commit c9d5604

Please sign in to comment.