this repo has no description
1# swim 2 3An OCaml 5 implementation of the SWIM (Scalable Weakly-consistent Infection-style Process Group Membership) protocol for cluster membership and failure detection. 4 5## Overview 6 7This library provides: 8 9- **Membership Management**: Automatic discovery and tracking of cluster nodes 10- **Failure Detection**: Identifies unreachable nodes using periodic probes and indirect checks 11- **Gossip Protocol**: Propagates state changes (Alive/Suspect/Dead) across the cluster 12- **Messaging**: Cluster-wide broadcast (gossip-based) and direct point-to-point UDP messaging 13- **Encryption**: Optional AES-256-GCM encryption for all network traffic 14 15Built on [Eio](https://github.com/ocaml-multicore/eio) for effect-based concurrency and [Kcas](https://github.com/ocaml-multicore/kcas) for lock-free shared state. 16 17## Requirements 18 19- OCaml >= 5.1 20- Dune >= 3.20 21 22## Installation 23 24```bash 25opam install . 26``` 27 28Or add to your dune-project: 29 30``` 31(depends (swim (>= 0.1.0))) 32``` 33 34## Usage 35 36### Basic Example 37 38```ocaml 39open Swim.Types 40 41let config = { 42 default_config with 43 bind_port = 7946; 44 node_name = Some "node-1"; 45 secret_key = "your-32-byte-secret-key-here!!!"; (* 32 bytes for AES-256 *) 46 encryption_enabled = true; 47} 48 49let () = 50 Eio_main.run @@ fun env -> 51 Eio.Switch.run @@ fun sw -> 52 let env_wrap = { stdenv = env; sw } in 53 match Swim.Cluster.create ~sw ~env:env_wrap ~config with 54 | Error `Invalid_key -> failwith "Invalid secret key" 55 | Ok cluster -> 56 Swim.Cluster.start cluster; 57 58 (* Join an existing cluster *) 59 let seed_nodes = ["192.168.1.10:7946"] in 60 (match Swim.Cluster.join cluster ~seed_nodes with 61 | Ok () -> Printf.printf "Joined cluster\n" 62 | Error `No_seeds_reachable -> Printf.printf "Failed to join\n"); 63 64 (* Send a broadcast message to all nodes *) 65 Swim.Cluster.broadcast cluster ~topic:"config" ~payload:"v2"; 66 67 (* Send a direct message to a specific node *) 68 let target = node_id_of_string "node-2" in 69 Swim.Cluster.send cluster ~target ~topic:"ping" ~payload:"hello"; 70 71 (* Handle incoming messages *) 72 Swim.Cluster.on_message cluster (fun sender topic payload -> 73 Printf.printf "From %s: [%s] %s\n" 74 (node_id_to_string sender.id) topic payload); 75 76 (* Listen for membership events *) 77 Eio.Fiber.fork ~sw (fun () -> 78 let stream = Swim.Cluster.events cluster in 79 while true do 80 match Eio.Stream.take stream with 81 | Join node -> Printf.printf "Joined: %s\n" (node_id_to_string node.id) 82 | Leave node -> Printf.printf "Left: %s\n" (node_id_to_string node.id) 83 | Suspect_event node -> Printf.printf "Suspect: %s\n" (node_id_to_string node.id) 84 | Alive_event node -> Printf.printf "Alive: %s\n" (node_id_to_string node.id) 85 | Update _ -> () 86 done); 87 88 Eio.Fiber.await_cancel () 89``` 90 91### Configuration Options 92 93| Field | Default | Description | 94|-------|---------|-------------| 95| `bind_addr` | "0.0.0.0" | Interface to bind listeners | 96| `bind_port` | 7946 | Port for SWIM protocol | 97| `protocol_interval` | 1.0 | Seconds between probe rounds | 98| `probe_timeout` | 0.5 | Seconds to wait for Ack | 99| `indirect_checks` | 3 | Peers to ask for indirect probes | 100| `secret_key` | (zeros) | 32-byte key for AES-256-GCM | 101| `encryption_enabled` | false | Enable encryption | 102 103## Interoperability Testing 104 105The library includes interoperability tests with HashiCorp's [memberlist](https://github.com/hashicorp/memberlist) (Go). This verifies protocol compatibility with the reference implementation. 106 107### Prerequisites 108 109- Go >= 1.19 110- OCaml environment with dune 111 112### Running Interop Tests 113 114The interop test suite starts a Go memberlist node and an OCaml node, then verifies they can discover each other and exchange messages. 115 116```bash 117# Build the OCaml project 118dune build 119 120# Build the Go memberlist server 121cd interop && go build -o memberlist-server main.go && cd .. 122 123# Run the interop test 124bash test/scripts/test_interop.sh 125 126# Run with encryption enabled 127bash test/scripts/test_interop_encrypted.sh 128``` 129 130### Manual Interop Testing 131 132Start the Go node: 133 134```bash 135cd interop 136go run main.go -name go-node -bind 127.0.0.1 -port 7946 137``` 138 139In another terminal, start the OCaml node: 140 141```bash 142dune exec swim-interop-test 143``` 144 145The OCaml node will connect to the Go node and print membership statistics for 30 seconds. 146 147### Available Test Scripts 148 149| Script | Description | 150|--------|-------------| 151| `test/scripts/test_interop.sh` | Basic interop test | 152| `test/scripts/test_interop_encrypted.sh` | Interop with AES encryption | 153| `test/scripts/test_interop_udp_only.sh` | UDP-only communication test | 154| `test/scripts/test_interop_go_joins.sh` | Go node joining OCaml cluster | 155 156### Debug Utilities 157 158```bash 159# Test packet encoding/decoding 160dune exec swim-debug-codec 161 162# Receive and display incoming SWIM packets 163dune exec swim-debug-recv 164 165# Send manual ping to a target node 166dune exec swim-debug-ping 167``` 168 169## Running Tests 170 171```bash 172dune runtest 173``` 174 175## License 176 177ISC License. See [LICENSE](LICENSE) for details.