pygar-client


Namepygar-client JSON
Version 1.7.8 PyPI version JSON
download
home_pagehttps://www.trinityriversystems.com/docs/gar_protocol/
SummaryA Python client for the GAR protocol
upload_time2025-07-09 13:56:45
maintainerNone
docs_urlNone
authorJon Hill
requires_pythonNone
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # GAR Protocol

Messages are serialized using an underlying transport — currently ZeroMQ.

Binary or JSON message format is supported by the server.

## Format Detection

- JSON is inferred if the first character of the introduction message is `{`.
- Otherwise, binary is assumed.

## Binary Messages

Start with a `message_type` enum, followed by the appropriate C struct. These are aligned C structures generated by `trscc`. See `gar_proto.h`.

## JSON Messages

JSON messages use the format:
```json
{
  "message_type": "<message_type enum name>",
  "value": { ... }
}
```

Example:
```json
{
  "message_type": "Subscribe",
  "value": {
    "subscription_mode": "Snapshot",
    "nagle_interval": 0,
    "name": "S1",
    "key_id": 0,
    "topic_id": 0,
    "_class": "Underlier",
    "key_filter": null,
    "topic_filter": null
  }
}
```

## Session Structure

- The first message must be an Introduction.
- Heartbeats must be sent regularly within `heartbeat_timeout_interval`.
- First heartbeat gets a 10x grace interval.

## Enumeration

- Topics and Keys must be introduced before publishing records.
- Clients and servers may use different enumerations.
- `0` is an invalid ID.
- Clients must map IDs between client and server contexts.

Example:  
Client assigns key "AAPL" → ID 2  
Server assigns same → ID 3  
Client sends `DeleteKey` with ID 2  
Receives `DeleteKey` from server with ID 3

## Records

- `NewRecord` must precede updates.
- Records may exist without values.
- Use `DeleteRecord` to remove empty ones.

## Record Updates

### Binary:

- Use `FixedLengthRecordUpdate` or `VariableLengthRecordUpdate`
- Fixed: starts with `record_id` followed by data
- Variable: serializes `binary_record_update`, includes size in first member

### JSON:

```json
{
  "message_type": "JSONRecordUpdate",
  "value": {
    "record_id": { "key_id": 1, "topic_id": 22 },
    "value": 0.3
  }
}
```

## Example Session

```json
Sent: {"message_type": "Introduction", "value": { "version": 650269, "heartbeat_timeout_interval": 3000, "user": "jonh" }}
Received: {"message_type": "Introduction", "value": { "version": 650269, "heartbeat_timeout_interval": 3000, "user": "jserver" }}
Sent: {"message_type": "Subscribe", "value": { "subscription_mode": "Streaming", "nagle_interval": 0, "name": "S1", "key_id": 0, "topic_id": 0, "_class": "Underlier", "key_filter": null, "topic_filter": null }}
Received: Topic and Key Introductions
Received: NewRecord, JSONRecordUpdate
Received: SnapshotComplete
Sent/Received: Heartbeats
Received: DeleteRecord, DeleteKey
Sent: Logoff
```

## Publication Rules

- Server publishes only subscribed messages.
- Clients may publish any messages but must introduce topics/keys first.

---

## Protocol Schema

```cpp
enum message_type : int64_t {
    Introduction = 'A',
    Heartbeat = 'B',
    Logoff = 'C',
    TopicIntroduction = 'D',
    KeyIntroduction = 'E',
    DeleteKey = 'F',
    Subscribe = 'G',
    SnapshotComplete = 'H',
    Unsubscribe = 'I',
    NewRecord = 'J',
    DeleteRecord = 'K',
    FixedLengthRecordUpdate = 'L',
    VariableLengthRecordUpdate = 'M',
    JSONRecordUpdate = 'N',
    Shutdown = 'O'
};

type u_milliseconds = uint64_t;

struct introduction {
    version : int;
    heartbeat_timeout_interval : u_milliseconds;
    user : string;
    schema : optional string;
};

type topic_id = unsigned;

struct topic_introduction {
    topic_id;
    name : string;
};

type key_id = unsigned;

struct key_introduction {
    key_id;
    name : string;
    _class : optional string;
};

struct delete_key {
    key_id;
};

enum subscription_mode { *None, Snapshot, Streaming, Throttled };

type regex text;

struct subscribe {
    subscription_mode;
    nagle_interval : u_milliseconds;
    name : string;
    key_id;
    topic_id;
    _class : optional string;
    key_filter : optional regex;
    topic_filter : optional regex;
};

struct snapshot_complete {
    name : string;
};

struct record_id {
    key_id;
    topic_id;
};

type byte = unsigned char;

struct json_record_update {
    record_id;
    value : json;
};

struct binary_record_update {
    record_id;
    data : byte[];
};

struct unsubscribe {
    name : string;
};
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://www.trinityriversystems.com/docs/gar_protocol/",
    "name": "pygar-client",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": null,
    "author": "Jon Hill",
    "author_email": null,
    "download_url": null,
    "platform": null,
    "description": "# GAR Protocol\n\nMessages are serialized using an underlying transport \u2014 currently ZeroMQ.\n\nBinary or JSON message format is supported by the server.\n\n## Format Detection\n\n- JSON is inferred if the first character of the introduction message is `{`.\n- Otherwise, binary is assumed.\n\n## Binary Messages\n\nStart with a `message_type` enum, followed by the appropriate C struct. These are aligned C structures generated by `trscc`. See `gar_proto.h`.\n\n## JSON Messages\n\nJSON messages use the format:\n```json\n{\n  \"message_type\": \"<message_type enum name>\",\n  \"value\": { ... }\n}\n```\n\nExample:\n```json\n{\n  \"message_type\": \"Subscribe\",\n  \"value\": {\n    \"subscription_mode\": \"Snapshot\",\n    \"nagle_interval\": 0,\n    \"name\": \"S1\",\n    \"key_id\": 0,\n    \"topic_id\": 0,\n    \"_class\": \"Underlier\",\n    \"key_filter\": null,\n    \"topic_filter\": null\n  }\n}\n```\n\n## Session Structure\n\n- The first message must be an Introduction.\n- Heartbeats must be sent regularly within `heartbeat_timeout_interval`.\n- First heartbeat gets a 10x grace interval.\n\n## Enumeration\n\n- Topics and Keys must be introduced before publishing records.\n- Clients and servers may use different enumerations.\n- `0` is an invalid ID.\n- Clients must map IDs between client and server contexts.\n\nExample:  \nClient assigns key \"AAPL\" \u2192 ID 2  \nServer assigns same \u2192 ID 3  \nClient sends `DeleteKey` with ID 2  \nReceives `DeleteKey` from server with ID 3\n\n## Records\n\n- `NewRecord` must precede updates.\n- Records may exist without values.\n- Use `DeleteRecord` to remove empty ones.\n\n## Record Updates\n\n### Binary:\n\n- Use `FixedLengthRecordUpdate` or `VariableLengthRecordUpdate`\n- Fixed: starts with `record_id` followed by data\n- Variable: serializes `binary_record_update`, includes size in first member\n\n### JSON:\n\n```json\n{\n  \"message_type\": \"JSONRecordUpdate\",\n  \"value\": {\n    \"record_id\": { \"key_id\": 1, \"topic_id\": 22 },\n    \"value\": 0.3\n  }\n}\n```\n\n## Example Session\n\n```json\nSent: {\"message_type\": \"Introduction\", \"value\": { \"version\": 650269, \"heartbeat_timeout_interval\": 3000, \"user\": \"jonh\" }}\nReceived: {\"message_type\": \"Introduction\", \"value\": { \"version\": 650269, \"heartbeat_timeout_interval\": 3000, \"user\": \"jserver\" }}\nSent: {\"message_type\": \"Subscribe\", \"value\": { \"subscription_mode\": \"Streaming\", \"nagle_interval\": 0, \"name\": \"S1\", \"key_id\": 0, \"topic_id\": 0, \"_class\": \"Underlier\", \"key_filter\": null, \"topic_filter\": null }}\nReceived: Topic and Key Introductions\nReceived: NewRecord, JSONRecordUpdate\nReceived: SnapshotComplete\nSent/Received: Heartbeats\nReceived: DeleteRecord, DeleteKey\nSent: Logoff\n```\n\n## Publication Rules\n\n- Server publishes only subscribed messages.\n- Clients may publish any messages but must introduce topics/keys first.\n\n---\n\n## Protocol Schema\n\n```cpp\nenum message_type : int64_t {\n    Introduction = 'A',\n    Heartbeat = 'B',\n    Logoff = 'C',\n    TopicIntroduction = 'D',\n    KeyIntroduction = 'E',\n    DeleteKey = 'F',\n    Subscribe = 'G',\n    SnapshotComplete = 'H',\n    Unsubscribe = 'I',\n    NewRecord = 'J',\n    DeleteRecord = 'K',\n    FixedLengthRecordUpdate = 'L',\n    VariableLengthRecordUpdate = 'M',\n    JSONRecordUpdate = 'N',\n    Shutdown = 'O'\n};\n\ntype u_milliseconds = uint64_t;\n\nstruct introduction {\n    version : int;\n    heartbeat_timeout_interval : u_milliseconds;\n    user : string;\n    schema : optional string;\n};\n\ntype topic_id = unsigned;\n\nstruct topic_introduction {\n    topic_id;\n    name : string;\n};\n\ntype key_id = unsigned;\n\nstruct key_introduction {\n    key_id;\n    name : string;\n    _class : optional string;\n};\n\nstruct delete_key {\n    key_id;\n};\n\nenum subscription_mode { *None, Snapshot, Streaming, Throttled };\n\ntype regex text;\n\nstruct subscribe {\n    subscription_mode;\n    nagle_interval : u_milliseconds;\n    name : string;\n    key_id;\n    topic_id;\n    _class : optional string;\n    key_filter : optional regex;\n    topic_filter : optional regex;\n};\n\nstruct snapshot_complete {\n    name : string;\n};\n\nstruct record_id {\n    key_id;\n    topic_id;\n};\n\ntype byte = unsigned char;\n\nstruct json_record_update {\n    record_id;\n    value : json;\n};\n\nstruct binary_record_update {\n    record_id;\n    data : byte[];\n};\n\nstruct unsubscribe {\n    name : string;\n};\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A Python client for the GAR protocol",
    "version": "1.7.8",
    "project_urls": {
        "Homepage": "https://www.trinityriversystems.com/docs/gar_protocol/"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "892beb8ed7810f1e5c1bf09ca3485a17e9aaae3f655f3383118037c41cb81630",
                "md5": "4062cb2fe2365d7374c14fd2617f5fd9",
                "sha256": "011a0f6b92f6cea8cad5c7cc6fe1e1fa5edbe5b037b13e2f9c2db85a96c7fc94"
            },
            "downloads": -1,
            "filename": "pygar_client-1.7.8-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4062cb2fe2365d7374c14fd2617f5fd9",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 12355,
            "upload_time": "2025-07-09T13:56:45",
            "upload_time_iso_8601": "2025-07-09T13:56:45.308627Z",
            "url": "https://files.pythonhosted.org/packages/89/2b/eb8ed7810f1e5c1bf09ca3485a17e9aaae3f655f3383118037c41cb81630/pygar_client-1.7.8-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-09 13:56:45",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "pygar-client"
}
        
Elapsed time: 1.88738s