Skip to content

Commit 462961f

Browse files
authored
[WebPubSub] Update the README of WebPubSubClient (#33267)
# Contributing to the Azure SDK Please see our [CONTRIBUTING.md](https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md) if you are not familiar with contributing to this repository or have questions. For specific information about pull request etiquette and best practices, see [this section](https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md#pull-request-etiquette-and-best-practices).
1 parent cccc9a3 commit 462961f

File tree

4 files changed

+162
-59
lines changed

4 files changed

+162
-59
lines changed

sdk/webpubsub/Azure.Messaging.WebPubSub.Client/README.md

Lines changed: 91 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Azure Web PubSub client library for .NET
22

3-
[Azure Web PubSub Service](https://aka.ms/awps/doc) is an Azure-managed service that helps developers easily build web applications with real-time features and publish-subscribe pattern. Any scenario that requires real-time publish-subscribe messaging between server and clients or among clients can use Azure Web PubSub service. Traditional real-time features that often require polling from server or submitting HTTP requests can also use Azure Web PubSub service.
3+
[Azure Web PubSub Service](https://aka.ms/awps/doc) is an Azure-managed service that helps developers easily build web applications with real-time features and publish-subscribe patterns. Any scenario that requires real-time publish-subscribe messaging between server and clients or among clients can use Azure Web PubSub service. Traditional real-time features that often require polling from the server or submitting HTTP requests can also use Azure Web PubSub service.
44

5-
You can use this library in your client side to manage the WebSocket client connections, as shown in below diagram:
5+
You can use this library on your client side to manage the WebSocket client connections, as shown in the below diagram:
66

7-
![overflow](https://user-images.githubusercontent.com/668244/140014067-25a00959-04dc-47e8-ac25-6957bd0a71ce.png)
7+
![overflow](./samples/media/overview.png)
88

99
Use this library to:
1010

@@ -36,13 +36,23 @@ dotnet add package Azure.Messaging.WebPubSub.Client
3636

3737
### Authenticate the client
3838

39-
In order to interact with the service, you'll need to create an instance of the `WebPubSubClient` class. To make this possible, you'll need an access token. You can copy and paste an access token from Azure portal.
39+
A Client uses a Client Access URL to connect and authenticate with the service. The Uri follow the patten as `wss://<service_name>.webpubsub.azure.com/client/hubs/<hub_name>?access_token=<token>`. There're multiple ways to get a Client Access URL. As a quick start, you can copy and paste from Azure Portal, and for production, you usually need a negotiation server to generate the Uri.
40+
41+
#### Use Client Access URL from Azure Portal
42+
43+
As a quick start, you can go to the Portal and copy the **Client Access URL** from **Key** blade.
44+
45+
![get_client_url](https://learn.microsoft.com/azure/azure-web-pubsub/media/howto-websocket-connect/generate-client-url.png)
46+
47+
As shown in the diagram, the client will be granted permission of sending messages to the specific group and joining the specific group. Learn more about client permission, see [permissions](https://learn.microsoft.com/azure/azure-web-pubsub/reference-json-reliable-webpubsub-subprotocol#permissions)
4048

4149
```C# Snippet:WebPubSubClient_Construct
4250
var client = new WebPubSubClient(new Uri("<client-access-uri>"));
4351
```
4452

45-
And in production, you usually get `ClientAccessUri` from a negotiate server.
53+
#### Use negotiation server to generate Client Access URL
54+
55+
In production, a client usually fetches the Client Access URL from a negotiation server. The server holds the connection string and generates the Client Access URL through `WebPubSubServiceClient`. As a sample, the code snippet below just demonstrates how to generate the Client Access URL inside a single process.
4656

4757
```C# Snippet:WebPubSubClient_Construct2
4858
var client = new WebPubSubClient(new WebPubSubClientCredential(token =>
@@ -52,13 +62,23 @@ var client = new WebPubSubClient(new WebPubSubClientCredential(token =>
5262
}));
5363
```
5464

55-
The `FetchClientAccessTokenFromServerAsync` usually fetch the token from server via Http request. And in the server side, you can use `WebPubSubServiceClient` to generate token and response to the fetch request.
56-
5765
```C# Snippet:WebPubSubClient_GenerateClientAccessUri
58-
var serviceClient = new WebPubSubServiceClient("<< Connection String >>", "hub");
59-
return await serviceClient.GetClientAccessUriAsync();
66+
public async ValueTask<Uri> FetchClientAccessTokenFromServerAsync(CancellationToken token)
67+
{
68+
var serviceClient = new WebPubSubServiceClient("<< Connection String >>", "hub");
69+
return await serviceClient.GetClientAccessUriAsync();
70+
}
6071
```
6172

73+
Features to differentiate `WebPubSubClient` and `WebPubSubServiceClient`.
74+
75+
|Class Name|WebPubSubClient|WebPubSubServiceClient|
76+
|------|---------|---------|
77+
|Nuget Package Name|Azure.Messaging.WebPubSub.Client |Azure.Messaging.WebPubSub|
78+
|Features|Usually used on client side. Publish messages and subscribe to messages.|Usually used on server side. Generate Client Access Uri and manage clients|
79+
80+
Find more details in [Azure.Messaging.WebPubSub](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/webpubsub/Azure.Messaging.WebPubSub)
81+
6282
## Key concepts
6383

6484
### Connection
@@ -67,11 +87,15 @@ A connection, also known as a client connection, represents an individual WebSoc
6787

6888
### Recovery
6989

70-
If using reliable protocols, a new WebSocket will try to reconnect using the connection ID of the lost connection. If the WebSocket connection is successfully connected, the connection is recovered. And all group contexts will be recovered, and unreceived messages will be resent.
90+
If a client using reliable protocols disconnects, a new WebSocket tries to establish using the connection ID of the lost connection. If the new WebSocket connection is successfully connected, the connection is recovered. Throughout the time a client is disconnected, the service retains the client's context as well as all messages that the client was subscribed to, and when the client recovers, the service will send these messages to the client. If the service returns WebSocket error code `1008` or the recovery attempt lasts more than 30 seconds, the recovery fails.
91+
92+
### Reconnect
93+
94+
Reconnection happens when the client connection drops and fails to recover. Reconnection starts a new connection and the new connection has a new connection ID. Unlike recovery, the service treats the reconnected client as a new client connection. The client connection needs to rejoin groups. By default, the client library rejoins groups after reconnection.
7195

7296
### Hub
7397

74-
A hub is a logical concept representing a collection of client connections. Usually, you use one hub for one purpose: for example, a chat hub, or a notification hub. When a client connection is created, it connects to a hub and, and during its lifetime, it is bound to that hub. Different applications can share one Azure Web PubSub service by using different hub names.
98+
A hub is a logical concept representing a collection of client connections. Usually, you use one hub for one purpose: for example, a chat hub, or a notification hub. When a client connection is created, it connects to a hub, and during its lifetime, it is bound to that hub. Different applications can share one Azure Web PubSub service by using different hub names.
7599

76100
### Group
77101

@@ -81,29 +105,53 @@ A group is a subset of connections to the hub. You can add and remove connection
81105

82106
Connections to Web PubSub can belong to one user. A user might have multiple connections, for example when a single user is connected across multiple devices or browser tabs.
83107

84-
### Message
108+
## Client Lifetime
85109

86-
When a client is connected, it can send messages to the upstream application, or receive messages from the upstream application, through the WebSocket connection. Also, it can send messages to groups and receive message from joined groups.
110+
Each of the Web PubSub clients is safe to cache and use as a singleton for the lifetime of the application. The registered event callbacks share the same lifetime with the client. This means you can add or remove callbacks at any time and the registration status won't change after reconnection or even stopping the client.
87111

88112
## Examples
89113

90-
### Send to groups
114+
### Specify subprotocol
91115

92-
```C# Snippet:WebPubSubClient_SendToGroup
93-
// Send message to group "testGroup"
94-
await client.SendToGroupAsync("testGroup", BinaryData.FromString("hello world"), WebPubSubDataType.Text);
116+
You can specify the subprotocol to be used by the client. By default, the client uses `json.reliable.webpubsub.azure.v1`. You can choose to use `json.reliable.webpubsub.azure.v1` or `json.webpubsub.azure.v1` as shown below.
117+
118+
```C# Snippet:WebPubSubClient_JsonProtocol
119+
var client = new WebPubSubClient(new Uri("<client-access-uri>"), new WebPubSubClientOptions
120+
{
121+
Protocol = new WebPubSubJsonProtocol()
122+
});
123+
```
124+
125+
```C# Snippet:WebPubSubClient_JsonReliableProtocol
126+
var client = new WebPubSubClient(new Uri("<client-access-uri>"), new WebPubSubClientOptions
127+
{
128+
Protocol = new WebPubSubJsonReliableProtocol()
129+
});
95130
```
96131

97-
### Send events to event handler
132+
### Consume messages from the server and groups
133+
134+
A client can add callbacks to consume messages from the server and groups. Please note, clients can only receive group messages that it has joined.
135+
136+
```C# Snippet:WebPubSubClient_Subscribe_ServerMessage
137+
client.ServerMessageReceived += eventArgs =>
138+
{
139+
Console.WriteLine($"Receive message: {eventArgs.Message.Data}");
140+
return Task.CompletedTask;
141+
};
142+
```
98143

99-
```C# Snippet:WebPubSubClient_SendEvent
100-
// Send custom event to server
101-
await client.SendEventAsync("testEvent", BinaryData.FromString("hello world"), WebPubSubDataType.Text);
144+
```C# Snippet:WebPubSubClient_Subscribe_GroupMessage
145+
client.GroupMessageReceived += eventArgs =>
146+
{
147+
Console.WriteLine($"Receive group message from {eventArgs.Message.Group}: {eventArgs.Message.Data}");
148+
return Task.CompletedTask;
149+
};
102150
```
103151

104-
### Handle the Connected event
152+
### Add callbacks for connected, disconnected, and stopped events
105153

106-
The `Connected` event is called after the client receives connected message. The event will be triggered every reconnection.
154+
When a client connection is connected to the service, the `Connected` event is triggered once it received the connected message from the service.
107155

108156
```C# Snippet:WebPubSubClient_Subscribe_Connected
109157
client.Connected += eventArgs =>
@@ -113,9 +161,7 @@ client.Connected += eventArgs =>
113161
};
114162
```
115163

116-
### Handle the Disconnected event
117-
118-
The `Disconnected` event is triggered every time the connection closed and could not be recovered
164+
When a client connection is disconnected and fails to recover, the `Disconnected` event is triggered.
119165

120166
```C# Snippet:WebPubSubClient_Subscribe_Disconnected
121167
client.Disconnected += eventArgs =>
@@ -125,9 +171,7 @@ client.Disconnected += eventArgs =>
125171
};
126172
```
127173

128-
### Handle the Stopped event
129-
130-
The `Stopped` event is triggered when the client is stopped. The client won't try to reconnect after being stopped. This event is typically the result of calling `StopAsync` or disabling the `AutoReconnect`
174+
When a client is stopped, which means the client connection is disconnected and the client stops trying to reconnect, the `Stopped` event will be triggered. This usually happens after the `client.StopAsync()` is called, or disabled `AutoReconnect`. If you want to restart the client, you can call `client.StartAsync()` in the `Stopped` event.
131175

132176
```C# Snippet:WebPubSubClient_Subscribe_Stopped
133177
client.Stopped += eventArgs =>
@@ -137,40 +181,35 @@ client.Stopped += eventArgs =>
137181
};
138182
```
139183

140-
### Handle the Server message event
184+
### Auto rejoin groups and handle rejoin failure
141185

142-
The `ServerMessageReceived` event is triggered when there's a message from server.
186+
When a client connection has dropped and fails to recover, all group contexts will be cleaned up on the service side. That means when the client reconnects, it needs to rejoin groups. By default, the client enabled `AutoRejoinGroups` options. However, this feature has limitations. The client can only rejoin groups that it's originally joined by the client rather than joined by the server side. And rejoin group operations may fail due to various reasons, e.g. the client doesn't have permission to join groups. In such cases, users need to add a callback to handle the failure.
143187

144-
```C# Snippet:WebPubSubClient_Subscribe_ServerMessage
145-
client.ServerMessageReceived += eventArgs =>
188+
```C# Snippet:WebPubSubClient_Subscribe_RestoreFailed
189+
client.RejoinGroupFailed += eventArgs =>
146190
{
147-
Console.WriteLine($"Receive message: {eventArgs.Message.Data}");
191+
Console.WriteLine($"Restore group failed");
148192
return Task.CompletedTask;
149193
};
150194
```
151195

152-
### Handle the Group message event
196+
### Operation and retry
153197

154-
The `GroupMessageReceived` event is triggered when there's a message from a group. You must join a group before you can receive messages from it.
198+
By default, the operation such as `client.JoinGroupAsync()`, `client.LeaveGroupAsync()`, `client.SendToGroupAsync()`, `client.SendEventAsync()` has three reties. You can use `WebPubSubClientOptions.MessageRetryOptions` to change. If all retries have failed, an error will be thrown. You can keep retrying by passing in the same `ackId` as previous retries, thus the service can help to deduplicate the operation with the same `ackId`
155199

156-
```C# Snippet:WebPubSubClient_Subscribe_GroupMessage
157-
client.GroupMessageReceived += eventArgs =>
200+
```C# Snippet:WebPubSubClient_JoinGroupAndRetry
201+
// Send message to group "testGroup"
202+
try
158203
{
159-
Console.WriteLine($"Receive group message from {eventArgs.Message.Group}: {eventArgs.Message.Data}");
160-
return Task.CompletedTask;
161-
};
162-
```
163-
164-
### Handle the restore failure event
165-
166-
The `RestoreGroupFailed` event is triggered when the `AutoRejoinGroups` is enabled and rejoining a group fails after reconnection.
167-
168-
```C# Snippet:WebPubSubClient_Subscribe_RestoreFailed
169-
client.RejoinGroupFailed += eventArgs =>
204+
await client.JoinGroupAsync("testGroup");
205+
}
206+
catch (SendMessageFailedException ex)
170207
{
171-
Console.WriteLine($"Restore group failed");
172-
return Task.CompletedTask;
173-
};
208+
if (ex.AckId == null)
209+
{
210+
await client.JoinGroupAsync("testGroup", ackId: ex.AckId);
211+
}
212+
}
174213
```
175214

176215
## Troubleshooting

sdk/webpubsub/Azure.Messaging.WebPubSub.Client/samples/Sample1_HelloWorld.md

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
1-
# Create client, publish and subscribe group messages
1+
# Create clients, publish and subscribe to group messages
22

33
This sample demonstrates the basic usage of Azure Web PubSub service, with the goal of quickly allowing you to publish to groups and subscribe to messages from groups. To accomplish this, the `WebPubSubClient` will be introduced, along with some of the core concepts of Azure Web PubSub service.
44

55
## Create the clients
66

7-
To interact with Azure WebPubSub service, a client is needed for each area of functionality. For each hub, a client must be created and copy and paste the `clientAcccessUri` from Azure Portal
7+
A Client uses a Client Access URL to connect and authenticate with the service. The Uri follow the patten as `wss://<service_name>.webpubsub.azure.com/client/hubs/<hub_name>?access_token=<token>`. There're multiple ways to get a Client Access URL. As a quick start, you can copy and paste from Azure Portal, and for production, you usually need a negotiation server to generate the Uri.
8+
9+
### Use Client Access URL from Azure Portal
10+
11+
As a quick start, you can go to the Portal and copy the **Client Access URL** from **Key** blade.
12+
13+
![get_client_url](https://learn.microsoft.com/azure/azure-web-pubsub/media/howto-websocket-connect/generate-client-url.png)
14+
15+
As shown in the diagram, the client will be granted permission of sending messages to the specific group and joining the specific group. Learn more about client permission, see [permissions](https://learn.microsoft.com/azure/azure-web-pubsub/reference-json-reliable-webpubsub-subprotocol#permissions)
816

917
```C# Snippet:WebPubSubClient_Construct
1018
var client = new WebPubSubClient(new Uri("<client-access-uri>"));
1119
```
1220

13-
The `clientAcccessUri` also can be generated by `WebPubSubServiceClient`
21+
### Use negotiation server to generate Client Access URL
22+
23+
In production, a client usually fetches the Client Access URL from a negotiation server. The server holds the connection string and generates the Client Access URL through `WebPubSubServiceClient`. As a sample, the code snippet below just demonstrates how to generate the Client Access URL inside a single process.
1424

1525
```C# Snippet:WebPubSubClient_Construct2
1626
var client = new WebPubSubClient(new WebPubSubClientCredential(token =>
@@ -20,11 +30,19 @@ var client = new WebPubSubClient(new WebPubSubClientCredential(token =>
2030
}));
2131
```
2232

23-
The client is responsible for making a connection to the service and efficiently publishing messages or subscribing messages from groups. By default, `WebPubSubClient` uses `json.reliable.webpubsub.azure.v1` subprotocol.
33+
```C# Snippet:WebPubSubClient_GenerateClientAccessUri
34+
public async ValueTask<Uri> FetchClientAccessTokenFromServerAsync(CancellationToken token)
35+
{
36+
var serviceClient = new WebPubSubServiceClient("<< Connection String >>", "hub");
37+
return await serviceClient.GetClientAccessUriAsync();
38+
}
39+
```
40+
41+
The client is responsible for making a connection to the service and efficiently publishing messages or subscribing to messages from groups. By default, `WebPubSubClient` uses `json.reliable.webpubsub.azure.v1` subprotocol.
2442

2543
## Subscribe to messages
2644

27-
Messages can come from groups or from servers. The client can register an event handler to be notified of messages and system events. The event handler share the same lifetime with the client, so you can subscribe them before you start the client. If the client has a permission to join group, it can join group to subscribe messages from that group. But note joining group operation must be called after the client has been started.
45+
Messages can come from groups or from servers. The client can register a callback to be notified when messages have been received. The callbacks share the same lifetime with the client, so you can subscribe to them before you start the client. If the client has permission to join groups, it can join the group to subscribe to messages from that group. But note joining group operation must be called after the client has been started.
2846

2947
```C# Snippet:WebPubSubClient_Subscribe_ServerMessage
3048
client.ServerMessageReceived += eventArgs =>
@@ -42,9 +60,17 @@ client.GroupMessageReceived += eventArgs =>
4260
};
4361
```
4462

63+
## Start client
64+
65+
After you call `client.StartAsync()`, the client starts to make connections to the service and be ready for sending messages.
66+
67+
```csharp
68+
await client.StartAsync();
69+
```
70+
4571
## Publish messages to group or server
4672

47-
To publish messages, a `WebPubSubClient` need to be created and started. The client can send event to server or send messages to groups.
73+
To publish messages, a `WebPubSubClient` need to be created and started. The client can send events to the server or send messages to groups.
4874

4975
```C# Snippet:WebPubSubClient_SendToGroup
5076
// Send message to group "testGroup"
32.8 KB
Loading

0 commit comments

Comments
 (0)