We have made many breaking changes in the version 1.2 release of this SDK.
In this guide we aim to highlight the main differences you will encounter when migrating your code from the interfaces we were offering prior to the version 1.2.0 release.
These include:
- Changes to numerous function and method signatures - these are breaking changes, in that your code will need to change to use them in their new form
- Adoption of the Context Concurrency Pattern using the context package - e.g. ably.RealtimeChannel.Subscribe
- Adoption of the Functional Options Pattern - e.g. ably.ClientOption
We've now moved to a model where methods are blocking in nature, cancellable with a Context.
We use ctx
in examples to refer to a Context
instance that you create in your code.
For robust, production-ready applications you will rarely (actually, probably never) want to create your Context
using the basic Background function, because it cannot be cancelled and remains for the lifecycle of the program. Instead, you should use WithTimeout or WithDeadline.
For example, a context can be created with a 10-second timeout like this:
context.WithTimeout(context.Background(), 10 * time.Second)
Adding the necessary code to stay on top of cancellation, you will need something like this:
ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
defer cancel()
This way, the context can be cancelled at the close of the function.
Note: For Realtime operations, cancellation isn't supported by the underlying protocol. A context cancellation in this case just means that the call returns immediately, without waiting for the operation to finish, with the error provided by the context; but the operation carries on in the background. Timeouts for these operations are handled separately, with a configurable realtime request timeout duration.
Before version 1.2.0, you instantiated a client using a ClientOptions
instance created with the NewClientOptions
function:
client, err := ably.NewRealtime(ably.NewClientOptions("xxx:xxx"))
Starting with version 1.2.0, you must use the new functional interface:
client, err := ably.NewRealtime(ably.WithKey("xxx:xxx"))
For a full list of client options, see all functions prefixed by With
that return a ClientOption
function
in the API reference.
Before version 1.2.0, you subscribed to receive all messages from a Go channel like this:
sub, _ := channel.Subscribe()
for msg := range sub.MessageChannel() {
fmt.Println("Received message: ", msg)
}
Starting with version 1.2.0, you must supply a context and your own message handler function to the new SubscribeAll method:
unsubscribe, _ := channel.SubscribeAll(ctx, func(msg *ably.Message) {
fmt.Println("Received message: ", msg)
})
The signature of the Subscribe method has also changed. It now requires a Context as well as the channel name and your message handler.
Both Subscribe
and SubscribeAll
are now blocking methods.
Detail around the concurrency and routing of calls to message and event handlers is described in the package documentation under Event Emitters.
Before version 1.2.0, you published messages to a channel by calling the Publish
method and then waiting for the Result
:
result, _ := channel.Publish("EventName1", "EventData1")
// block until the publish operation completes
result.Wait()
Starting with version 1.2.0, you must supply a context, as this method is now blocking:
// block until the publish operation completes or is cancelled
err := channel.Publish(ctx, "EventName1", "EventData1")
Before version 1.2.0, you queried history as shown below, receiving a PaginatedResult
from the History
function:
page, err := channel.History(nil)
for ; err == nil; page, err = page.Next() {
for _, message := range page.Messages() {
fmt.Println("Message from History: ", message)
}
}
if err != nil {
panic(err)
}
Starting with version 1.2.0, you must first call History
, which can be passed functional options, and then use the Pages (or Items, if you prefer) method on the returned HistoryRequest
instance
pages, err := channel.History().Pages(ctx)
if err != nil {
panic(err)
}
for pages.Next(ctx) {
for _, message := range pages.Items() {
fmt.Println("Message from History: ", message)
}
}
if err := pages.Err(); err != nil {
panic(err)
}