Skip to content

Commit 16d372d

Browse files
authored
Merge pull request #1179 from ably/ECO-5642/edit-deletes-api
[ECO-5642] feat: add message editing support to channels
2 parents cd51650 + c6cf81d commit 16d372d

File tree

8 files changed

+1390
-10
lines changed

8 files changed

+1390
-10
lines changed

lib/src/main/java/io/ably/lib/realtime/ChannelBase.java

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import io.ably.lib.http.HttpUtils;
1717
import io.ably.lib.objects.RealtimeObjects;
1818
import io.ably.lib.objects.LiveObjectsPlugin;
19+
import io.ably.lib.rest.MessageEditsMixin;
1920
import io.ably.lib.rest.RestAnnotations;
2021
import io.ably.lib.transport.ConnectionManager;
2122
import io.ably.lib.transport.ConnectionManager.QueuedMessage;
@@ -32,6 +33,7 @@
3233
import io.ably.lib.types.Message;
3334
import io.ably.lib.types.MessageAnnotations;
3435
import io.ably.lib.types.MessageDecodeException;
36+
import io.ably.lib.types.MessageOperation;
3537
import io.ably.lib.types.MessageSerializer;
3638
import io.ably.lib.types.MessageVersion;
3739
import io.ably.lib.types.PaginatedResult;
@@ -100,6 +102,8 @@ public abstract class ChannelBase extends EventEmitter<ChannelEvent, ChannelStat
100102

101103
@Nullable private final LiveObjectsPlugin liveObjectsPlugin;
102104

105+
private volatile MessageEditsMixin messageEditsMixin;
106+
103107
public RealtimeObjects getObjects() throws AblyException {
104108
if (liveObjectsPlugin == null) {
105109
throw AblyException.fromErrorInfo(
@@ -1172,6 +1176,172 @@ else if(!"false".equalsIgnoreCase(param.value)) {
11721176
private static final String KEY_UNTIL_ATTACH = "untilAttach";
11731177
private static final String KEY_FROM_SERIAL = "fromSerial";
11741178

1179+
//region Message Edits and Deletes
1180+
1181+
/**
1182+
* Retrieves the latest version of a specific message by its serial identifier.
1183+
* <p>
1184+
* This method allows you to fetch the current state of a message, including any updates
1185+
* or deletions that have been applied since its creation.
1186+
*
1187+
* @param serial The unique serial identifier of the message to retrieve.
1188+
* @return A {@link Message} object representing the latest version of the message.
1189+
* @throws AblyException If the message cannot be retrieved or does not exist.
1190+
*/
1191+
public Message getMessage(String serial) throws AblyException {
1192+
return messageEditsMixin.getMessage(ably.http, serial);
1193+
}
1194+
1195+
/**
1196+
* Asynchronously retrieves the latest version of a specific message by its serial identifier.
1197+
*
1198+
* @param serial The unique serial identifier of the message to retrieve.
1199+
* @param callback A callback to handle the result asynchronously.
1200+
* <p>
1201+
* This callback is invoked on a background thread.
1202+
*/
1203+
public void getMessageAsync(String serial, Callback<Message> callback) {
1204+
messageEditsMixin.getMessageAsync(ably.http, serial, callback);
1205+
}
1206+
1207+
/**
1208+
* Updates an existing message using patch semantics.
1209+
* <p>
1210+
* Non-null fields in the provided message (name, data, extras) will replace the corresponding
1211+
* fields in the existing message, while null fields will be left unchanged.
1212+
*
1213+
* @param message A {@link Message} object containing the fields to update and the serial identifier.
1214+
* Only non-null fields will be applied to the existing message.
1215+
* @param operation operation metadata such as clientId, description, or metadata in the version field
1216+
* @throws AblyException If the update operation fails.
1217+
*/
1218+
public void updateMessage(Message message, MessageOperation operation) throws AblyException {
1219+
messageEditsMixin.updateMessage(ably.http, message, operation);
1220+
}
1221+
1222+
/**
1223+
* Updates an existing message using patch semantics.
1224+
* <p>
1225+
* Non-null fields in the provided message (name, data, extras) will replace the corresponding
1226+
* fields in the existing message, while null fields will be left unchanged.
1227+
*
1228+
* @param message A {@link Message} object containing the fields to update and the serial identifier.
1229+
* Only non-null fields will be applied to the existing message.
1230+
* @throws AblyException If the update operation fails.
1231+
*/
1232+
public void updateMessage(Message message) throws AblyException {
1233+
updateMessage(message, null);
1234+
}
1235+
1236+
/**
1237+
* Asynchronously updates an existing message.
1238+
*
1239+
* @param message A {@link Message} object containing the fields to update and the serial identifier.
1240+
* @param operation operation metadata such as clientId, description, or metadata in the version field
1241+
* @param listener A listener to be notified of the outcome of this operation.
1242+
* <p>
1243+
* This listener is invoked on a background thread.
1244+
*/
1245+
public void updateMessageAsync(Message message, MessageOperation operation, CompletionListener listener) {
1246+
messageEditsMixin.updateMessageAsync(ably.http, message, operation, listener);
1247+
}
1248+
1249+
/**
1250+
* Asynchronously updates an existing message.
1251+
*
1252+
* @param message A {@link Message} object containing the fields to update and the serial identifier.
1253+
* @param listener A listener to be notified of the outcome of this operation.
1254+
* <p>
1255+
* This listener is invoked on a background thread.
1256+
*/
1257+
public void updateMessageAsync(Message message, CompletionListener listener) {
1258+
updateMessageAsync(message, null, listener);
1259+
}
1260+
1261+
/**
1262+
* Marks a message as deleted.
1263+
* <p>
1264+
* This operation does not remove the message from history; it marks it as deleted
1265+
* while preserving the full message history. The deleted message can still be
1266+
* retrieved and will have its action set to MESSAGE_DELETE.
1267+
*
1268+
* @param message A {@link Message} message containing the serial identifier.
1269+
* @param operation operation metadata such as clientId, description, or metadata in the version field
1270+
* @throws AblyException If the delete operation fails.
1271+
*/
1272+
public void deleteMessage(Message message, MessageOperation operation) throws AblyException {
1273+
messageEditsMixin.deleteMessage(ably.http, message, operation);
1274+
}
1275+
1276+
/**
1277+
* Marks a message as deleted.
1278+
* <p>
1279+
* This operation does not remove the message from history; it marks it as deleted
1280+
* while preserving the full message history. The deleted message can still be
1281+
* retrieved and will have its action set to MESSAGE_DELETE.
1282+
*
1283+
* @param message A {@link Message} message containing the serial identifier.
1284+
* @throws AblyException If the delete operation fails.
1285+
*/
1286+
public void deleteMessage(Message message) throws AblyException {
1287+
deleteMessage(message, null);
1288+
}
1289+
1290+
/**
1291+
* Asynchronously marks a message as deleted.
1292+
*
1293+
* @param message A {@link Message} object containing the serial identifier and operation metadata.
1294+
* @param operation operation metadata such as clientId, description, or metadata in the version field
1295+
* @param listener A listener to be notified of the outcome of this operation.
1296+
* <p>
1297+
* This listener is invoked on a background thread.
1298+
*/
1299+
public void deleteMessageAsync(Message message, MessageOperation operation, CompletionListener listener) {
1300+
messageEditsMixin.deleteMessageAsync(ably.http, message, operation, listener);
1301+
}
1302+
1303+
/**
1304+
* Asynchronously marks a message as deleted.
1305+
*
1306+
* @param message A {@link Message} object containing the serial identifier and operation metadata.
1307+
* @param listener A listener to be notified of the outcome of this operation.
1308+
* <p>
1309+
* This listener is invoked on a background thread.
1310+
*/
1311+
public void deleteMessageAsync(Message message, CompletionListener listener) {
1312+
deleteMessageAsync(message, null, listener);
1313+
}
1314+
1315+
/**
1316+
* Retrieves all historical versions of a specific message.
1317+
* <p>
1318+
* This method returns a paginated result containing all versions of the message,
1319+
* ordered chronologically. Each version includes metadata about when and by whom
1320+
* the message was modified.
1321+
*
1322+
* @param serial The unique serial identifier of the message.
1323+
* @param params Query parameters for filtering or pagination (e.g., limit, start, end).
1324+
* @return A {@link PaginatedResult} containing an array of {@link Message} objects
1325+
* representing all versions of the message.
1326+
* @throws AblyException If the versions cannot be retrieved.
1327+
*/
1328+
public PaginatedResult<Message> getMessageVersions(String serial, Param[] params) throws AblyException {
1329+
return messageEditsMixin.getMessageVersions(ably.http, serial, params);
1330+
}
1331+
1332+
/**
1333+
* Asynchronously retrieves all historical versions of a specific message.
1334+
*
1335+
* @param serial The unique serial identifier of the message.
1336+
* @param params Query parameters for filtering or pagination.
1337+
* @param callback A callback to handle the result asynchronously.
1338+
*/
1339+
public void getMessageVersionsAsync(String serial, Param[] params, Callback<AsyncPaginatedResult<Message>> callback) throws AblyException {
1340+
messageEditsMixin.getMessageVersionsAsync(ably.http, serial, params, callback);
1341+
}
1342+
1343+
//endregion
1344+
11751345
/************************************
11761346
* Channel history
11771347
************************************/
@@ -1278,6 +1448,7 @@ public void setOptions(ChannelOptions options) throws AblyException {
12781448
*/
12791449
public void setOptions(ChannelOptions options, CompletionListener listener) throws AblyException {
12801450
this.options = options;
1451+
this.messageEditsMixin = new MessageEditsMixin(basePath, ably.options, options, ably.auth);
12811452
if(this.shouldReattachToSetOptions(options)) {
12821453
this.attach(true, listener);
12831454
} else {
@@ -1353,6 +1524,7 @@ else if(stateChange.current.equals(failureState)) {
13531524
this,
13541525
new RestAnnotations(name, ably.http, ably.options, options)
13551526
);
1527+
this.messageEditsMixin = new MessageEditsMixin(basePath, ably.options, options, ably.auth);
13561528
}
13571529

13581530
void onChannelMessage(ProtocolMessage msg) {

0 commit comments

Comments
 (0)