Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EDU-176] Migrate content to relevant sections and remove best practice guide #2087

Merged
merged 1 commit into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 6 additions & 4 deletions content/auth/identified-clients.textile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ languages:
- swift
---

When a client is authenticated and connected to Ably, it is considered to be an authenticated client. While an authenticated client has a means to authenticate with Ably, they do not necessarily have an identity.
When a client is authenticated and connected to Ably, it is considered to be an authenticated client. While an authenticated client has a means to authenticate with Ably, they do not necessarily have an identity.

When a client is assigned a trusted identity, that is, a @clientId@, then they are considered to be an identified client. For all operations that client performs with the Ably service, their @clientId@ field will be automatically populated and can be trusted by other clients.

Expand All @@ -28,9 +28,11 @@ There are three different ways a client can be identified with using a @clientId
* A client is authenticating with a token issued for a specific @clientId@.
* A client claims a @clientId@ when authenticating with a token that is issued for a wildcard @clientId@.

When a client sets their own ID there is the possibility that they can pretend to be someone else. To prevent this, it is recommended that you embed a @clientId@ in the token issued to your clients from your auth server. This ensures that the @clientId@ is set by your auth server, and eliminates the chance of a client pretending to be someone else.

<aside data-type='note'>
<p>Identifying a client varies depending on whether they are authenticating with basic authentication or token authentication. Token authentication is "recommended":/auth#selecting-auth in most instances so that clients authenticate using short-lived tokens and do not have access to API keys.</p>
<p>Since you then control the @clientId@ that may be used by any clients, all other clients can rely on the validity of the @clientId@ in published messages and of members present in presence channels.</p>
<p>Since you then control the @clientId@, all other clients can rely on the validity of the @clientId@ in published messages and of members present in presence channels. This eliminates the possibility of a client pretending to be someone else, as they cannot claim a @clientId@ in their own.</p>
</aside>

h3(#basic). Basic auth
Expand All @@ -39,7 +41,7 @@ You can use "basic authentication":/auth/basic to allow a client to claim any @c

h3(#token). Token auth

You can use "token authentication":/auth/token to set an explicit @clientId@ when creating or issuing a token. Clients using that token are restricted to operations for only that @clientId@, and all operations will implicitly contain that @clientId@.
You can use "token authentication":/auth/token to set an explicit @clientId@ when creating or issuing a token. Clients using that token are restricted to operations for only that @clientId@, and all operations will implicitly contain that @clientId@.

For example, when publishing a message, the @clientId@ attribute of the message will be pre-populated with that @clientId@. Entering presence will also implicitly use that @clientId@.

Expand Down Expand Up @@ -184,7 +186,7 @@ The following example demonstrates how to issue an "Ably TokenRequest":/auth/tok

h3(#wildcard). Wildcard token auth

You can use "token authentication":/auth/token to set a wildcard @clientId@ using a value of @*@ when creating a token. Clients are then able to assume any identity in their operations, such as when publishing a message or entering presence.
You can use "token authentication":/auth/token to set a wildcard @clientId@ using a value of @*@ when creating a token. Clients are then able to assume any identity in their operations, such as when publishing a message or entering presence.

h2(#unidentified). Unidentified clients

Expand Down
8 changes: 8 additions & 0 deletions content/channels/index.textile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ h2(#create). Create or retrieve a channel

A @Channel@ object is a reference to a single channel and is uniquely identified by its unicode string name. A channel is created, or an existing channel is retrieved from the @Channels@ collection, using the "@get()@":/api/realtime-sdk/channels#get method. You can only connect to one channel in a single operation. Wildcards are not supported.

Although Ably recommends that you use channels to distribute work more evenly across the cluster, there is an associated cost for a high number of channels. Don't use different channels just to indicate different types of data, or different events, if all messages are going to the same set of clients. Use a single channel and distinguish between them using a different message @name@.

Channels are the unit of security and scalability. If you are sending data that must not be shared with certain clients, ensure it is on a channel that those clients don't have the "capabilities":/auth/capabilities to "attach":#attach to.

The following is an example of creating a channel:

```[realtime_javascript]
Expand Down Expand Up @@ -667,6 +671,8 @@ h2(#subscribe). Subscribe to a channel

Subscribe to a channel in order to receive messages being published to it, by registering a listener. Subscribing is an operation available to the realtime interface and uses the "@subscribe()@":/api/realtime-sdk/channels#subscribe method.

Subscribing to events server-side using the Pub/Sub method can be disadvantageous as it can increase latency or duplicate events among multiple servers. "Message Queues":/general/queues are more a appropriate method to use in that instance, as multiple worker servers enable Ably to distribute the load of messages received from published. This means that each message is only processed once by any one of your worker servers.
m-hulbert marked this conversation as resolved.
Show resolved Hide resolved

<div lang="jsall,objc,swift">
A client can subscribe to all messages published to a channel by passing a listener function to the @subscribe()@ method. The listener is passed a "@Message@":/api/realtime-sdk/types#message object for each message received. Alternatively, a client can listen for a subset of messages based on the name of the published message.
</div><div lang="java">
Expand Down Expand Up @@ -1453,6 +1459,8 @@ Previously registered listeners can be removed individually or all together.
stateChangeListener.cancel();
```

Be aware that when registering listeners for channel state changes, certain repeating states may add new listeners each time.

h2(#failure). Handle channel failures

Channel attach and detach operations are asynchronous. After initiating an attach request, the client will wait for a response from Ably that confirms that the channel is established on the service and then trigger a "state change":#states event.
Expand Down
51 changes: 29 additions & 22 deletions content/connect/index.textile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ redirect_from:
- /realtime/versions/v0.8/connection
---

Clients establish and maintain a connection to the Ably service using the most efficient transport available, typically "WebSockets":https://ably.com/topic/websockets. Ably SDKs operate and multiplex all "channel":/channels traffic over that connection. Once connected, clients can monitor and manage their "connection state":/connect/states.
Clients establish and maintain a connection to the Ably service using the most efficient transport available, typically "WebSockets":https://ably.com/topic/websockets. Ably SDKs operate and multiplex all "channel":/channels traffic over that connection. This maximizes throughput, minimizes bandwidth consumption, and reduces power usage. Once connected, clients can monitor and manage their "connection state":/connect/states.

<aside data-type='note'>
<p>Connections can only be established using the realtime interface of an Ably SDK. See "how to use Ably":/basics/use-ably for further information on the differences between the REST and realtime interface.</p>
Expand All @@ -31,7 +31,7 @@ Ably SDKs open and maintain a connection to the Ably realtime servers on instant

This example relies on the default auto-connect behavior of the SDK, checking for when the connection state is @connected@ event:

```[realtime_javascript]
```[realtime_javascript]
// Using callbacks
const ably = new Ably.Realtime({ '{{API_KEY}}' });
ably.connection.on('connected', () => {
Expand All @@ -48,7 +48,7 @@ console.log('Connected to Ably!');
```[realtime_nodejs]
// Using callbacks
const Ably = require('ably');
const ably = new Ably.Realtime({ '{{API_KEY}}' });
const ably = new Ably.Realtime({ '{{API_KEY}}' });
ably.connection.on('connected', () => {
console.log('Connected to Ably!');
});
Expand All @@ -60,7 +60,7 @@ await ably.connection.once("connected");
console.log('Connected to Ably!');
```

```[realtime_ruby]
```[realtime_ruby]
ably = Ably::Realtime.new('{{API_KEY}}')
ably.connection.on(:connected) do
puts "Connected to Ably!"
Expand All @@ -73,7 +73,7 @@ await ably.connection.once_async('connected')
print('Connected to Ably')
```

```[realtime_java]
```[realtime_java]
AblyRealtime ably = new AblyRealtime("{{API_KEY}}");
ably.connection.on(ConnectionEvent.connected, new ConnectionStateListener() {
@Override
Expand All @@ -83,28 +83,28 @@ ably.connection.on(ConnectionEvent.connected, new ConnectionStateListener() {
});
```

```[realtime_csharp]
```[realtime_csharp]
AblyRealtime ably = new AblyRealtime("{{API_KEY}}");
ably.Connection.On(ConnectionEvent.Connected, args => {
Console.WriteLine("Connected to Ably!");
});
```

```[realtime_objc]
```[realtime_objc]
ARTRealtime *ably = [[ARTRealtime alloc] initWithKey:@"{{API_KEY}}"];
[ably.connection on:ARTRealtimeConnectionEventConnected callback:^(ARTConnectionStateChange *change) {
NSLog(@"Connected to Ably!");
}];
```

```[realtime_swift]
```[realtime_swift]
let realtime = ARTRealtime(key: "{{API_KEY}}")
realtime.connection.on(.connected) { change in
print("Connected to Ably!")
}
```

```[realtime_flutter]
```[realtime_flutter]
final realtime = ably.Realtime(key: '{{API_KEY}}');
final channel = realtime
.on(ably.ConnectionStateChange.connected)
Expand All @@ -114,7 +114,7 @@ final channel = realtime
);
```

If you're not using the SDK's auto-connect feature you can also connect with "@connect()@":/api/realtime-sdk/connection#connect to manually connect unless the state is already @connected@ or @connecting@.
If you're not using the SDK's auto-connect feature you can also connect with "@connect()@":/api/realtime-sdk/connection#connect to manually connect unless the state is already @connected@ or @connecting@.

Explicitly calling connect is unnecessary unless the ClientOptions attribute autoConnect is false. Unless already connected or connecting, this method causes the connection to open, entering the connecting state. To manually attempt to open a connection you call the "@connect()@":/api/realtime-sdk/connection#connect function: @ably.connect()@.

Expand Down Expand Up @@ -160,7 +160,7 @@ You can also call "@ping()@":/api/realtime-sdk/connection#ping to send a heartbe

The following example code demonstrates establishing a connection to Ably with a @heartbeatInterval@ of 10 seconds:

```[realtime_javascript]
```[realtime_javascript]
const ably = new Ably.Realtime(
{
key: '{{API_KEY}}',
Expand All @@ -169,7 +169,7 @@ const ably = new Ably.Realtime(
);
```

```[realtime_nodejs]
```[realtime_nodejs]
const ably = new Ably.Realtime(
{
key: '{{API_KEY}}',
Expand All @@ -184,17 +184,17 @@ A connection to Ably should be closed once it is no longer needed. Note that the

The following code sample explicitly closes the connection to Ably by calling the @close()@ method and prints the message @Closed the connection to Ably@:

```[realtime_javascript]
```[realtime_javascript]
ably.close(); // runs synchronously
console.log('Closed the connection to Ably.');
```

```[realtime_nodejs]
```[realtime_nodejs]
ably.close(); // runs synchronously
console.log('Closed the connection to Ably.');
```

```[realtime_java]
```[realtime_java]
ably.connection.close();
ably.connection.on(ConnectionState.closed, new ConnectionStateListener() {
@Override
Expand All @@ -215,19 +215,19 @@ ably.connection.on(ConnectionState.closed, new ConnectionStateListener() {
});
```

```[realtime_python]
```[realtime_python]
await ably.close()
print('Closed the connection to Ably.')
```

```[realtime_ruby]
```[realtime_ruby]
ably.connection.close
ably.connection.on(:closed) do
puts "Closed the connection to Ably!"
end
```

```[realtime_swift]
```[realtime_swift]
ably.connection.close()
ably.connection.on { stateChange in
let stateChange = stateChange
Expand All @@ -242,22 +242,22 @@ ably.connection.on { stateChange in
}
```

```[realtime_csharp]
```[realtime_csharp]
ably.Connection.Close();
ably.Connection.On(ConnectionEvent.Closed, args =>
{
Console.Out.WriteLine("Closed the connection to Ably.");
});
```

```[realtime_objc]
```[realtime_objc]
[ably.connection close];
[ably.connection on:ARTRealtimeConnectionEventClosed callback:^(ARTConnectionStateChange *stateChange) {
NSLog(@"Closed the connection to Ably.");
}];
```

```[realtime_flutter]
```[realtime_flutter]
realtime.connection.close();
realtime.connection
.on(ably.ConnectionEvent.closed)
Expand All @@ -275,9 +275,16 @@ realtime.connection
});
```

```[realtime_go]
```[realtime_go]
client.Connection.On(ably.ConnectionEventClosed, func(change ably.ConnectionStateChange) {
fmt.Println("Closed the connection to Ably.")
})
client.Close()
```

<aside data-type='important'>
<p>It is important to understand the difference between unsubscribing from a "channel":/channels and closing a connection, compared to calling the @off()@ method for a channel or connection.</p>
<p>The "@unsubscribe()@":/api/realtime-sdk/channels#unsubscribe method removes message listeners for a channel.</p>
<p>The "@close()@":/api/realtime-sdk/connection#close method closes a realtime connection.</p>
<p>The @off()@ method for a "channel":/api/realtime-sdk/channels#off or "connection":/api/realtime-sdk/connection#off removes "@ChannelEvent@":/channels#listen-for-state or "@ConnectionEvent@":/connect/states#listen listeners that are listening for state changes on a channel or for a connection.</p>
</aside>
20 changes: 11 additions & 9 deletions content/connect/states.textile
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ languages:

Connections to Ably will transition through multiple states throughout their lifecycle. States can be observed and triggered using methods available on the connection object.

Although connection state is temporary, Ably provides continuity of message delivery between a client and the service provided that a dropped connection is re-established by the client within a limited interval (typically around two minutes). After that time the connection becomes stale and the system will not attempt to recover the connection state.
Although connection state is temporary, Ably provides continuity of message delivery between a client and the service provided that a dropped connection is re-established by the client within a limited interval (typically around two minutes). After that time the connection becomes stale and the system will not attempt to recover the connection state.

An Ably SDK is responsible for managing a connection. This includes:
An Ably SDK is responsible for managing a connection. This includes:

* selecting a transport, when multiple transports are available
* selecting a transport, when multiple transports are available
* selecting a new host to connect to when automatically falling back to an alternate datacenter if needed
* managing continuity of operation when the connection drops

Expand Down Expand Up @@ -183,21 +183,21 @@ Previously registered <span lang="default">listeners</span><span lang="csharp">h

```[realtime_javascript]
/* remove a listener registered for a single event */
realtime.connection.off('connected', myListener);
realtime.connection.off('connected', myListener);

/* remove a listener registered for all events */
realtime.connection.off(myListener);
realtime.connection.off(myListener);

/* remove all event listeners */
realtime.connection.off();
```

```[realtime_nodejs]
/* remove a listener registered for a single event */
realtime.connection.off('connected', myListener);
realtime.connection.off('connected', myListener);

/* remove a listener registered for all events */
realtime.connection.off(myListener);
realtime.connection.off(myListener);

/* remove all event listeners */
realtime.connection.off();
Expand Down Expand Up @@ -260,6 +260,8 @@ Previously registered <span lang="default">listeners</span><span lang="csharp">h
realtime.connection.off()
```

Be aware that when registering listeners for connection state changes certain repeating states may add new listeners each time. For example, registering a listener for @on(connected)@ adds a new listener each time a client becomes connected, even if this is a reconnected after being offline for a period of time.

h2(#connection-state-recovery). Connection state recovery

The Ably system preserves connection state to allow connections to continue transparently across brief disconnections. The connection state that is tracked includes the messages sent to the client on the connection, members present on a channel and the set of channels that the client is attached to.
Expand Down Expand Up @@ -344,7 +346,7 @@ blang[javascript,nodejs].
Alternatively, if it is necessary to be explicit about the connection @recoveryKey@, the connection can be recovered by providing the last value of the connection's @recoveryKey@ value in the "client options":/api/realtime-sdk#client-options @recover@ attribute when instantiating an SDK.

blang[default].


h2(#handling-failures). Handling connection failures

Expand All @@ -360,4 +362,4 @@ h3(#nonfatal-errors). Nonfatal errors

Other classes of error are nonfatal. For example, a client may have network connectivity issues. An SDK will attempt to automatically reconnect and recover from these sort of issues, as detailed in the @DISCONNECTED@ and @SUSPENDED@ explanations in the "Available connection states":#connection-states section.

If message continuity is lost in the process, e.g. because you have been disconnected from Ably for more than two minutes, the SDK will notify you through the "@resumed@":#resume flag mechanism.
If message continuity is lost in the process, e.g. because you have been disconnected from Ably for more than two minutes, the SDK will notify you through the "@resumed@":#resume flag mechanism.
Loading