[AIT-1009] Implement Json and MsgPack serializers for path-based LiveObjects#1218
Conversation
|
Warning Review limit reached
More reviews will be available in 54 minutes and 58 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Implemented JsonSerializer annotation for better json handling
Point the JSON and MsgPack serializers in io.ably.lib.object.serialization
at the new WireObjectMessage wire model instead of the legacy
io.ably.lib.objects.ObjectMessage, so the new `object` package has no
dependency on the legacy `objects` package.
- DefaultSerialization: implement the new ObjectSerializer interface and
(de)serialize WireObjectMessage arrays (reflectively loaded via
ObjectSerializer.Holder).
- Json/MsgpackSerialization: bind the Wire* types; replace legacy
objectError with the object package's objectStateError (same 500/92000).
- WireObjectMessage: restore the gson annotations required for wire-format
fidelity - @SerializedName("object") on objectState and
@JsonAdapter(WireObjectDataJsonSerializer) on WireObjectData.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes checkstyle AvoidStarImport violation on com.google.gson.*. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Caution Review failedAn error occurred during the review process. Please try again later. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
b69d950 to
bfa574f
Compare
There was a problem hiding this comment.
Pull request overview
Adds the wire-format serialization layer for the path-based LiveObjects API (io.ably.lib.object), providing JSON and MessagePack codecs for the Wire* object-message model while keeping the core lib module decoupled from the optional liveobjects plugin via reflective loading.
Changes:
- Introduces
ObjectSerializer(+ObjectJsonSerializer) inlib, with a lazy reflectively-loaded plugin implementation. - Adds
DefaultObjectsSerializerplus JSON/MsgPack encoding/decoding forWireObjectMessagearrays inliveobjects. - Updates the
Wire*model with Gson annotations needed for wire-format fidelity (e.g.,"object"field name andWireObjectDataJSON-as-string handling).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| liveobjects/src/main/kotlin/io/ably/lib/object/serialization/MsgpackSerialization.kt | MessagePack (de)serialization for the path-based Wire* object model. |
| liveobjects/src/main/kotlin/io/ably/lib/object/serialization/JsonSerialization.kt | Gson configuration + enum-by-code adapters + WireObjectData JSON-as-string adapter. |
| liveobjects/src/main/kotlin/io/ably/lib/object/serialization/DefaultSerialization.kt | Plugin-side ObjectSerializer implementation for JSON/MsgPack arrays of WireObjectMessage. |
| liveobjects/src/main/kotlin/io/ably/lib/object/message/WireObjectMessage.kt | Wire model updates: Gson annotations for "object" and WireObjectData adapter. |
| lib/src/main/java/io/ably/lib/object/serialization/ObjectSerializer.java | Core-side serializer interface + reflective singleton loader for plugin implementation. |
| lib/src/main/java/io/ably/lib/object/serialization/ObjectJsonSerializer.java | Gson serializer/deserializer for the protocol state field via ObjectSerializer.tryGet(). |
| lib/src/main/java/io/ably/lib/object/LiveObjectsPlugin.java | Core-side reflective plugin initializer interface for LiveObjects functionality. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (action == null) { | ||
| throw objectStateError("Missing required 'action' field in WireObjectOperation") | ||
| } | ||
|
|
||
| return WireObjectOperation( |
|
|
||
| return WireObjectState( |
| ObjectSerializer serializer = ObjectSerializer.tryGet(); | ||
| if (serializer == null) { | ||
| Log.w(TAG, "Skipping 'state' field json deserialization because ObjectsSerializer not found."); | ||
| return null; | ||
| } |
| ObjectSerializer serializer = ObjectSerializer.tryGet(); | ||
| if (serializer == null) { | ||
| Log.w(TAG, "Skipping 'state' field json serialization because ObjectsSerializer not found."); | ||
| return JsonNull.INSTANCE; | ||
| } |
| } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | | ||
| NoSuchMethodException | | ||
| InvocationTargetException e) { | ||
| Log.w(TAG, "Failed to init ObjectsSerializer, LiveObjects plugin not included in the classpath", e); | ||
| return null; | ||
| } |
| internal class DefaultObjectsSerializer : ObjectSerializer { | ||
|
|
||
| override fun readMsgpackArray(unpacker: MessageUnpacker): Array<Any> { | ||
| val objectMessagesCount = unpacker.unpackArrayHeader() | ||
| return Array(objectMessagesCount) { readObjectMessage(unpacker) } |
Summary
Adds the serialization layer for the path-based LiveObjects API (
io.ably.lib.object), supporting both JSON and MessagePack encoding/decoding of object messages. This is the wire-format plumbing that sits underneath the path-based public API.The design keeps the core
libfree of any hard dependency on the optional LiveObjects plugin: the core declares interfaces and reflectively loads the implementation from theliveobjectsmodule at runtime, returningnullwhen the plugin is absent.Core (
lib)ObjectSerializer— public interface declaring the four codec entry points (readMsgpackArray/writeMsgpackArray/readFromJsonArray/asJsonArray). The implementation is loaded reflectively and cached as a lazy singleton via a nestedHolder(double-checked locking; retries until the plugin is present), exposed through the staticObjectSerializer.tryGet().ObjectJsonSerializer— GsonJsonSerializer/JsonDeserializerfor the protocol-messagestatefield; delegates to the loadedObjectSerializer, and no-ops gracefully (logs +JsonNull) when the plugin is unavailable.Plugin (
liveobjects)DefaultObjectsSerializer— implementsObjectSerializer, (de)serializing arrays of object messages for JSON and MessagePack.JsonSerialization— Gson setup: enum-by-code adapters andWireObjectDataJsonSerializer(handles thejson-as-string encoding per OD4c5 and the "at least one value field" validation).MsgpackSerialization— hand-rolled MessagePack pack/unpack for the full object model (operations, state, map/counter payloads, map entries, object data).Wire model decoupling
The serializers operate on the
WireObjectMessagemodel inio.ably.lib.object.message, so the newobjectpackage carries no dependency on the legacyio.ably.lib.objectspackage.WireObjectMessagecarries the Gson annotations needed for wire-format fidelity —@SerializedName("object")onobjectState(OM2g) and@JsonAdapter(WireObjectDataJsonSerializer)onWireObjectData.Notes
objectpackage'sobjectStateError(ErrorInfo 500 / 92000).Wire*model are tracked as a follow-up.Spec: OM*, OOP*, OD*, OMP*, OCN*, OST*, MCR*, MST*, MRM*, CCR*, CIN*, ODE*, MCL*
🤖 Generated with Claude Code