Skip to content

Protocol logic

Bohdan Karpenko edited this page Apr 1, 2026 · 1 revision

Protocol Overview

Communication between client and server uses a bidirectional request-response protocol. Both sides can initiate requests, and each request is paired with a corresponding response. Messages are structured in JSON and include unique IDs for tracking.


Message Structure

All messages conform to the Message enum:

{
  "type": "request" | "response",
  "id": 1,
  "action": "string (requests only)",
  "status": "ok" | "error (responses only)",
  "code": 200 | 400 | ...,
  "message": "string",
  "data": { ... } | null
}

Fields

  • type — "request" or "response".
  • id — numeric identifier for pairing requests and responses.
  • action — request action name (present only in requests).
  • status — "ok" or "error" (present only in responses).
  • code — numeric status code.
  • message — human-readable result.
  • data — optional payload.

Request-Response IDs

  • Each request includes an ID chosen by the sender.

  • The corresponding response must use the same ID.

  • Both server and client can independently initiate requests.

  • Multiple in-flight requests are supported simultaneously.

  • IDs are only unique per active request:

    • Once a response is received, the ID can be reused for future requests.
    • This prevents unbounded growth of ID numbers.

ID Rules and Duplication

  1. Matching IDs:

    • Response id always matches the originating request id.
  2. Independent ID sequences:

    • Client and server maintain separate ID sequences.
    • The client can send id = 1 while the server sends id = 17 for its own request.
  3. ID reuse:

    • After a request has been responded to, its ID can be reused for a new request.
    • This ensures IDs remain within reasonable numeric ranges.
  4. Concurrent requests:

    • Multiple requests can be active simultaneously on either side.
    • Each side tracks its own IDs independently, without conflicting with the other side’s IDs.

Example Scenario

  1. Client sends a request:
{ "type": "request", "action": "get-all-tasks", "id": 1, "data": null }
  1. Server sends a request simultaneously:
{ "type": "request", "action": "update-core", "id": 5, "data": { ... } }
  1. Client responds to server request:
{ "type": "response", "id": 5, "status": "ok", "code": 200, "message": "Core updated", "data": null }
  1. Server responds to client request:
{ "type": "response", "id": 1, "status": "ok", "code": 200, "message": "Tasks retrieved", "data": [ ... ] }

Key points:

  • IDs 1 and 5 are independent for each side.
  • The same ID can be reused once the original request has been answered.
  • Requests and responses remain correctly paired, even with simultaneous activity.

Notes

  • The protocol supports fully bidirectional, asynchronous communication.
  • IDs must always be mirrored in responses to match requests.
  • Reusing IDs after a request has been completed prevents unbounded growth.
  • Messages without payload should either set "data": null or omit the field.

Clone this wiki locally