Skip to content

Commit

Permalink
[ECO-5139] feat: add action and serial fields
Browse files Browse the repository at this point in the history
  • Loading branch information
ttypic committed Nov 27, 2024
1 parent 1ba7723 commit d730716
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,10 @@ private void onMessage(final ProtocolMessage protocolMessage) {
if(msg.connectionId == null) msg.connectionId = protocolMessage.connectionId;
if(msg.timestamp == 0) msg.timestamp = protocolMessage.timestamp;
if(msg.id == null) msg.id = protocolMessage.id + ':' + i;
// (TM2p)
if(msg.version == null) msg.version = String.format("%s:%03d", protocolMessage.channelSerial, i);
// (TM2k)
if(msg.serial == null) msg.serial = msg.version;

try {
msg.decode(options, decodingContext);
Expand Down
14 changes: 14 additions & 0 deletions lib/src/main/java/io/ably/lib/types/BaseMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,20 @@ protected Long readLong(final JsonObject map, final String key) {
return element.getAsLong();
}

/**
* Read an optional numerical value.
* @return The value, or null if the key was not present in the map.
* @throws ClassCastException if an element exists for that key and that element is not a {@link JsonPrimitive}
* or is not a valid int value.
*/
protected Integer readInt(final JsonObject map, final String key) {
final JsonElement element = map.get(key);
if (null == element || element instanceof JsonNull) {
return null;
}
return element.getAsInt();
}

/* Msgpack processing */
boolean readField(MessageUnpacker unpacker, String fieldName, MessageFormat fieldType) throws IOException {
boolean result = true;
Expand Down
59 changes: 59 additions & 0 deletions lib/src/main/java/io/ably/lib/types/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,33 @@ public class Message extends BaseMessage {
*/
public String connectionKey;

/**
* (TM2k) serial string – an opaque string that uniquely identifies the message. If a message received from Ably
* (whether over realtime or REST, eg history) with an action of MESSAGE_CREATE does not contain a serial,
* the SDK must set it equal to its version.
*/
public String serial;

/**
* (TM2p) version string – an opaque string that uniquely identifies the message, and is different for different versions.
* If a message received from Ably over a realtime transport does not contain a version,
* the SDK must set it to <channelSerial>:<padded_index> from the channelSerial field of the enclosing ProtocolMessage,
* and padded_index is the index of the message inside the messages array of the ProtocolMessage,
* left-padded with 0s to three digits (for example, the second entry might be foo:001)
*/
public String version;

/**
* (TM2j) action enum
*/
public MessageAction action;

private static final String NAME = "name";
private static final String EXTRAS = "extras";
private static final String CONNECTION_KEY = "connectionKey";
private static final String SERIAL = "serial";
private static final String VERSION = "version";
private static final String ACTION = "action";

/**
* Default constructor
Expand Down Expand Up @@ -128,6 +152,9 @@ void writeMsgpack(MessagePacker packer) throws IOException {
int fieldCount = super.countFields();
if(name != null) ++fieldCount;
if(extras != null) ++fieldCount;
if(serial != null) ++fieldCount;
if(version != null) ++fieldCount;
if(action != null) ++fieldCount;
packer.packMapHeader(fieldCount);
super.writeFields(packer);
if(name != null) {
Expand All @@ -138,6 +165,18 @@ void writeMsgpack(MessagePacker packer) throws IOException {
packer.packString(EXTRAS);
extras.write(packer);
}
if(serial != null) {
packer.packString(SERIAL);
packer.packString(serial);
}
if(version != null) {
packer.packString(VERSION);
packer.packString(version);
}
if(action != null) {
packer.packString(ACTION);
packer.packInt(action.ordinal());
}
}

Message readMsgpack(MessageUnpacker unpacker) throws IOException {
Expand All @@ -157,6 +196,12 @@ Message readMsgpack(MessageUnpacker unpacker) throws IOException {
name = unpacker.unpackString();
} else if (fieldName.equals(EXTRAS)) {
extras = MessageExtras.read(unpacker);
} else if (fieldName.equals(SERIAL)) {
serial = unpacker.unpackString();
} else if (fieldName.equals(VERSION)) {
version = unpacker.unpackString();
} else if (fieldName.equals(ACTION)) {
action = MessageAction.tryFindByOrdinal(unpacker.unpackInt());
} else {
Log.v(TAG, "Unexpected field: " + fieldName);
unpacker.skipValue();
Expand Down Expand Up @@ -313,6 +358,11 @@ protected void read(final JsonObject map) throws MessageDecodeException {
}
extras = MessageExtras.read((JsonObject) extrasElement);
}

serial = readString(map, SERIAL);
version = readString(map, VERSION);
Integer actionOrdinal = readInt(map, ACTION);
action = actionOrdinal == null ? null : MessageAction.tryFindByOrdinal(actionOrdinal);
}

public static class Serializer implements JsonSerializer<Message>, JsonDeserializer<Message> {
Expand All @@ -328,6 +378,15 @@ public JsonElement serialize(Message message, Type typeOfMessage, JsonSerializat
if (message.connectionKey != null) {
json.addProperty(CONNECTION_KEY, message.connectionKey);
}
if (message.serial != null) {
json.addProperty(SERIAL, message.serial);
}
if (message.version != null) {
json.addProperty(VERSION, message.version);
}
if (message.action != null) {
json.addProperty(ACTION, message.action.ordinal());
}
return json;
}

Expand Down
15 changes: 15 additions & 0 deletions lib/src/main/java/io/ably/lib/types/MessageAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.ably.lib.types;

public enum MessageAction {
MESSAGE_UNSET, // 0
MESSAGE_CREATE, // 1
MESSAGE_UPDATE, // 2
MESSAGE_DELETE, // 3
ANNOTATION_CREATE, // 4
ANNOTATION_DELETE, // 5
META_OCCUPANCY; // 6

static MessageAction tryFindByOrdinal(int ordinal) {
return values().length <= ordinal ? null: values()[ordinal];
}
}
65 changes: 65 additions & 0 deletions lib/src/test/java/io/ably/lib/types/MessageTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,69 @@ public void serialize_message_with_name_and_data() {
assertEquals("test-data", serializedObject.get("data").getAsString());
assertEquals("test-name", serializedObject.get("name").getAsString());
}

@Test
public void serialize_message_with_serial() {
// Given
Message message = new Message("test-name", "test-data");
message.clientId = "test-client-id";
message.connectionKey = "test-key";
message.action = MessageAction.MESSAGE_CREATE;
message.serial = "01826232498871-001@abcdefghij:001";

// When
JsonElement serializedElement = serializer.serialize(message, null, null);

// Then
JsonObject serializedObject = serializedElement.getAsJsonObject();
assertEquals("test-client-id", serializedObject.get("clientId").getAsString());
assertEquals("test-key", serializedObject.get("connectionKey").getAsString());
assertEquals("test-data", serializedObject.get("data").getAsString());
assertEquals("test-name", serializedObject.get("name").getAsString());
assertEquals(1, serializedObject.get("action").getAsInt());
assertEquals("01826232498871-001@abcdefghij:001", serializedObject.get("serial").getAsString());
}

@Test
public void deserialize_message_with_serial() throws Exception {
// Given
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("clientId", "test-client-id");
jsonObject.addProperty("data", "test-data");
jsonObject.addProperty("name", "test-name");
jsonObject.addProperty("action", 1);
jsonObject.addProperty("serial", "01826232498871-001@abcdefghij:001");

// When
Message message = Message.fromEncoded(jsonObject, new ChannelOptions());

// Then
assertEquals("test-client-id", message.clientId);
assertEquals("test-data", message.data);
assertEquals("test-name", message.name);
assertEquals(MessageAction.MESSAGE_CREATE, message.action);
assertEquals("01826232498871-001@abcdefghij:001", message.serial);
}


@Test
public void deserialize_message_with_unknown_action() throws Exception {
// Given
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("clientId", "test-client-id");
jsonObject.addProperty("data", "test-data");
jsonObject.addProperty("name", "test-name");
jsonObject.addProperty("action", 10);
jsonObject.addProperty("serial", "01826232498871-001@abcdefghij:001");

// When
Message message = Message.fromEncoded(jsonObject, new ChannelOptions());

// Then
assertEquals("test-client-id", message.clientId);
assertEquals("test-data", message.data);
assertEquals("test-name", message.name);
assertNull(message.action);
assertEquals("01826232498871-001@abcdefghij:001", message.serial);
}
}

0 comments on commit d730716

Please sign in to comment.