scriptling.net.gossip
Gossip protocol cluster membership and messaging with automatic failure detection, metadata propagation, tag-based routing, encryption, and compression.
Overview
The scriptling.net.gossip library implements a gossip protocol for decentralized cluster management. Nodes automatically discover each other, detect failures, and propagate metadata across the cluster. It supports both unreliable (UDP) and reliable (TCP) messaging with optional AES encryption and Snappy compression.
Available Functions
| Function | Description |
|---|---|
create(bind_addr, ...) |
Create a gossip cluster node |
decode_json(json_string) |
Decode a JSON string to a scriptling value |
Constants
| Constant | Value | Description |
|---|---|---|
MSG_USER |
128 | Minimum user-defined message type |
Cluster Methods
The create() function returns a cluster object with these methods:
| Method | Description |
|---|---|
start() |
Start the cluster node |
join(peers) |
Join an existing cluster |
leave() |
Gracefully leave the cluster |
stop() |
Stop the cluster and clean up |
send(type, data, reliable=False) |
Broadcast to all nodes |
send_tagged(tag, type, data, reliable=False) |
Send to nodes with matching tag |
send_to(node_id, type, data, reliable=False) |
Send to a specific node |
handle(type, handler) |
Register a message handler |
on_state_change(handler) |
Register a state change handler |
nodes() |
Get all known nodes |
alive_nodes() |
Get all alive nodes |
local_node() |
Get local node info |
num_nodes() |
Get total node count |
num_alive() |
Get alive node count |
node_id() |
Get local node UUID |
set_metadata(key, value) |
Set local metadata |
get_metadata(key) |
Get local metadata value |
all_metadata() |
Get all local metadata |
delete_metadata(key) |
Delete a metadata key |
Setup
import scriptlinggossip "github.com/paularlott/scriptling/extlibs/net/gossip"
scriptlinggossip.Register(p, log)Functions
scriptling.net.gossip.create(bind_addr=“127.0.0.1:8000”, …)
Create a gossip cluster node.
Parameters:
bind_addr(string): Address to bind to (default:"127.0.0.1:8000")node_id(string): Unique node ID (auto-generated if empty)advertise_addr(string): Address to advertise to peers (default: same as bind_addr)encryption_key(string): Encryption key (16, 24, or 32 bytes for AES)tags(list): Tags for tag-based message routingcompression(bool): Enable Snappy compression (default: False)bearer_token(string): Authentication bearer tokenapp_version(string): Application version for compatibility checks
Returns: Cluster object
Example:
import scriptling.net.gossip as gossip
cluster = gossip.create(
bind_addr="127.0.0.1:8000",
tags=["web"],
encryption_key="0123456789abcdef"
)Cluster Methods
cluster.start()
Start the cluster node. Begins transport, health monitoring, and gossip routines.
Example:
cluster.start()cluster.join(peers)
Join an existing cluster by connecting to known peers.
Parameters:
peers(string or list): One or more peer addresses to join
Example:
cluster.join("127.0.0.1:8001")
cluster.join(["127.0.0.1:8001", "127.0.0.1:8002"])cluster.leave()
Gracefully leave the cluster. Other nodes will be notified.
Example:
cluster.leave()cluster.stop()
Stop the cluster and clean up all resources.
Example:
cluster.stop()cluster.send(message_type, data, reliable=False)
Broadcast a message to all cluster nodes.
Parameters:
message_type(int): Message type (must be >= 128)data: Message payload (string, int, float, list, dict)reliable(bool): Use reliable TCP transport (default: False)
Example:
cluster.send(128, "Hello cluster!")
cluster.send(128, {"key": "value"}, reliable=True)cluster.send_tagged(tag, message_type, data, reliable=False)
Send a tagged message. Only delivered to nodes that have the matching tag.
Parameters:
tag(string): Tag for routingmessage_type(int): Message type (must be >= 128)data: Message payloadreliable(bool): Use reliable transport (default: False)
Example:
cluster.send_tagged("web", 128, "Hello web nodes!")cluster.send_to(node_id, message_type, data, reliable=False)
Send a direct message to a specific node.
Parameters:
node_id(string): Target node UUIDmessage_type(int): Message type (must be >= 128)data: Message payloadreliable(bool): Use reliable transport (default: False)
Example:
target = cluster.nodes()[0]
cluster.send_to(target["id"], 128, "Direct message!")cluster.handle(message_type, handler)
Register a handler for a specific message type.
Parameters:
message_type(int): Message type to handle (must be >= 128)handler(function): Handler function called with a message dict
The handler receives a dict with:
type: message type (int)sender: dict withid,addr,state,metadatapayload: decoded message payload
Example:
def on_message(msg):
print(f"From {msg['sender']['id']}: {msg['payload']}")
cluster.handle(128, on_message)cluster.on_state_change(handler)
Register a handler called when any node changes state.
Parameters:
handler(function): Handler function(node_id, new_state)
States: "alive", "suspect", "dead", "leaving"
Example:
def on_change(node_id, state):
print(f"Node {node_id} is now {state}")
cluster.on_state_change(on_change)cluster.nodes()
Get all known nodes in the cluster.
Returns: List of node dicts with id, addr, state, metadata
Example:
for node in cluster.nodes():
print(f"{node['id']}: {node['state']} at {node['addr']}")cluster.alive_nodes()
Get all nodes currently in the alive state.
Returns: List of node dicts
cluster.local_node()
Get the local node information.
Returns: Node dict with id, addr, state, metadata
cluster.num_nodes()
Get the total number of known nodes.
Returns: int
cluster.num_alive()
Get the number of alive nodes.
Returns: int
cluster.node_id()
Get the local node’s unique UUID.
Returns: string
cluster.set_metadata(key, value)
Set a local node metadata value. Metadata is automatically gossiped to other nodes.
Parameters:
key(string): Metadata keyvalue(string, int, float, or bool): Metadata value
Example:
cluster.set_metadata("role", "worker")
cluster.set_metadata("version", 2)cluster.get_metadata(key)
Get a local metadata value.
Parameters:
key(string): Metadata key
Returns: string or None
cluster.all_metadata()
Get all local metadata.
Returns: dict
cluster.delete_metadata(key)
Delete a metadata key.
Parameters:
key(string): Metadata key to delete
scriptling.net.gossip.decode_json(json_string)
Decode a JSON string to a scriptling value.
Parameters:
json_string(string): JSON string to decode
Returns: Decoded value (dict, list, string, int, float, bool, or None)
Examples
Basic Cluster
import scriptling.net.gossip as gossip
cluster = gossip.create(bind_addr="127.0.0.1:8000")
cluster.start()
cluster.join(["127.0.0.1:8001"])
cluster.handle(128, lambda msg: print(msg["payload"]))
cluster.send(128, "Hello!")
cluster.stop()Three-Node Cluster with Tags
import scriptling.net.gossip as gossip
# Node 1 - web server
web = gossip.create(bind_addr="127.0.0.1:8000", tags=["web"])
web.start()
# Node 2 - worker
worker = gossip.create(bind_addr="127.0.0.1:8001", tags=["worker"])
worker.start()
worker.join(["127.0.0.1:8000"])
# Node 3 - both
hybrid = gossip.create(bind_addr="127.0.0.1:8002", tags=["web", "worker"])
hybrid.start()
hybrid.join(["127.0.0.1:8000"])
# Only web-tagged nodes receive this
web.send_tagged("web", 128, "Hello web nodes!")Metadata and State Monitoring
import scriptling.net.gossip as gossip
cluster = gossip.create(bind_addr="127.0.0.1:8000")
cluster.set_metadata("role", "leader")
cluster.set_metadata("version", 2)
cluster.start()
cluster.on_state_change(lambda node_id, state:
print(f"Node {node_id} -> {state}")
)
cluster.join(["127.0.0.1:8001"])
# Check other nodes' metadata
for node in cluster.alive_nodes():
print(f"{node['id']}: {node['metadata']}")Encrypted Cluster
import scriptling.net.gossip as gossip
cluster = gossip.create(
bind_addr="0.0.0.0:8000",
encryption_key="32-byte-key-here-1234567890ab",
compression=True,
bearer_token="secret-token"
)
cluster.start()
cluster.join(["10.0.0.1:8000"])Notes
- Message types 0-127 are reserved for internal protocol use
- User message types must be >= 128 (use
MSG_USERconstant) reliable=Trueuses TCP for guaranteed delivery- Metadata is eventually consistent across the cluster
- Always call
stop()to properly clean up resources