Class Message

java.lang.Object
com.loomcache.common.protocol.Message

public final class Message extends Object
The core message object for all LoomCache communication.

Every message (request or response) flowing between nodes or between client and server uses this format. The fixed 16-byte header is parsed first, then the variable-length body is read based on bodyLength.

Wire format (16-byte header): [magic 1B][opcode 1B][corrId 4B][bodyLen 4B][flags 1B][keyLen 2B][status 1B][mapNameLen 1B][reserved 1B]

Body layout: [mapName bytes][key bytes][value bytes] - mapNameLen in header tells how many bytes of mapName prefix the body - keyLen in header tells how many bytes of key follow the mapName - remaining bytes are the value

Backward compatible: old messages have mapNameLen=0 (was reserved/zero).

Thread-safety warning: Message instances are mutable. The withXxx() builder methods mutate and return this for chaining during construction. Once a Message has been sent or shared across threads, it must not be further mutated. Use copy() to create an independent copy if you need to modify a shared message.

Correlation ID enables request-response multiplexing on a single TCP connection — the client sends requests with incrementing IDs and matches responses by ID, allowing pipelining (send multiple requests before waiting for responses).

  • Field Details

    • MAGIC

      public static final byte MAGIC
      See Also:
    • HEADER_SIZE

      public static final int HEADER_SIZE
      See Also:
    • FLAG_HAS_SENDER_ID

      public static final byte FLAG_HAS_SENDER_ID
      Flag bit indicating the message body carries a length-prefixed senderId between the mapName and key regions. Used for write-retry idempotency: the client stamps a stable dedup ID via withSenderId(String) and the server's IdempotencyManager uses it to deduplicate retried mutations.
      See Also:
    • FLAG_COMPRESSED_LZ4

      public static final byte FLAG_COMPRESSED_LZ4
      Transport-only flag: body bytes are LZ4-compressed after a successful PROTOCOL_HELLO negotiation. Cleared before a decoded Message is exposed.
      See Also:
    • FLAG_COMPRESSED_ZSTD

      public static final byte FLAG_COMPRESSED_ZSTD
      Transport-only flag: body bytes are zstd-compressed after a successful PROTOCOL_HELLO negotiation. Cleared before a decoded Message is exposed.
      See Also:
    • FLAG_COMPRESSION_INTEGRITY

      public static final byte FLAG_COMPRESSION_INTEGRITY
      Transport-only flag: compressed body bytes include the v2 integrity checksum envelope. Cleared before a decoded Message is exposed.
      See Also:
    • FLAG_COMPRESSED_MASK

      public static final byte FLAG_COMPRESSED_MASK
      See Also:
  • Method Details

    • request

      public static Message request(MessageType type)
      Create a request message.
      Parameters:
      type - the message type (must not be null)
      Returns:
      a new request message
    • response

      public static Message response(MessageType type, int correlationId)
      Create a response message.
      Parameters:
      type - the message type (must not be null)
      correlationId - the correlation ID from the request
      Returns:
      a new response message
    • response

      public static Message response(MessageType type, int correlationId, byte status)
      Create a response message with status.
      Parameters:
      type - the message type (must not be null)
      correlationId - the correlation ID from the request
      status - the response status code
      Returns:
      a new response message
    • withFreshCorrelationId

      public Message withFreshCorrelationId()
      Create a copy of this message with a fresh correlation ID. Used for retries to prevent delayed responses from matching the wrong future.
      Returns:
      a new Message with the same type/key/value/mapName/flags but a new correlationId
    • withKey

      public Message withKey(byte @Nullable [] key)
    • withValue

      public Message withValue(byte @Nullable [] value)
      Set the message value.
      Parameters:
      value - the value bytes (may be null)
      Returns:
      this message for chaining
    • withMapName

      public Message withMapName(@Nullable String mapName)
      Set the target data structure name (map, queue, or topic). The name length is stored as an unsigned byte in the wire header, so the maximum encoded size is 255 bytes.
      Parameters:
      mapName - the structure name (may be null)
      Returns:
      this message for chaining
      Throws:
      IllegalArgumentException - if encoded name exceeds 255 bytes
    • withTtl

      public Message withTtl(long ttlMillis)
      Set the TTL for put operations.
      Parameters:
      ttlMillis - TTL in milliseconds
      Returns:
      this message for chaining
    • withSenderId

      public Message withSenderId(@Nullable String senderId)
      Set the sender node ID.
      Parameters:
      senderId - the originating node ID (may be null)
      Returns:
      this message for chaining
    • withFlags

      public Message withFlags(byte flags)
      Set message flags.
      Parameters:
      flags - the flag bits
      Returns:
      this message for chaining
    • withStatus

      public Message withStatus(byte status)
      Set the response status code.
      Parameters:
      status - the status code
      Returns:
      this message for chaining
    • type

      public @Nullable MessageType type()
      Get the message type.
      Returns:
      the message type, or null if not set
    • correlationId

      public int correlationId()
      Get the correlation ID.
      Returns:
      the correlation ID for request-response matching
    • bodyLength

      public int bodyLength()
      Get the body length.
      Returns:
      the length of the message body in bytes
    • flags

      public byte flags()
      Get the message flags.
      Returns:
      the flag bits
    • keyLength

      public short keyLength()
      Get the key length.
      Returns:
      the length of the key in bytes
    • status

      public byte status()
      Get the status code.
      Returns:
      the response status code
    • mapNameLength

      public byte mapNameLength()
      Get the map name length.
      Returns:
      the length of the map name in the body
    • key

      public byte[] key()
      Get the key bytes.
      Returns:
      the key data (never null; empty array if not set)
    • value

      public byte[] value()
      Get the value bytes.
      Returns:
      the value data (never null; empty array if not set)
    • mapName

      public @Nullable String mapName()
      Get the map/structure name.
      Returns:
      the structure name (map, queue, or topic), or null if not set
    • ttlMillis

      public long ttlMillis()
      Get the TTL in milliseconds.
      Returns:
      TTL in milliseconds for put operations
    • senderId

      public @Nullable String senderId()
      Get the sender node ID.
      Returns:
      the originating node ID, or null if not set
    • copy

      public Message copy()
      Create a deep copy of this message. Use this when you need to modify a message that may be shared across threads.
      Returns:
      a new Message with the same field values (byte arrays are cloned)
    • equals

      public boolean equals(Object o)
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object