From 7f68d08134d783f2b9fb2693f6703c1c2ecac383 Mon Sep 17 00:00:00 2001 From: narawat Date: Tue, 24 Feb 2026 21:40:33 +0700 Subject: [PATCH] update --- docs/implementation.md | 121 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 11 deletions(-) diff --git a/docs/implementation.md b/docs/implementation.md index 7b68f11..1f4b6e4 100644 --- a/docs/implementation.md +++ b/docs/implementation.md @@ -19,17 +19,39 @@ NATSBridge is implemented in three languages, each providing the same API: | **JavaScript** | [`src/NATSBridge.js`](../src/NATSBridge.js) | JavaScript implementation for Node.js and browsers | | **Python/Micropython** | [`src/nats_bridge.py`](../src/nats_bridge.py) | Python implementation for desktop and microcontrollers | -### Multi-Payload Support +### File Server Handler Architecture -The implementation uses a **standardized list-of-tuples format** for all payload operations. **Even when sending a single payload, the user must wrap it in a list.** +The system uses **handler functions** to abstract file server operations, allowing support for different file server implementations (e.g., Plik, AWS S3, custom HTTP server). + +**Handler Function Signatures:** + +```julia +# Upload handler - uploads data to file server and returns URL +# The handler is passed to smartsend as fileserver_upload_handler parameter +# It receives: (file_server_url::String, dataname::String, data::Vector{UInt8}) +# Returns: Dict{String, Any} with keys: "status", "uploadid", "fileid", "url" +fileserver_upload_handler(file_server_url::String, dataname::String, data::Vector{UInt8})::Dict{String, Any} + +# Download handler - fetches data from file server URL with exponential backoff +# The handler is passed to smartreceive as fileserver_download_handler parameter +# It receives: (url::String, max_retries::Int, base_delay::Int, max_delay::Int, correlation_id::String) +# Returns: Vector{UInt8} (the downloaded data) +fileserver_download_handler(url::String, max_retries::Int, base_delay::Int, max_delay::Int, correlation_id::String)::Vector{UInt8} +``` + +This design allows the system to support multiple file server backends without changing the core messaging logic. + +### Multi-Payload Support (Standard API) + +The system uses a **standardized list-of-tuples format** for all payload operations. **Even when sending a single payload, the user must wrap it in a list.** **API Standard:** ```julia # Input format for smartsend (always a list of tuples with type info) [(dataname1, data1, type1), (dataname2, data2, type2), ...] -# Output format for smartreceive (returns envelope dictionary with payloads field) -# Returns: Dict with envelope metadata and payloads field containing list of tuples +# Output format for smartreceive (returns a dictionary with payloads field containing list of tuples) +# Returns: Dict with envelope metadata and payloads field containing Vector{Tuple{String, Any, String}} # { # "correlation_id": "...", # "msg_id": "...", @@ -48,20 +70,51 @@ The implementation uses a **standardized list-of-tuples format** for all payload # } ``` -Where `type` can be: `"text"`, `"dictionary"`, `"table"`, `"image"`, `"audio"`, `"video"`, `"binary"` +**Supported Types:** +- `"text"` - Plain text +- `"dictionary"` - JSON-serializable dictionaries (Dict, NamedTuple) +- `"table"` - Tabular data (DataFrame, array of structs) +- `"image"` - Image data (Bitmap, PNG/JPG bytes) +- `"audio"` - Audio data (WAV, MP3 bytes) +- `"video"` - Video data (MP4, AVI bytes) +- `"binary"` - Generic binary data (Vector{UInt8}) + +This design allows per-payload type specification, enabling **mixed-content messages** where different payloads can use different serialization formats in a single message. **Examples:** ```julia -# Single payload - still wrapped in a list (type is required as third element) -smartsend("/test", [(dataname1, data1, "text")], broker_url="nats://localhost:4222") +# Single payload - still wrapped in a list +smartsend( + "/test", + [("dataname1", data1, "dictionary")], # List with one tuple (data, type) + broker_url="nats://localhost:4222", + fileserver_upload_handler=plik_oneshot_upload +) -# Multiple payloads in one message (each payload has its own type) -smartsend("/test", [(dataname1, data1, "dictionary"), (dataname2, data2, "table")], broker_url="nats://localhost:4222") +# Multiple payloads in one message with different types +smartsend( + "/test", + [("dataname1", data1, "dictionary"), ("dataname2", data2, "table")], + broker_url="nats://localhost:4222", + fileserver_upload_handler=plik_oneshot_upload +) + +# Mixed content (e.g., chat with text, image, audio) +smartsend( + "/chat", + [ + ("message_text", "Hello!", "text"), + ("user_image", image_data, "image"), + ("audio_clip", audio_data, "audio") + ], + broker_url="nats://localhost:4222" +) # Receive returns a dictionary envelope with all metadata and deserialized payloads env = smartreceive(msg; fileserver_download_handler=_fetch_with_backoff, max_retries=5, base_delay=100, max_delay=5000) -# env["payloads"] = [(dataname1, data1, "text"), (dataname2, data2, "table"), ...] +# env["payloads"] = [("dataname1", data1, type1), ("dataname2", data2, type2), ...] # env["correlation_id"], env["msg_id"], etc. +# env is a dictionary containing envelope metadata and payloads field ``` ## Cross-Platform Interoperability @@ -263,7 +316,53 @@ node test/scenario3_julia_to_julia.js ## Usage -### Scenario 0: Basic Multi-Payload Example +### Scenario 1: Command & Control (Small Dictionary) + +**Focus:** Sending small dictionary configurations across platforms. This is the simplest use case for command and control scenarios. + +**Julia (Sender/Receiver):** +```julia +using NATSBridge + +# Subscribe to control subject +# Parse JSON envelope +# Execute simulation with parameters +# Send acknowledgment +``` + +**JavaScript (Sender/Receiver):** +```javascript +const { smartsend } = require('./src/NATSBridge'); + +// Create small dictionary config +// Send via smartsend with type="dictionary" +const config = { + step_size: 0.01, + iterations: 1000, + threshold: 0.5 +}; + +await smartsend("control", [ + { dataname: "config", data: config, type: "dictionary" } +]); +``` + +**Python/Micropython (Sender/Receiver):** +```python +from nats_bridge import smartsend + +# Create small dictionary config +# Send via smartsend with type="dictionary" +config = { + "step_size": 0.01, + "iterations": 1000, + "threshold": 0.5 +} + +smartsend("control", [("config", config, "dictionary")]) +``` + +### Basic Multi-Payload Example #### Python/Micropython (Sender) ```python