Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ECO-5139] feat: add action and serial fields #1048

Merged
merged 1 commit into from
Nov 28, 2024

Conversation

ttypic
Copy link
Contributor

@ttypic ttypic commented Nov 27, 2024

Add action and serial fields to the message object for the Chat SDK

Summary by CodeRabbit

  • New Features

    • Introduced a method for reading optional integer values from JSON.
    • Added new fields (serial, version, action, createdAt) to the Message class for enhanced message details.
    • Created a new enum (MessageAction) to represent various message actions.
    • Enhanced message handling logic to improve tracking of message versions during transmission.
    • Added a new capability in the JSON configuration to allow all actions.
  • Bug Fixes

    • Improved serialization and deserialization processes to handle new fields effectively.
    • Refined error handling and state management during message processing and recovery.
  • Tests

    • Expanded test coverage for the Message class, including new tests for serialization and deserialization with the new fields.
    • Added tests to validate message properties in the RealtimeMessageTest class.

Copy link

coderabbitai bot commented Nov 27, 2024

Walkthrough

The changes in this pull request introduce new functionality to the BaseMessage and Message classes, as well as a new MessageAction enum. A method for reading optional integers from JSON is added to BaseMessage, while Message gains additional fields for serial, version, action, and createdAt, along with updated serialization and deserialization logic. The MessageAction enum provides constants for various message actions and a method to retrieve them by ordinal. Corresponding tests have been added to ensure the correct functionality of these new features.

Changes

File Path Change Summary
lib/src/main/java/io/ably/lib/types/BaseMessage.java Added method: protected Integer readInt(final JsonObject map, final String key)
lib/src/main/java/io/ably/lib/types/Message.java Added fields: public String serial, public String version, public MessageAction action, public Long createdAt; Updated methods for serialization and deserialization to include new fields.
lib/src/main/java/io/ably/lib/types/MessageAction.java Added enum: public enum MessageAction; Added method: static MessageAction tryFindByOrdinal(int ordinal)
lib/src/test/java/io/ably/lib/types/MessageTest.java Added test methods for serialization and deserialization of Message with new fields.
lib/src/main/java/io/ably/lib/realtime/ChannelBase.java Updated onMessage method logic; modified publish method signatures to include CompletionListener.
lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java Added test method: public void should_have_serial_action_createdAt() throws AblyException to validate message properties.
lib/src/test/resources/local/testAppSpec.json Added new capability entry: {"capability": "{ \"[*]*\":[\"*\"] }"} in the "keys" array.

Poem

In the code where messages flow,
New fields and actions start to grow.
With integers read from JSON bright,
Our messages now take flight!
So hop along, let’s celebrate,
For changes here are truly great! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ttypic ttypic requested review from AndyTWF and sacOO7 November 27, 2024 10:21
@github-actions github-actions bot temporarily deployed to staging/pull/1048/features November 27, 2024 10:22 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1048/javadoc November 27, 2024 10:23 Inactive
@ttypic ttypic force-pushed the ECO-5139/parse-action-and-serial branch from d536b10 to 91e85ca Compare November 27, 2024 10:23
@github-actions github-actions bot temporarily deployed to staging/pull/1048/features November 27, 2024 10:24 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1048/javadoc November 27, 2024 10:25 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (5)
lib/src/test/java/io/ably/lib/types/MessageTest.java (3)

50-70: Consider adding edge cases for action field

While the test covers the basic case, consider adding tests for:

  • null action
  • boundary values of action enum

72-91: Consider using parameterized tests for MessageAction values

To ensure comprehensive coverage of the MessageAction enum, consider using JUnit's Parameterized tests to verify serialization/deserialization of all possible action values.

Example structure:

@ParameterizedTest
@EnumSource(MessageAction.class)
void deserialize_message_with_different_actions(MessageAction action) {
    // Test implementation
}

49-113: Consider additional test coverage

While the current tests provide good coverage of the happy path and some edge cases, consider adding tests for:

  1. Null values for action and serial fields
  2. Empty or malformed serial strings
  3. Boundary conditions for both fields
lib/src/main/java/io/ably/lib/types/BaseMessage.java (1)

Line range hint 1-1: Consider adding integer field support in serialization methods.

Since this PR adds a new integer field (serial), the BaseMessage class should be updated to properly handle integer fields in its serialization methods:

  1. toJsonObject: Add support for integer field serialization
  2. writeFields: Add support for integer field serialization in MessagePack format

Here's a suggested implementation:

public static JsonObject toJsonObject(final BaseMessage message) {
    JsonObject json = new JsonObject();
+   // Add support for integer fields
+   if (message instanceof Message) {
+       Message msg = (Message) message;
+       if (msg.serial != null) {
+           json.addProperty("serial", msg.serial);
+       }
+   }
    // ... existing code ...
}

void writeFields(MessagePacker packer) throws IOException {
+   // Add support for integer fields
+   if (this instanceof Message) {
+       Message msg = (Message) this;
+       if (msg.serial != null) {
+           packer.packString("serial");
+           packer.packInt(msg.serial);
+       }
+   }
    // ... existing code ...
}
lib/src/main/java/io/ably/lib/types/Message.java (1)

66-68: Enhance the Javadoc comment for the action field

The Javadoc comment for the action field is minimal. Consider providing a more detailed description to clarify its purpose and usage.

🛑 Comments failed to post (4)
lib/src/main/java/io/ably/lib/types/MessageAction.java (1)

12-14: 🛠️ Refactor suggestion

Consider enhancing the utility method.

The method has a few areas for improvement:

  1. The method should be public since it needs to be accessed by the Message class for serialization/deserialization
  2. Missing Javadoc documentation
  3. No validation for negative ordinals

Consider applying these improvements:

-    static MessageAction tryFindByOrdinal(int ordinal) {
-        return values().length <= ordinal ? null: values()[ordinal];
+    /**
+     * Attempts to find a MessageAction by its ordinal value.
+     * @param ordinal the ordinal value to look up
+     * @return the corresponding MessageAction or null if not found
+     */
+    public static MessageAction tryFindByOrdinal(int ordinal) {
+        if (ordinal < 0 || ordinal >= values().length) {
+            return null;
+        }
+        return values()[ordinal];
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    /**
     * Attempts to find a MessageAction by its ordinal value.
     * @param ordinal the ordinal value to look up
     * @return the corresponding MessageAction or null if not found
     */
    public static MessageAction tryFindByOrdinal(int ordinal) {
        if (ordinal < 0 || ordinal >= values().length) {
            return null;
        }
        return values()[ordinal];
    }
lib/src/test/java/io/ably/lib/types/MessageTest.java (2)

57-57: 💡 Codebase verification

Serial number format should be documented in the Message class

The serial number format (timestamp-sequence@node:version) is not documented in the codebase. While the format is being used in tests, there's no clear documentation explaining its structure and requirements. Please add JSDoc comments to the serial field in the Message class to document:

  • The format pattern: timestamp-sequence@node:version
  • The purpose of each component
  • Any validation requirements
🔗 Analysis chain

Verify the serial number format documentation

The serial number follows a specific format: timestamp-sequence@node:version. Please ensure this format is documented in the Message class or relevant documentation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for documentation of serial number format
rg -l "serial.*format|message.*serial" --type md

Length of output: 63


Script:

#!/bin/bash
# Check the content of CHANGELOG.md for serial format documentation
rg -A 5 -B 5 "serial.*format|message.*serial" CHANGELOG.md

# Also search for serial-related documentation in source files
ast-grep --pattern 'class Message {
  $$$
  serial
  $$$
}'

# Look for any comments or documentation about serial format
rg "serial.*format|message.*serial" --type java

Length of output: 4262


94-113: 💡 Codebase verification

Add test cases for boundary values of MessageAction

The current test verifies behavior for action=10, but should be expanded to cover:

  • Negative values (-1)
  • Values at the boundary (6, 7)
  • Integer.MAX_VALUE

The behavior is properly implemented in MessageAction.tryFindByOrdinal() which returns null for any ordinal >= values().length, but this isn't documented. Add javadoc to:

  • Message.action field explaining null handling for invalid values
  • MessageAction.tryFindByOrdinal() documenting the null return for out-of-range values

Locations needing documentation:

  • lib/src/main/java/io/ably/lib/types/Message.java: action field
  • lib/src/main/java/io/ably/lib/types/MessageAction.java: tryFindByOrdinal method
🔗 Analysis chain

Enhance invalid action value testing

The test handles unknown action values well, but consider:

  1. Adding test cases for other invalid values (negative numbers, Integer.MAX_VALUE)
  2. Documenting this behavior in the Message class

Let me search for more context about the action field and its documentation.


Let me check the MessageAction enum to understand the valid action values and their documentation.


Let me check the content of the MessageAction enum file to understand the implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for documentation of action field behavior
rg -A 5 "action.*field|invalid.*action" --type java lib/src/main/java/io/ably/lib/types/Message.java

Length of output: 321


Script:

#!/bin/bash
# Search for action field declaration and related code
ast-grep --pattern 'class Message {
  $$$
  action
  $$$
}'

# Search for any javadoc or comments related to action field
rg -B 5 "action" --type java lib/src/main/java/io/ably/lib/types/Message.java

Length of output: 2347


Script:

#!/bin/bash
# Search for MessageAction enum definition
rg -B 5 "enum MessageAction" --type java

# Search for tryFindByOrdinal implementation
ast-grep --pattern 'tryFindByOrdinal($$$)'

Length of output: 308


Script:

#!/bin/bash
# Get the content of MessageAction.java
cat lib/src/main/java/io/ably/lib/types/MessageAction.java

Length of output: 431

lib/src/main/java/io/ably/lib/types/Message.java (1)

155-156: ⚠️ Potential issue

Include version in fieldCount for serialization

In the writeMsgpack method, the version field is not included in the fieldCount calculation. This omission may prevent the version field from being serialized properly. Please include version in the field count to ensure it is serialized.

Apply the following diff to fix the issue:

 if(name != null) ++fieldCount;
 if(extras != null) ++fieldCount;
 if(serial != null) ++fieldCount;
+if(version != null) ++fieldCount;
 if(action != null) ++fieldCount;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        if(serial != null) ++fieldCount;
        if(version != null) ++fieldCount;
        if(action != null) ++fieldCount;

@github-actions github-actions bot temporarily deployed to staging/pull/1048/features November 27, 2024 10:27 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
lib/src/test/java/io/ably/lib/types/MessageTest.java (2)

50-70: Consider adding more test cases for serialization.

While the test covers the basic serialization case, consider adding the following test cases for better coverage:

  • Different MessageAction values
  • Null/empty serial numbers
  • Invalid serial number formats

Here's a suggested additional test:

@Test
public void serialize_message_with_null_fields() {
    Message message = new Message("test-name", "test-data");
    message.action = null;
    message.serial = null;

    JsonElement serializedElement = serializer.serialize(message, null, null);
    JsonObject serializedObject = serializedElement.getAsJsonObject();
    
    assertNull(serializedObject.get("action"));
    assertNull(serializedObject.get("serial"));
}

94-113: Enhance error handling test coverage.

While the test verifies handling of one unknown action value, consider adding tests for:

  • Negative action values
  • Action values at type boundaries (Integer.MAX_VALUE)
  • Invalid data types for action (string, boolean)

Here's a suggested additional test:

@Test
public void deserialize_message_with_invalid_action_type() throws Exception {
    JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("clientId", "test-client-id");
    jsonObject.addProperty("action", "invalid_string");  // Invalid type

    Message message = Message.fromEncoded(jsonObject, new ChannelOptions());
    assertNull(message.action);
}
lib/src/main/java/io/ably/lib/types/Message.java (1)

Line range hint 1-411: Consider versioning strategy for MessageAction

While the implementation is solid, consider these architectural points:

  1. Document the stability guarantee for MessageAction ordinals
  2. Consider adding a version field to the wire protocol to handle future enum extensions
  3. Consider using string representations instead of ordinals for better forward compatibility
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d536b10 and 91e85ca.

📒 Files selected for processing (4)
  • lib/src/main/java/io/ably/lib/types/BaseMessage.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (6 hunks)
  • lib/src/main/java/io/ably/lib/types/MessageAction.java (1 hunks)
  • lib/src/test/java/io/ably/lib/types/MessageTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/src/main/java/io/ably/lib/types/BaseMessage.java
  • lib/src/main/java/io/ably/lib/types/MessageAction.java
🔇 Additional comments (6)
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)

72-91: Document the serial number format requirements.

The test uses a specific format for the serial number (01826232498871-001@abcdefghij:001), which appears to contain timestamp and sequence information. This format should be documented and validated.

Let's check if there's any documentation about the serial number format:

Consider adding a comment explaining the serial number format and its components:

 @Test
 public void deserialize_message_with_serial() throws Exception {
+    // Serial number format: <timestamp>-<sequence>@<connection-id>:<message-sequence>
     // Given
     JsonObject jsonObject = new JsonObject();
lib/src/main/java/io/ably/lib/types/Message.java (5)

49-69: LGTM! Well-documented field additions

The new fields are thoroughly documented with clear specifications and initialization requirements. The documentation effectively explains the complex logic for version field initialization.


360-364: LGTM! Clean JSON deserialization implementation

The implementation properly handles null values and uses appropriate helper methods for type conversion.


198-203: Consider handling invalid action ordinals

The tryFindByOrdinal result should be validated as it might return null for invalid ordinals.

Let's check the implementation of tryFindByOrdinal:


380-388: Verify test coverage for serialization edge cases

The serialization logic looks correct, but we should ensure comprehensive test coverage for various combinations of null and non-null values.

Let's check for existing tests:

✅ Verification successful

Test coverage for serialization is adequate

The test coverage for the serialization of serial, version, and action fields is well implemented in MessageTest.java. Specifically:

  • Test case serialize_message_with_serial verifies serialization of serial and action fields
  • Both positive and negative test cases exist for action field (including unknown action values)
  • Null checks are implicitly tested through serialize_message_with_name_and_data which verifies optional fields are not included when null
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find test files covering Message serialization
fd -e java -e kt --exec rg -l "Message.*[Ss]eriali[sz]" {} \;

Length of output: 1383


Script:

#!/bin/bash
# Check MessageTest.java for specific test cases covering serial, version, and action serialization
rg -A 5 -B 5 "serial|version|action.*serializ" ./lib/src/test/java/io/ably/lib/types/MessageTest.java

# Also check MessageSerializer tests
rg -A 5 -B 5 "serial|version|action.*serializ" ./lib/src/test/java/io/ably/lib/types/MessageSerializer.java

Length of output: 4638


Line range hint 155-178: Verify MessageAction ordinal stability across versions

The code packs the action as an ordinal integer. This approach requires careful consideration of backward compatibility.

Let's verify the MessageAction enum's stability:

@github-actions github-actions bot temporarily deployed to staging/pull/1048/javadoc November 27, 2024 10:28 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (4)
lib/src/main/java/io/ably/lib/types/Message.java (4)

56-59: Enhance documentation for the action field

The documentation for the action field is minimal. Consider adding details about:

  • The purpose of this field
  • Possible values from MessageAction enum
  • When this field is expected to be set/used

162-164: Consider using a more stable enum serialization approach

Using ordinal() for enum serialization is risky as it depends on the enum declaration order. If the MessageAction enum is modified in the future (reordering, inserting new values), it could break message compatibility.

Consider using:

  1. A string representation of the enum value, or
  2. A dedicated numeric value that doesn't depend on declaration order

345-347: Consider validating the serial field format

The serial field is read without any validation. If there are expectations about its format (e.g., length, character set), consider adding validation to ensure data integrity.


49-60: Consider adding unit tests for new fields

The implementation of the new serial and action fields appears complete with proper serialization/deserialization support. To ensure robustness, consider adding unit tests for:

  1. Serialization/deserialization of both fields in various formats (Msgpack, JSON)
  2. Edge cases (null values, invalid action ordinals)
  3. Serial field format validation
  4. Backward compatibility with messages lacking these fields

Would you like me to help generate comprehensive unit tests for these scenarios?

Also applies to: 145-164, 184-187, 344-347, 363-368

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 91e85ca and addebf3.

📒 Files selected for processing (1)
  • lib/src/main/java/io/ably/lib/types/Message.java (6 hunks)
🔇 Additional comments (1)
lib/src/main/java/io/ably/lib/types/Message.java (1)

184-187: Verify error handling for invalid action values

Please ensure that MessageAction.tryFindByOrdinal() properly handles invalid ordinal values. Consider:

  1. What happens if the ordinal is out of range?
  2. Should we log a warning when an invalid action is encountered?
✅ Verification successful

Let me try a different approach to find the implementation of MessageAction.tryFindByOrdinal.


Error handling for invalid action values is properly implemented

The MessageAction.tryFindByOrdinal() implementation safely handles invalid ordinal values by:

  1. Returning null for out-of-range ordinals (when ordinal >= values length)
  2. Safely accessing valid ordinals through the enum's values() array

The calling code in Message.java also properly handles null actions, and there's already logging in place for unexpected fields. No additional error handling is needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for tryFindByOrdinal implementation and its error handling
ast-grep --pattern 'tryFindByOrdinal($_) {
  $$$
}'

Length of output: 53


Script:

#!/bin/bash
# First, let's find the MessageAction enum file
fd MessageAction.java

# Then let's look at its content to find tryFindByOrdinal implementation
rg -A 5 "tryFindByOrdinal" --type java

Length of output: 1614

Copy link
Collaborator

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to https://github.com/ably/specification/pull/210/files and https://github.com/ably/specification/pull/235/files.
I'm not sure why we didn't address other materialization fields as a part of this PR
e.g. as per TM2k

@(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 @TM2p@ @version@

Seems TM2p version field is missing

@ttypic
Copy link
Contributor Author

ttypic commented Nov 27, 2024

@sacOO7,

version is not important for now, originally I added version as well, but decided to rollback it, this PR focused on fields that's important for Chat Beta. For Chat Beta we don't need to implement all parts of the spec, we just should be able to filter non "message.create" actions and use serial field instead of timeserial from extras.

why we didn't address other materialization fields as a part of this PR

It requires some thinking, more tests and it will be better to implement as part of separate PR

@sacOO7
Copy link
Collaborator

sacOO7 commented Nov 27, 2024

Sure, but the spec says the SDK must set it equal to its @TM2p@ @version@ if @MESSAGE_CREATE@ does not contain a @serial@. Won't this cause issue while reading serial for MESSAGE_CREATE
Also, we should create issue to address other fields, same as Cocoa-Add new properties to ARTMessage if current implementation is sufficient

@ttypic ttypic force-pushed the ECO-5139/parse-action-and-serial branch from addebf3 to d730716 Compare November 27, 2024 14:30
@github-actions github-actions bot temporarily deployed to staging/pull/1048/features November 27, 2024 14:31 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1048/javadoc November 27, 2024 14:31 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (5)
lib/src/test/java/io/ably/lib/types/MessageTest.java (3)

50-70: Consider adding edge cases to the serialization test.

While the current test covers the happy path, consider adding test cases for:

  • Null action and serial fields
  • Empty serial string
  • Invalid serial format

Here's a suggested additional test:

@Test
public void serialize_message_with_null_fields() {
    // Given
    Message message = new Message("test-name", "test-data");
    message.action = null;
    message.serial = null;

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

    // Then
    JsonObject serializedObject = serializedElement.getAsJsonObject();
    assertNull(serializedObject.get("action"));
    assertNull(serializedObject.get("serial"));
}

72-91: Add tests for different JSON formats.

Consider adding test cases for:

  • JSON with missing optional fields
  • Different data types (e.g., numbers as strings)
  • Malformed JSON handling

Example test case:

@Test
public void deserialize_message_with_missing_optional_fields() throws Exception {
    // Given
    JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("name", "test-name");
    jsonObject.addProperty("data", "test-data");
    
    // When
    Message message = Message.fromEncoded(jsonObject, new ChannelOptions());
    
    // Then
    assertNull(message.action);
    assertNull(message.serial);
    assertEquals("test-name", message.name);
    assertEquals("test-data", message.data);
}

94-113: Add boundary tests for action values.

The current test only checks one unknown action value (10). Consider adding tests for:

  • Negative action values
  • Maximum integer value
  • Zero value

Example test:

@Test
public void deserialize_message_with_boundary_action_values() throws Exception {
    // Test cases: -1, 0, Integer.MAX_VALUE
    int[] testValues = {-1, 0, Integer.MAX_VALUE};
    
    for (int actionValue : testValues) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("name", "test-name");
        jsonObject.addProperty("action", actionValue);
        
        Message message = Message.fromEncoded(jsonObject, new ChannelOptions());
        assertNull("Action should be null for value: " + actionValue, message.action);
    }
}
lib/src/main/java/io/ably/lib/types/Message.java (1)

Line range hint 155-179: Remove version-related serialization logic

The serialization logic includes the version field which should be removed as per PR objectives. Otherwise, the implementation for serial and action fields is correct.

Apply this diff to remove version-related serialization:

        if(serial != null) ++fieldCount;
-       if(version != null) ++fieldCount;
        if(action != null) ++fieldCount;
        packer.packMapHeader(fieldCount);
        super.writeFields(packer);
        if(name != null) {
            packer.packString(NAME);
            packer.packString(name);
        }
        if(extras != null) {
            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());
        }
lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (1)

846-849: Consider adding detailed documentation for version and serial fields.

The integration of version and serial fields in the message processing flow is clean and well-placed. However, consider adding more detailed comments explaining:

  • The purpose and significance of these fields
  • The relationship between version and serial
  • Any assumptions or limitations of the format
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between addebf3 and d730716.

📒 Files selected for processing (5)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/BaseMessage.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (6 hunks)
  • lib/src/main/java/io/ably/lib/types/MessageAction.java (1 hunks)
  • lib/src/test/java/io/ably/lib/types/MessageTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/src/main/java/io/ably/lib/types/BaseMessage.java
  • lib/src/main/java/io/ably/lib/types/MessageAction.java
🔇 Additional comments (3)
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)

49-113: Addressing previous version field comment.

Based on the PR discussion, the version field was intentionally removed to focus on essential fields for Chat Beta. The current test implementation correctly reflects this decision by focusing on the action and serial fields.

lib/src/main/java/io/ably/lib/types/Message.java (1)

65-68: Verify MessageAction enum implementation and usage

The code references MessageAction enum but its implementation is not visible in the provided context. We should verify:

  1. The enum implementation includes all required action types
  2. The impact of these changes on message handling throughout the SDK

Let's verify the MessageAction enum implementation and its usage:

✅ Verification successful

Let's gather more information about the MessageAction enum definition since it wasn't found in the previous search:


MessageAction enum implementation is complete and properly used

The MessageAction enum is well-defined in lib/src/main/java/io/ably/lib/types/MessageAction.java with all required action types:

  • MESSAGE_UNSET (0)
  • MESSAGE_CREATE (1)
  • MESSAGE_UPDATE (2)
  • MESSAGE_DELETE (3)
  • ANNOTATION_CREATE (4)
  • ANNOTATION_DELETE (5)
  • META_OCCUPANCY (6)

The enum is properly used in Message class for:

  • Deserialization via tryFindByOrdinal
  • Message creation and validation in tests
  • Handling message serials with MESSAGE_CREATE action
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find MessageAction enum definition
echo "=== MessageAction enum definition ==="
ast-grep --pattern 'enum MessageAction {
  $$$
}'

# Find all usages of MessageAction
echo -e "\n=== MessageAction usages ==="
rg "MessageAction\." -A 2

Length of output: 1389


Script:

#!/bin/bash
# Search for MessageAction enum definition with a broader pattern
echo "=== MessageAction enum definition ==="
fd MessageAction --exec cat {}

# Search for any references to MESSAGE_CREATE to find potential enum values
echo -e "\n=== MESSAGE_CREATE references ==="
rg "MESSAGE_CREATE" -B 2 -A 2

Length of output: 2536

lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (1)

846-849: Consider adding format validation and overflow handling.

The implementation of version and serial fields looks good, but there are a few considerations:

  1. The version format using channelSerial:messageIndex with zero-padded index is clean.
  2. Setting serial equal to version aligns with the PR objectives.

However, consider:

  • Adding validation for channelSerial format
  • Handling cases where messageIndex exceeds 999 to prevent format issues

Let's verify the channelSerial format across the codebase:

@ttypic ttypic force-pushed the ECO-5139/parse-action-and-serial branch from d730716 to 5f0f7df Compare November 27, 2024 15:59
@github-actions github-actions bot temporarily deployed to staging/pull/1048/features November 27, 2024 16:00 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1048/javadoc November 27, 2024 16:01 Inactive
@ttypic ttypic requested a review from AndyTWF November 27, 2024 16:02
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (11)
lib/src/test/java/io/ably/lib/types/MessageTest.java (3)

50-70: Add test cases for edge cases and invalid inputs.

While the basic serialization test is good, consider adding test cases for:

  • Empty/null serial numbers
  • Invalid serial number formats
  • Different MessageAction values

Example test case:

@Test
public void serialize_message_with_null_serial() {
    Message message = new Message("test-name", "test-data");
    message.action = MessageAction.MESSAGE_CREATE;
    message.serial = null;

    JsonElement serialized = serializer.serialize(message, null, null);
    JsonObject serializedObject = serialized.getAsJsonObject();
    
    assertEquals(1, serializedObject.get("action").getAsInt());
    assertNull(serializedObject.get("serial"));
}

72-91: Add tests for JSON structure validation and optional fields.

The current test only covers the happy path. Consider adding tests for:

  • Missing optional fields in JSON
  • Malformed JSON input
  • Different data types for fields (e.g., numeric vs string serial)

Example test case:

@Test
public void deserialize_message_with_missing_optional_fields() throws Exception {
    JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("name", "test-name");
    jsonObject.addProperty("data", "test-data");
    
    Message message = Message.fromEncoded(jsonObject, new ChannelOptions());
    
    assertNull(message.action);
    assertNull(message.serial);
}

94-113: Add boundary tests and document action handling.

The test correctly verifies unknown action handling, but consider:

  • Testing boundary values (0, negative numbers)
  • Adding a comment explaining the null action behavior
  • Testing all valid MessageAction enum values

Example test case:

@Test
public void deserialize_message_with_boundary_action_values() throws Exception {
    JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("name", "test-name");
    // Test negative value
    jsonObject.addProperty("action", -1);
    
    Message message = Message.fromEncoded(jsonObject, new ChannelOptions());
    assertNull(message.action);
}
lib/src/main/java/io/ably/lib/types/Message.java (5)

80-83: Constants are well-defined but include unnecessary VERSION constant

The constants follow the existing naming pattern and are properly defined. However, the VERSION constant should be removed along with its corresponding field.

    private static final String SERIAL = "serial";
-   private static final String VERSION = "version";
    private static final String ACTION = "action";
    private static final String CREATED_AT = "createdAt";

Line range hint 163-192: Message packing implementation is correct but includes version field

The message packing implementation correctly handles the new fields with proper null checks and type conversions. However, version-related packing should be removed.

    int fieldCount = super.countFields();
    if(name != null) ++fieldCount;
    if(extras != null) ++fieldCount;
    if(serial != null) ++fieldCount;
-   if(version != null) ++fieldCount;
    if(action != null) ++fieldCount;
    if(createdAt != null) ++fieldCount;
    // ... other code ...
    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());
    }

212-219: Message unpacking implementation is correct but includes version field

The message unpacking implementation correctly handles the new fields with proper type conversions. However, version-related unpacking should be removed.

    } 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 if (fieldName.equals(CREATED_AT)) {
        createdAt = unpacker.unpackLong();

376-381: JSON reading implementation is correct but includes version field

The JSON reading implementation correctly handles the new fields with proper helper methods and null handling. However, version-related reading should be removed.

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

397-408: JSON serialization implementation is correct but includes version field

The JSON serialization implementation correctly handles the new fields with proper null checks and type conversions. However, version-related serialization should be removed.

    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());
    }
    if (message.createdAt != null) {
        json.addProperty(CREATED_AT, message.createdAt);
    }
lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (3)

998-1007: Consider using a helper method for creating chat messages.

The REST API call could be encapsulated in a helper method to improve reusability and readability, especially if more chat-related tests will be added in the future.

+ private void publishChatMessage(AblyRealtime realtime, String roomId, String text) throws AblyException {
+     JsonObject chatMessage = new JsonObject();
+     chatMessage.addProperty("text", text);
+     realtime.request(
+         "POST",
+         "/chat/v2/rooms/" + roomId + "/messages",
+         new Param[] { new Param("v", 3) },
+         HttpUtils.requestBodyFromGson(chatMessage, realtime.options.useBinaryProtocol),
+         null
+     );
+ }

1009-1011: Consider adding more specific error messages.

The assertion message could be more descriptive to help identify failures more easily.

- assertNull(msgComplete.waitFor(1, 3_000));
+ assertNull("Message should be received within 3 seconds", msgComplete.waitFor(1, 3_000));

983-984: Consider documenting the key permissions.

It would be helpful to add a comment explaining what permissions key[5] has, as it's specifically chosen for this test.

+ // Using key[5] which has permissions for chat operations
ClientOptions opts = createOptions(testVars.keys[5].keyStr);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d730716 and 5f0f7df.

📒 Files selected for processing (6)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/BaseMessage.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (6 hunks)
  • lib/src/main/java/io/ably/lib/types/MessageAction.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (3 hunks)
  • lib/src/test/java/io/ably/lib/types/MessageTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/src/main/java/io/ably/lib/types/BaseMessage.java
  • lib/src/main/java/io/ably/lib/types/MessageAction.java
🔇 Additional comments (4)
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)

49-113: Past comment about version field tests is no longer applicable.

According to the PR objectives, the version field was intentionally removed to focus on essential fields for Chat Beta. The existing test coverage for action and serial fields aligns with the current implementation scope.

lib/src/main/java/io/ably/lib/types/Message.java (1)

49-76: Field declarations look good, except for the version field

The field declarations and documentation for serial, action, and createdAt are well-implemented and properly documented with their respective spec references (TM2k, TM2j, TM2o).

The version field and its documentation should be removed as discussed in the PR objectives.

lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (1)

982-996: LGTM! Well-structured test setup and assertions.

The test method effectively validates the new message fields and their expected values. The assertions are comprehensive and cover all the required fields: serial, version, createdAt, action, and message format.

lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (1)

851-851: ⚠️ Potential issue

Ensure createdAt is only set if not provided by server

The current implementation always overwrites createdAt with timestamp. According to TM2o spec and the previous review comment, we should only set it if not provided by the server.

Apply this diff to fix the issue:

-if(msg.createdAt == null) msg.createdAt = msg.timestamp;
+if(msg.createdAt == null) msg.createdAt = msg.timestamp;

Likely invalid or redundant comment.

Add 256 bit AES CBC encrypted variable length data generated by Java client library SDK (#49)
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (6)
lib/src/test/resources/local/testAppSpec.json (1)

23-25: Document the purpose of the wildcard capability

Consider adding a comment in the JSON to explain why this broad capability is needed, particularly in relation to testing the new message actions and serial fields being added in this PR.

   {
+    "description": "Capability for testing message actions across all channels",
     "capability": "{ \"[*]*\":[\"*\"] }"
   }
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)

50-70: Consider adding edge cases to the serialization test.

While the test covers the basic serialization scenario, consider adding test cases for:

  • Null values for action and serial fields
  • Different MessageAction values besides MESSAGE_CREATE
  • Maximum length/special characters in serial field

Example test case:

@Test
public void serialize_message_with_null_fields() {
    Message message = new Message("test-name", "test-data");
    message.action = null;
    message.serial = null;

    JsonElement serialized = serializer.serialize(message, null, null);
    JsonObject serializedObject = serialized.getAsJsonObject();
    
    assertNull(serializedObject.get("action"));
    assertNull(serializedObject.get("serial"));
}
lib/src/main/java/io/ably/lib/types/Message.java (1)

Line range hint 163-192: Remove version field from MessagePack serialization

Remove version-related serialization logic as the field is being removed.

    int fieldCount = super.countFields();
    if(name != null) ++fieldCount;
    if(extras != null) ++fieldCount;
    if(serial != null) ++fieldCount;
-   if(version != null) ++fieldCount;
    if(action != null) ++fieldCount;
    if(createdAt != null) ++fieldCount;
    // ... later in the code ...
    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());
    }
lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (3)

978-982: Add test documentation

Consider adding Javadoc to explain the test's purpose, expected behavior, and its relationship to the Chat SDK.

+/**
+ * Verifies that Chat SDK message fields (serial, action, createdAt) are properly populated
+ * when receiving messages through the chat API endpoint.
+ * 
+ * @throws AblyException if test setup or execution fails
+ */
 @Test
 public void should_have_serial_action_createdAt() throws AblyException {

986-986: Extract magic strings into constants

Consider extracting the channel name pattern and API endpoint into constants for better maintainability.

+private static final String CHAT_MESSAGES_CHANNEL_PATTERN = "%s::$chat::$chatMessages";
+private static final String CHAT_MESSAGES_ENDPOINT = "/chat/v2/rooms/%s/messages";

-final Channel channel = realtime.channels.get("foo::$chat::$chatMessages");
+final Channel channel = realtime.channels.get(String.format(CHAT_MESSAGES_CHANNEL_PATTERN, "foo"));

-"/chat/v2/rooms/foo/messages",
+String.format(CHAT_MESSAGES_ENDPOINT, "foo"),

Also applies to: 1003-1003


1010-1010: Extract timeout value into a constant

The 10-second timeout value should be extracted into a named constant for better maintainability.

+private static final long CHAT_MESSAGE_TIMEOUT_MS = 10_000;

-assertNull(msgComplete.waitFor(1, 10_000));
+assertNull(msgComplete.waitFor(1, CHAT_MESSAGE_TIMEOUT_MS));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5f0f7df and 0c65aff.

📒 Files selected for processing (7)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (2 hunks)
  • lib/src/main/java/io/ably/lib/types/BaseMessage.java (1 hunks)
  • lib/src/main/java/io/ably/lib/types/Message.java (6 hunks)
  • lib/src/main/java/io/ably/lib/types/MessageAction.java (1 hunks)
  • lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (3 hunks)
  • lib/src/test/java/io/ably/lib/types/MessageTest.java (1 hunks)
  • lib/src/test/resources/local/testAppSpec.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
  • lib/src/main/java/io/ably/lib/types/BaseMessage.java
  • lib/src/main/java/io/ably/lib/types/MessageAction.java
🔇 Additional comments (8)
lib/src/test/resources/local/testAppSpec.json (1)

23-25: Verify the security implications of wildcard permissions

The new capability grants unrestricted access (*) to all channels in all namespaces ([*]*). While this is acceptable for testing purposes, we should ensure this configuration is only used in test environments.

✅ Verification successful

Wildcard permissions are safely confined to test environment

The verification confirms that:

  • The wildcard capability pattern [*]* with * permissions only exists in testAppSpec.json
  • This file is exclusively used in test contexts:
    • Located in test/resources/local/ directory
    • Only referenced by test setup code (Setup.java) and test build script
    • No usage found in production or example code
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that this wildcard capability is only used in test configurations
# and not in production code or examples

# Check if similar wildcard patterns exist in non-test files
rg -g '!test*' -g '!*.test.*' -l '\[\*\]\*.*\*'

# Check if this file is referenced outside of test code
rg -g '!test*' -g '!*.test.*' 'testAppSpec.json'

Length of output: 98


Script:

#!/bin/bash
# Let's try a different approach to verify the security implications:

# 1. Find all JSON files that might contain capability configurations
fd -e json

# 2. Search for wildcard patterns in all JSON files
rg -t json '\[\*\]\*.*\*' -C 2

# 3. Check if testAppSpec.json is referenced anywhere in the codebase
rg "testAppSpec\.json"

Length of output: 747

lib/src/test/java/io/ably/lib/types/MessageTest.java (1)

94-113: Address integration testing requirements.

While this unit test properly handles unknown actions, there are two pending items from the PR discussion:

  1. Integration tests for inbound message handling were requested
  2. If version field is planned for future implementation, we should document this requirement

Let's check if there are any existing integration tests:

Consider creating a separate integration test class (e.g., MessageIntegrationTest) to verify the end-to-end behavior of these fields in a real connection scenario.

lib/src/main/java/io/ably/lib/types/Message.java (4)

56-64: Remove version field and documentation

The version field should be removed as per PR objectives to focus on essential fields for Chat Beta.


376-381: ⚠️ Potential issue

Implement missing serial field requirement and remove version

  1. Remove version-related deserialization
  2. Implement the spec requirement: "if MESSAGE_CREATE does not contain a serial, set it equal to its version"
    serial = readString(map, SERIAL);
-   version = readString(map, VERSION);
    Integer actionOrdinal = readInt(map, ACTION);
    action = actionOrdinal == null ? null : MessageAction.tryFindByOrdinal(actionOrdinal);
+   // Set serial equal to version for MESSAGE_CREATE action when serial is missing
+   if (serial == null && action == MessageAction.MESSAGE_CREATE) {
+       serial = version;
+   }
    createdAt = readLong(map, CREATED_AT);

Likely invalid or redundant comment.


397-408: 🛠️ Refactor suggestion

Remove version field from JSON serialization

Remove version-related serialization logic as the field is being removed.

    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());
    }

Likely invalid or redundant comment.


212-219: 🛠️ Refactor suggestion

Remove version field from MessagePack deserialization

Remove version-related deserialization logic as the field is being removed.

    } 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 if (fieldName.equals(CREATED_AT)) {
        createdAt = unpacker.unpackLong();

Likely invalid or redundant comment.

lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (2)

6-7: LGTM: Required imports added for new test

The new imports are necessary and properly used in the new test method.

Also applies to: 22-22


988-996: Consider adding error case verification

The test only verifies the success path. Consider adding assertions for error cases such as:

  • Invalid message format
  • Missing required fields
  • Invalid action types

Copy link
Collaborator

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

@ttypic ttypic merged commit 6c0ffcf into main Nov 28, 2024
12 checks passed
@ttypic ttypic deleted the ECO-5139/parse-action-and-serial branch November 28, 2024 10:33
@coderabbitai coderabbitai bot mentioned this pull request Nov 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants