{"id":34746111,"url":"https://github.com/paularlott/gossip","last_synced_at":"2026-05-22T20:06:21.688Z","repository":{"id":286175492,"uuid":"958109111","full_name":"paularlott/gossip","owner":"paularlott","description":"Go library to implement gossip based membership and messaging, it supports TCP, UDP and WebSocket protocols with pluggable codecs.","archived":false,"fork":false,"pushed_at":"2026-05-14T17:40:36.000Z","size":570,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-14T19:38:27.278Z","etag":null,"topics":["distributed-systems","gossip-protocol","websocket"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paularlott.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":"CONTRIBUTOR_LICENSE_AGREEMENT.md"}},"created_at":"2025-03-31T16:54:54.000Z","updated_at":"2026-05-14T17:40:40.000Z","dependencies_parsed_at":"2025-04-04T19:45:12.191Z","dependency_job_id":"dd7725ba-392a-47a4-a683-6c9e05ab9787","html_url":"https://github.com/paularlott/gossip","commit_stats":null,"previous_names":["paularlott/gossip"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/paularlott/gossip","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paularlott%2Fgossip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paularlott%2Fgossip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paularlott%2Fgossip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paularlott%2Fgossip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paularlott","download_url":"https://codeload.github.com/paularlott/gossip/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paularlott%2Fgossip/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33364339,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-21T12:23:38.849Z","status":"online","status_checked_at":"2026-05-22T02:00:06.671Z","response_time":265,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distributed-systems","gossip-protocol","websocket"],"created_at":"2025-12-25T04:40:02.214Z","updated_at":"2026-05-22T20:06:21.682Z","avatar_url":"https://github.com/paularlott.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gossip Protocol Library\n\nA lightweight, Go-based library for implementing the gossip protocol in distributed systems. The library supports multiple transport mechanisms, including TCP, UDP, and HTTP, providing flexibility for a variety of use cases.\n\nWith its straightforward API, the library simplifies decentralized communication by enabling the creation and management of nodes, exchanging messages, and handling critical events like node joins and departures. Designed with reliability in mind, it continuously monitors node health within the cluster and seamlessly removes unreachable nodes, ensuring the system stays robust and adaptive.\n\nThe library leverages a hybrid approach to gossiping, combining **event-driven gossiping** and **periodic gossiping** to balance rapid updates and eventual consistency across the cluster:\n\n- **Event-Driven Gossiping** swiftly propagates critical updates immediately after events occur, minimizing latency.\n- **Periodic Gossiping** adds redundancy by disseminating updates at regular intervals, ensuring eventual consistency even if some nodes initially miss updates.\n\nThis flexible architecture supports the development of resilient distributed systems with efficient data sharing and robust fault tolerance.\n\n## Features\n\n- **Multiple Transport Support**: TCP, UDP, and HTTP connections\n- **Message Security**: Optional encryption for message payloads\n- **Compression**: Configurable message compression, support for Snappy is provide by default\n- **Health Monitoring**: Automatic node health checking with direct and indirect pings\n- **Flexible Codec Support**: Pluggable serialization with support for multiple msgpack implementations\n- **Metadata Sharing**: Distribute custom node metadata across the cluster\n- **Version Checking**: Application and protocol version compatibility verification\n- **Automatic Transport Selection**: UDP will be used wherever possible, however if the packet exceeds the MTU size, TCP will be used instead\n\n## Installation\n\nTo install the library, use the following command:\n\n```shell\ngo get github.com/paularlott/gossip\n```\n\n## Basic Usage\n\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"time\"\n\n  \"github.com/paularlott/gossip\"\n  \"github.com/paularlott/gossip/codec\"\n  \"github.com/paularlott/gossip/compression\"\n)\n\nfunc main() {\n  // Create configuration\n  config := gossip.DefaultConfig()\n  config.NodeID = \"01960f9b-72ca-7a51-9efa-47c12f42a138\"       // Optional: auto-generated if not specified\n  config.BindAddr = \"127.0.0.1:8000\"                           // Listen on TCP and UDP\n  config.EncryptionKey = \"your-32-byte-key\"                    // Optional: enables encryption\n\tconfig.Cipher = encryption.NewAESEncryptor()                 // Encryption algorithm\n  config.MsgCodec = codec.NewShamatonMsgpackCodec()            // Message serialization\n  config.Compressor = compression.NewSnappyCompressor()        // Optional: enables compression\n\n  // Create and start the cluster\n  cluster, err := gossip.NewCluster(config)\n  if err != nil {\n    panic(err)\n  }\n\tcluster.Start()\n\tdefer cluster.Stop()\n\n  // Join existing cluster (if any)\n  err = cluster.Join([]string{\"127.0.0.1:8001\"})\n  if err != nil {\n    fmt.Println(\"Warning:\", err)\n  }\n\n  // Register message handler\n  const CustomMsg gossip.MessageType = gossip.UserMsg + 1\n  cluster.HandleFunc(CustomMsg, func(sender *gossip.Node, packet *gossip.Packet) error {\n    var message string\n    if err := packet.UnmarshalPayload(\u0026message); err != nil {\n        return err\n    }\n    fmt.Printf(\"Received message from %s: %s\\n\", sender.ID, message)\n    return nil\n  })\n\n  // Broadcast a message\n  message := \"Hello cluster!\"\n  cluster.Broadcast(CustomMsg, message)\n\n  // Keep the application running\n  select {}\n}\n```\n\n## Address Formats\n\nThe gossip library supports multiple address formats for binding and connecting to the cluster:\n\n- **IP:port** - Standard TCP/UDP address (e.g., 127.0.0.1:8000)\n- **hostname:port** - DNS hostname with port, when multiple addresses are returned the node will attempt to connect to each address in turn assuming each is a node within the cluster\n- **hostname** or **IP** - The default port will be used, for a hostname returning multiple addresses the node will attempt to connect to each address in turn assuming each is a node within the cluster\n- **srv+service-name** - SRV DNS record lookup, when multiple addresses are returned the node will attempt to connect to each address in turn assuming each is a node within the cluster\n- **https://hostname:port/endpoint** - HTTP connection\n- **srv+https://hostname:port/endpoint** - Secure HTTP connection looking up the port number for the target\n\n## Configuration Options\n\nThe `Config` struct provides extensive customization:\n\n```go\nconfig := gossip.DefaultConfig()\n\n// Node identification\nconfig.NodeID = \"unique-node-id\"               // Optional: auto-generated if not provided\nconfig.BindAddr = \"0.0.0.0:3500\"               // Address to bind for listening\nconfig.AdvertiseAddr = \"192.168.1.1:3500\"      // Address to advertise to peers (optional)\n\n// Communication\nconfig.EncryptionKey = \"your-32-byte-key\"              // Optional: enables encryption\nconfig.Cipher = encryption.NewAESEncryptor()           // Encryption algorithm\nconfig.Compressor = compression.NewSnappyCompressor()  // Enable payload compression using the provided compressor\nconfig.CompressMinSize = 1024                          // Minimum size of a packet that will be considered for compression\nconfig.Transport = gossip.NewSocketTransport(config)   // Socket based transport\n\n// Custom dialer/listener (e.g. for overlay networks like Tailscale tsnet)\nconfig.DialFunc = srv.Dial       // Custom TCP dial function, defaults to net.DialTimeout\nconfig.ListenFunc = srv.Listen   // Custom TCP listen function, defaults to net.ListenTCP\n                                 // Setting ListenFunc automatically enables ForceReliableTransport\n\n// Logging\nconfig.Logger = logger.NewNullLogger()                 // Default: no logging\n```\n\n## Logging\n\nThe library uses the [github.com/paularlott/logger](https://github.com/paularlott/logger) interface for logging. By default, a null logger is used which discards all log output. You can provide your own logger implementation by implementing the `logger.Logger` interface:\n\n```go\ntype Logger interface {\n    Trace(msg string, args ...any)\n    Debug(msg string, args ...any)\n    Info(msg string, args ...any)\n    Warn(msg string, args ...any)\n    Error(msg string, args ...any)\n    Fatal(msg string, args ...any)\n    With(key string, value any) Logger\n    WithError(err error) Logger\n    WithGroup(name string) Logger\n}\n```\n\nThe `Fatal` method logs the message and then calls `os.Exit(1)`, making it convenient for handling fatal errors without explicit exit calls.\n\n### Using slog\n\nThe library provides examples using the slog implementation:\n\n```go\nimport (\n    \"os\"\n    \"github.com/paularlott/logger/slog\"\n)\n\n// Create a console logger with colored output\nlogger := slog.New(\"debug\", \"console\", os.Stderr)\n\n// Configure the cluster with the logger\nconfig := gossip.DefaultConfig()\nconfig.Logger = logger\n```\n\nSee the [examples/common/log.go](examples/common/log.go) file for a complete implementation using slog.\n\n## Node States\n\nNodes in the cluster go through several states:\n\n- **NodeUnknown** - Node state is unknown, nodes start in this state and change to NodeAlive when joining the cluster\n- **NodeAlive** - Node is active and healthy\n- **NodeSuspect** - Node might be unhealthy (pending confirmation)\n- **NodeDead** - Node is confirmed dead\n- **NodeLeaving** - Node is gracefully leaving the cluster\n\n## Message Codecs\n\nMultiple serialization options are available allowing you to choose the one that best fits your application:\n\n```go\n// Using Shamaton msgpack\nconfig.MsgCodec = codec.NewShamatonMsgpackCodec()\n\n// Using Vmihailenco msgpack\nconfig.MsgCodec = codec.NewVmihailencoMsgpackCodec()\n\n// Using JSON\nconfig.MsgCodec = codec.NewJSONCodec()\n```\n\n### Examples\n\nThe `examples` directory contains various examples demonstrating the library's capabilities. Each example is self-contained and can be run independently.\n\n- **[basic](examples/basic)**: A basic usage example that creates a cluster and joins nodes to it. Nodes can communicate over TCP/UDP or HTTP.\n- **[events](examples/events)**: Example that installs an event handler to display cluster events.\n- **[usermessages](examples/usermessages)**: Example that demonstrates user defined message handling.\n- **[kv](examples/kv)**: Example Key Value store.\n- **[leader](examples/leader)**: Example demonstrating leader election.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaularlott%2Fgossip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaularlott%2Fgossip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaularlott%2Fgossip/lists"}