{"id":21754604,"url":"https://github.com/mdawar/pubsub","last_synced_at":"2025-03-21T03:15:07.153Z","repository":{"id":252619065,"uuid":"840009344","full_name":"mdawar/pubsub","owner":"mdawar","description":"A simple and generic publish/subscribe package for Go.","archived":false,"fork":false,"pushed_at":"2025-01-22T17:32:20.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-22T18:24:11.522Z","etag":null,"topics":["event-bus","go","message-bus","pubsub"],"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/mdawar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2024-08-08T19:22:38.000Z","updated_at":"2025-01-22T17:31:56.000Z","dependencies_parsed_at":"2025-01-22T18:32:02.691Z","dependency_job_id":null,"html_url":"https://github.com/mdawar/pubsub","commit_stats":null,"previous_names":["mdawar/pubsub"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdawar%2Fpubsub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdawar%2Fpubsub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdawar%2Fpubsub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdawar%2Fpubsub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdawar","download_url":"https://codeload.github.com/mdawar/pubsub/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244728235,"owners_count":20500023,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["event-bus","go","message-bus","pubsub"],"created_at":"2024-11-26T09:14:29.294Z","updated_at":"2025-03-21T03:15:07.135Z","avatar_url":"https://github.com/mdawar.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pubsub\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/mdawar/pubsub.svg)](https://pkg.go.dev/github.com/mdawar/pubsub)\n[![Go Report Card](https://goreportcard.com/badge/github.com/mdawar/pubsub)](https://goreportcard.com/report/github.com/mdawar/pubsub)\n[![Tests](https://github.com/mdawar/pubsub/actions/workflows/test.yml/badge.svg)](https://github.com/mdawar/pubsub/actions/workflows/test.yml)\n\n`pubsub` is a simple and generic **topic-based** **publish/subscribe** package for in-process communication in **Go**.\n\n## Installation\n\n```sh\ngo get -u github.com/mdawar/pubsub\n```\n\n#### Import\n\n```go\nimport \"github.com/mdawar/pubsub\"\n```\n\n## Usage\n\n#### Create a Broker\n\n```go\n// Create a message broker.\n// The type params are for the topic, payload and sender respectively.\nbroker := pubsub.NewBroker[string, string, string]()\n\n// Any types can be used.\nevents := pubsub.NewBroker[string, Event, int]()\n```\n\n#### Subscriptions\n\nA subscription is simply a channel, everything that you know about [channels](https://go.dev/ref/spec#Channel_types) can be applied to subscriptions.\n\n```go\n// Create a subscription to a topic.\n// A subscription is a channel that receives messages published to the topic.\n// By default the channel is unbuffered (capacity = 0).\nsub1 := broker.Subscribe(\"events\")\n\n// A subscription can be created to multiple topics.\n// The channel will receive all the messages published to all the specified topics.\nsub2 := broker.Subscribe(\"events\", \"actions\", \"testing\")\n\n// Create a subscription with a buffered channel.\n// The channel capacity is specified as the first parameter.\nsub3 := broker.SubscribeWithCapacity(10, \"events\")\n\n// Unsubscribe from a specific topic or topics.\n// The channel will still receive messages for the other topics.\nbroker.Unsubscribe(sub2, \"actions\", \"testing\")\n\n// Unsubscribe from all topics.\n// The channel will not be closed, it will only stop receiving messages.\n// NOTE: Specifying all the topics is much more efficient if performance is critical.\nbroker.Unsubscribe(sub2)\n```\n\n#### Publishing Messages\n\n```go\n// A message is composed of a topic, payload and an optional sender.\n// The type params are the same types used when creating the broker.\nvar msg = pubsub.Message[string, string, string]{\n  Topic: \"events\",\n  Payload: \"Sample message\",\n  Sender: \"sender-id\",\n}\n\n// You can specify an alias for the generic message type.\ntype Message = pubsub.Message[string, string, string]\n\n// Publish a message with the specified payload.\n// The payload can be of any type that is specified when creating the broker.\n//\n// The message will be sent concurrently to the subscribers, ensuring that a slow\n// consumer won't affect the other subscribers.\n//\n// This call will block until all the subscription channels receive the message\n// or until the context is canceled.\n//\n// A nil return value indicates that all the subscribers received the message.\nbroker.Publish(context.TODO(), Message{\n  Topic: \"events\",\n  Payload: \"Sample message\",\n  Sender: \"sender-id\", // Optional.\n})\n```\n\n```go\n// Publish a message and timeout after 1 second.\nctx, cancel := context.WithTimeout(context.Background(), time.Second)\ndefer cancel()\n// In this case, Publish will deliver the message to subscribers that are\n// ready and will wait for the others for up to the timeout duration.\nerr := broker.Publish(ctx, Message{Topic: \"events\", Payload: \"Sample message\"})\n// The error is not nil if the context was canceled or the deadline exceeded.\nif err != nil {\n  if errors.Is(err, context.DeadlineExceeded) {\n    // Timed out.\n  } else if errors.Is(err, context.Canceled) {\n    // Canceled.\n  }\n}\n```\n\n```go\n// Non blocking publish (Fire and forget).\n//\n// The message is sent sequentially to the subscribers that are ready to receive it\n// and the others are skipped.\n//\n// NOTE: Message delivery is not guaranteed.\nbroker.TryPublish(Message{\n  Topic: \"events\",\n  Payload: \"A message that may not be delivered\",\n})\n\n// Buffered subscriptions can be used for guaranteed delivery with a non-blocking publish.\n//\n// Publish will still block if any subscription's channel buffer is full, or any of the\n// subscriptions is an unbuffered channel.\nsub := broker.SubscribeWithCapacity(1, \"events\")\nbroker.Publish(context.TODO(), Message{\n  Topic: \"events\",\n  Payload: \"Guaranteed delivery message\",\n})\n```\n\n#### Messages\n\n```go\nsub := broker.Subscribe(\"events\")\n\n// Receive a message from the channel.\nmsg := \u003c-sub\n\n// The topic that the message was published on.\nmsg.Topic\n// The payload that was published using Publish() or TryPublish().\nmsg.Payload\n// The message sender.\nmsg.Sender\n```\n\n#### Topics\n\n```go\n// Get a slice of all the topics registered on the broker.\n// NOTE: The order of the topics is not guaranteed.\ntopics := broker.Topics()\n\n// Get the total number of topics.\ntopicsCount := broker.NumTopics()\n\n// Get the subscribers count on a specific topic.\ncount := broker.Subscribers(\"events\")\n```\n\n## Tests\n\n```sh\ngo test -race -cover\n# If you have \"just\" installed.\njust test\n# Or using make.\nmake test\n```\n\n## Benchmarks\n\n```sh\ngo test -bench .\n# Or Using \"just\".\njust benchmark\n# Or using make.\nmake benchmark\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdawar%2Fpubsub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdawar%2Fpubsub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdawar%2Fpubsub/lists"}