architecture.md rev1
This commit is contained in:
@@ -4,6 +4,32 @@
|
||||
|
||||
This document describes the implementation of the high-performance, bi-directional data bridge between Julia and JavaScript services using NATS (Core & JetStream), implementing the Claim-Check pattern for large payloads.
|
||||
|
||||
### Multi-Payload Support
|
||||
|
||||
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.**
|
||||
|
||||
**API Standard:**
|
||||
```julia
|
||||
# Input format for smartsend (always a list of tuples)
|
||||
[(dataname1, data1), (dataname2, data2), ...]
|
||||
|
||||
# Output format for smartreceive (always returns a list of tuples)
|
||||
[(dataname1, data1), (dataname2, data2), ...]
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```julia
|
||||
# Single payload - still wrapped in a list
|
||||
smartsend("/test", [(dataname1, data1)], ...)
|
||||
|
||||
# Multiple payloads in one message
|
||||
smartsend("/test", [(dataname1, data1), (dataname2, data2)], ...)
|
||||
|
||||
# Receive always returns a list
|
||||
payloads = smartreceive(msg, ...)
|
||||
# payloads = [(dataname1, data1), (dataname2, data2), ...]
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
The implementation follows the Claim-Check pattern:
|
||||
@@ -107,20 +133,66 @@ node test/scenario3_julia_to_julia.js
|
||||
|
||||
## Usage
|
||||
|
||||
### Scenario 0: Basic Multi-Payload Example
|
||||
|
||||
#### Julia (Sender)
|
||||
```julia
|
||||
using NATSBridge
|
||||
|
||||
# Send multiple payloads in one message
|
||||
smartsend(
|
||||
"/test",
|
||||
[("dataname1", data1), ("dataname2", data2)],
|
||||
nats_url="nats://localhost:4222",
|
||||
fileserver_url="http://localhost:8080/upload",
|
||||
metadata=Dict("custom_key" => "custom_value")
|
||||
)
|
||||
|
||||
# Even single payload must be wrapped in a list
|
||||
smartsend("/test", [("single_data", mydata)])
|
||||
```
|
||||
|
||||
#### Julia (Receiver)
|
||||
```julia
|
||||
using NATSBridge
|
||||
|
||||
# Receive returns a list of payloads
|
||||
payloads = smartreceive(msg, "http://localhost:8080/upload")
|
||||
# payloads = [(dataname1, data1), (dataname2, data2), ...]
|
||||
```
|
||||
|
||||
### Scenario 1: Command & Control (Small JSON)
|
||||
|
||||
#### JavaScript (Sender)
|
||||
```javascript
|
||||
const { SmartSend } = require('./js_bridge');
|
||||
|
||||
const config = {
|
||||
step_size: 0.01,
|
||||
iterations: 1000
|
||||
};
|
||||
// Single payload wrapped in a list
|
||||
const config = [{
|
||||
dataname: "config",
|
||||
data: { step_size: 0.01, iterations: 1000 },
|
||||
type: "json"
|
||||
}];
|
||||
|
||||
await SmartSend("control", config, "json", {
|
||||
correlationId: "unique-id"
|
||||
});
|
||||
|
||||
// Multiple payloads
|
||||
const configs = [
|
||||
{
|
||||
dataname: "config1",
|
||||
data: { step_size: 0.01 },
|
||||
type: "json"
|
||||
},
|
||||
{
|
||||
dataname: "config2",
|
||||
data: { iterations: 1000 },
|
||||
type: "json"
|
||||
}
|
||||
];
|
||||
|
||||
await SmartSend("control", configs, "json");
|
||||
```
|
||||
|
||||
#### Julia (Receiver)
|
||||
@@ -157,8 +229,8 @@ df = DataFrame(
|
||||
category = rand(["A", "B", "C"], 10_000_000)
|
||||
)
|
||||
|
||||
# Send via SmartSend with type="table"
|
||||
await SmartSend("analysis_results", df, "table");
|
||||
# Send via SmartSend - wrapped in a list
|
||||
await SmartSend("analysis_results", [("table_data", df)], "table");
|
||||
```
|
||||
|
||||
#### JavaScript (Receiver)
|
||||
@@ -177,8 +249,12 @@ const table = result.data;
|
||||
```javascript
|
||||
const { SmartSend } = require('./js_bridge');
|
||||
|
||||
// Capture binary chunk
|
||||
const binaryData = await navigator.mediaDevices.getUserMedia({ binary: true });
|
||||
// Binary data wrapped in a list
|
||||
const binaryData = [{
|
||||
dataname: "audio_chunk",
|
||||
data: binaryBuffer,
|
||||
type: "binary"
|
||||
}];
|
||||
|
||||
await SmartSend("binary_input", binaryData, "binary", {
|
||||
metadata: {
|
||||
@@ -208,16 +284,13 @@ end
|
||||
|
||||
#### Julia (Producer)
|
||||
```julia
|
||||
using NATS
|
||||
using NATSBridge
|
||||
|
||||
function publish_health_status(nats)
|
||||
jetstream = JetStream(nats, "health_updates")
|
||||
|
||||
while true
|
||||
status = Dict("cpu" => rand(), "memory" => rand())
|
||||
publish(jetstream, "health", status)
|
||||
sleep(5) # Every 5 seconds
|
||||
end
|
||||
function publish_health_status(nats_url)
|
||||
# Send status wrapped in a list
|
||||
status = Dict("cpu" => rand(), "memory" => rand())
|
||||
smartsend("health", [("status", status)], "json", nats_url=nats_url)
|
||||
sleep(5) # Every 5 seconds
|
||||
end
|
||||
```
|
||||
|
||||
@@ -238,7 +311,8 @@ const consumer = await js.pullSubscribe("health", {
|
||||
// Process historical and real-time messages
|
||||
for await (const msg of consumer) {
|
||||
const result = await SmartReceive(msg);
|
||||
// Process the data
|
||||
// result.data contains the list of payloads
|
||||
// result.envelope contains the message envelope
|
||||
msg.ack();
|
||||
}
|
||||
```
|
||||
@@ -257,16 +331,39 @@ for await (const msg of consumer) {
|
||||
|
||||
```json
|
||||
{
|
||||
"correlation_id": "uuid-v4-string",
|
||||
"type": "json|table|binary",
|
||||
"transport": "direct|link",
|
||||
"payload": "base64-encoded-string", // Only if transport=direct
|
||||
"url": "http://fileserver/path/to/data", // Only if transport=link
|
||||
"correlationId": "uuid-v4-string",
|
||||
"msgId": "uuid-v4-string",
|
||||
"timestamp": "2024-01-15T10:30:00Z",
|
||||
|
||||
"sendTo": "topic/subject",
|
||||
"msgPurpose": "ACK | NACK | updateStatus | shutdown | chat",
|
||||
"senderName": "agent-wine-web-frontend",
|
||||
"senderId": "uuid4",
|
||||
"receiverName": "agent-backend",
|
||||
"receiverId": "uuid4",
|
||||
"replyTo": "topic",
|
||||
"replyToMsgId": "uuid4",
|
||||
"BrokerURL": "nats://localhost:4222",
|
||||
|
||||
"metadata": {
|
||||
"content_type": "application/octet-stream",
|
||||
"content_length": 123456,
|
||||
"format": "arrow_ipc_stream"
|
||||
}
|
||||
"content_length": 123456
|
||||
},
|
||||
|
||||
"payloads": [
|
||||
{
|
||||
"id": "uuid4",
|
||||
"dataname": "login_image",
|
||||
"type": "image",
|
||||
"transport": "direct",
|
||||
"encoding": "base64",
|
||||
"size": 15433,
|
||||
"data": "base64-encoded-string",
|
||||
"metadata": {
|
||||
"checksum": "sha256_hash"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user