Skip to content

Commit 2c7beb4

Browse files
Rebase: Aligns with latest main branch changes
1 parent 0474da3 commit 2c7beb4

File tree

1 file changed

+153
-18
lines changed

1 file changed

+153
-18
lines changed

content/channels/index.textile

+153-18
Original file line numberDiff line numberDiff line change
@@ -753,56 +753,191 @@ channel.Publish(context.Background(), "action", "boom!")
753753

754754
h3(#idempotency). Idempotent publish
755755

756-
Idempotency ensures that multiple publishes of the same message cannot result in duplicate messages.
756+
Idempotent publishing ensures that multiple attempts to publish the same message do not result in duplicate messages. This feature is essential when network issues may cause a client to reattempt message publication without knowing if the initial attempt succeeded.
757757

758+
<<<<<<< HEAD
758759
It is possible that a client publishing a message using the REST interface may not receive acknowledgement of receipt from Ably, due to issues such as network failure outside of Ably's control. Clients will internally attempt to re-publish messages in these instances.
759760

760761
When idempotent publishing is enabled, the Ably SDK will internally assign a unique ID to each message which ensures that subsequent retry attempts cannot result in duplicate messages. Idempotent publishing is enabled by default in all latest Ably SDKs. It can be disabled by setting the @idempotentRestPublishing@ "@ClientOptions@":/api/rest-sdk#client-options to @false@.
761762

762763
Note that Ably can only detect duplicate messages within a 2-minute window after the original message, with the same ID, is published. If a message with the same ID is published after this 2-minute window, it will be treated as a new message.
763764

764765
You can also specify message IDs externally. The following is an example of how you might do this:
766+
=======
767+
h4. Automatic idempotency
765768

766-
```[rest_javascript]
767-
const rest = new Ably.Rest('{{API_KEY}}');
768-
const channel = rest.channels.get('{{RANDOM_CHANNEL_NAME}}');
769-
await channel.publish([{data: 'payload', id: 'unique123'}]);
769+
For versions 1.2 and later of the Ably library, idempotent publishing is enabled by default. This means the Ably SDK automatically assigns a unique ID to each message to prevent duplicates during retries. This functionality applies to both REST and realtime publishing.
770+
For older versions (before 1.2), this feature was not enabled by default for publishing. However, it could be activated using @idempotentRestPublishing@ in "@ClientOptions@":/api/rest-sdk#client-optionsidempotentRestPublishing.
771+
772+
h4. Client ID idempotency
773+
774+
There are scenarios where specifying a client-supplied ID to achieve idempotency are necessary, such as:
775+
776+
* Ensuring idempotency when a publisher instance might be restarted, and continuous activity cannot be guaranteed.
777+
* Integrating with an upstream system that uses its message IDs, ensuring idempotency across an entire message processing pipeline.
778+
779+
In these cases, you can manually specify the message ID for REST and realtime publishing.
780+
781+
The following example manually specifies a message ID:
782+
783+
```[realtime_javascript]
784+
const realtime = new Ably.Realtime = '{{API_KEY}}';
785+
const channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}');
786+
const message = [{ data: 'payload', id: 'unique123' }];
770787
```
771788

772-
```[rest_go]
773-
rest, err := ably.NewREST(
789+
```[realtime_nodejs]
790+
const realtime = new Ably.Realtime = '{{API_KEY}}';
791+
const channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}');
792+
const message = [{ data: 'payload', id: 'unique123' }];
793+
```
794+
795+
```[realtime_ruby]
796+
realtime = Ably::Realtime.new(key: '{{API_KEY}}')
797+
channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}')
798+
channel.publish(name: 'example', data: 'payload', id: 'unique123')
799+
```
800+
801+
```[realtime_python]
802+
realtime = AblyRealtime('{{API_KEY}}')
803+
channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}')
804+
await channel.publish([{data: 'payload', id: 'unique123'}])
805+
```
806+
807+
```[realtime_java]
808+
ClientOptions options = new ClientOptions('{{API_KEY}}');
809+
AblyRealtime ably = new AblyRealtime(options);
810+
Channel channel = ably.channels.get('{{RANDOM_CHANNEL_NAME}}');
811+
812+
Message message = new Message();
813+
message.data = "payload";
814+
message.id = "unique123";
815+
```
816+
817+
```[realtime_csharp]
818+
ARTRealtime *realtime = [[ARTRealtime alloc] initWithKey:@"{{API_KEY}}"];
819+
ARTRealtimeChannel *channel = [realtime.channels get:@"{{RANDOM_CHANNEL_NAME}}"];
820+
channel publish:@"example" data:@"payload" id:@"unique123" callback:^(ARTErrorInfo *error)
821+
```
822+
823+
```[realtime_swift]
824+
let realtime = ARTRealtime(key: "{{API_KEY}}")
825+
let channel = realtime.channels.get("{{RANDOM_CHANNEL_NAME}}")
826+
channel.publish("example", data: "message data", id: "unique123")
827+
```
828+
829+
```[realtime_objc]
830+
ARTRealtime *realtime = [[ARTRealtime alloc] initWithKey:("{{API_KEY}}"));
831+
ARTRealtimeChannel *channel = [realtime.channels get:("{{RANDOM_CHANNEL_NAME}}");
832+
[channel.publish("example", data: "message data", id: "unique123")];
833+
```
834+
835+
```[realtime_flutter]
836+
final clientOptions = ably.ClientOptions(key: '{{API_KEY}}');
837+
final realtime = ably.Realtime(options: clientOptions);
838+
final channel = realtime.channels.get('{{RANDOM_CHANNEL_NAME}}');
839+
await message = ably.Message(data: 'payload', id: 'unique123');
840+
```
841+
842+
```[realtime_go]
843+
realtime, err := ably.NewRealtime(
774844
ably.WithKey("{{API_KEY}}"))
775845
if err != nil {
776846
log.Fatalf("Error creating Ably client: %v", err)
777847
}
778848

779-
channel := rest.Channels.Get("{{RANDOM_CHANNEL_NAME}}")
849+
channel := realtime.Channels.Get("{{RANDOM_CHANNEL_NAME}}")
780850

781851
message := &ably.Message{
782852
Data: "payload",
783853
ID: "unique123",
784854
}
855+
```
856+
>>>>>>> 4bfa4c08 (EDU-1469: Re-writes idempotent publishing section to improve clarity to the reader)
785857

786-
// Publish the message to the channel
787-
err = channel.Publish(context.Background(), "eventName", message)
788-
if err != nil {
789-
log.Fatalf("Error publishing message: %v", err)
790-
}
858+
```[rest_javascript]
859+
const rest = new Ably.Rest = '{{API_KEY}}';
860+
const channel = rest.channels.get('{{RANDOM_CHANNEL_NAME}}');
861+
const message = [{ data: 'payload', id: 'unique123' }];
862+
```
863+
864+
```[rest_nodejs]
865+
const rest = new Ably.Rest = '{{API_KEY}}';
866+
const channel = rest.channels.get('{{RANDOM_CHANNEL_NAME}}');
867+
const message = [{ data: 'payload', id: 'unique123' }];
868+
```
869+
870+
```[rest_ruby]
871+
rest = Ably::Rest.new(key: '{{API_KEY}}')
872+
channel = rest.channels.get('{{RANDOM_CHANNEL_NAME}}')
873+
channel.publish(name: 'example', data: 'payload', id: 'unique123')
874+
```
875+
876+
```[rest_python]
877+
rest = AblyRest('{{API_KEY}}')
878+
channel = rest.channels.get('{{RANDOM_CHANNEL_NAME}}')
879+
await channel.publish([{data: 'payload', id: 'unique123'}])
880+
```
881+
882+
```[rest_php]
883+
$rest = new Ably\AblyRest('{{API_KEY}}');
884+
$channel = $rest->channels->get('{{RANDOM_CHANNEL_NAME}}')
885+
$channel->publish([{data: 'payload', id: 'unique123'}]);
791886
```
792887

793888
```[rest_java]
794-
ClientOptions options = new ClientOptions("{{API_KEY}}");
795-
AblyRealtime ably = new AblyRealtime(options);
796-
Channel channel = ably.channels.get("{{RANDOM_CHANNEL_NAME}}");
889+
ClientOptions options = new ClientOptions('{{API_KEY}}');
890+
AblyRest ably = new AblyRest(options);
891+
Channel channel = ably.channels.get('{{RANDOM_CHANNEL_NAME}}');
797892

798893
Message message = new Message();
799894
message.data = "payload";
800895
message.id = "unique123";
896+
```
801897

802-
channel.publish(new Message[]{message});
898+
```[rest_csharp]
899+
ARTRealtime *rest = [[ARTRealtime alloc] initWithKey:@"{{API_KEY}}"];
900+
ARTRealtimeChannel *channel = [rest.channels get:@"{{RANDOM_CHANNEL_NAME}}"];
901+
channel publish:@"example" data:@"payload" id:@"unique123" callback:^(ARTErrorInfo *error)
803902
```
804903

805-
If manually specifying message IDs, it is important to be aware of how messages are published when calling the "publish()":/api/rest-sdk/channels#publish method with an array of messages. See this "FAQ":https://faqs.ably.com/client-specified-message-id-restrictions-for-multiple-messages-published-atomically for further information.
904+
```[rest_swift]
905+
let rest = ARTRest(key: "{{API_KEY}}")
906+
var channel = rest.channels.get("{{RANDOM_CHANNEL_NAME}}")
907+
channel.publish("example", data: "message data", id: "unique123")
908+
```
909+
910+
```[rest_objc]
911+
ARTRest *rest = [[ARTRest alloc] initWithKey:("{{API_KEY}}"));
912+
ARTRestChannel *channel = [rest.channels get:("{{RANDOM_CHANNEL_NAME}}");
913+
[channel.publish("example", data: "message data", id: "unique123")];
914+
```
915+
916+
```[rest_flutter]
917+
final clientOptions = ably.ClientOptions(key: '{{API_KEY}}');
918+
final rest = ably.Rest(options: clientOptions);
919+
final channel = rest.channels.get('{{RANDOM_CHANNEL_NAME}}');
920+
await message = ably.Message(data: 'payload', id: 'unique123');
921+
```
922+
923+
```[rest_go]
924+
rest, err := ably.NewREST(
925+
ably.WithKey("{{API_KEY}}"))
926+
if err != nil {
927+
log.Fatalf("Error creating Ably client: %v", err)
928+
}
929+
930+
channel := rest.Channels.Get("{{RANDOM_CHANNEL_NAME}}")
931+
932+
message := &ably.Message{
933+
Data: "payload",
934+
ID: "unique123",
935+
}
936+
```
937+
938+
h4. Restrictions and considerations
939+
940+
When specifying custom message IDs, particularly when attempting to "@publish()@":/api/rest-sdk/channels#publish multiple messages atomically with idempotency, ensure that the IDs adhere to the format restrictions. For more details on these restrictions, refer to the "FAQ":https://faqs.ably.com/client-specified-message-id-restrictions-for-multiple-messages-published-atomically.
806941

807942
h3(#publish-on-behalf). Use the REST interface to publish on behalf of a realtime connection
808943

0 commit comments

Comments
 (0)