{"id":37212348,"url":"https://github.com/razzie/broadcaster","last_synced_at":"2026-01-15T00:25:34.747Z","repository":{"id":210324447,"uuid":"726291980","full_name":"razzie/broadcaster","owner":"razzie","description":"A simple library that broadcasts messages from one channel to many, with timeout support","archived":false,"fork":false,"pushed_at":"2024-04-13T13:41:27.000Z","size":59,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-14T01:13:36.289Z","etag":null,"topics":["broadcast","broadcaster","eventstream","golang","library","server-sent-events","sse"],"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/razzie.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}},"created_at":"2023-12-02T00:46:06.000Z","updated_at":"2024-05-05T22:00:09.685Z","dependencies_parsed_at":null,"dependency_job_id":"973daa20-632b-483e-b9ce-40a4d371305e","html_url":"https://github.com/razzie/broadcaster","commit_stats":null,"previous_names":["razzie/broadcaster"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/razzie/broadcaster","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razzie%2Fbroadcaster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razzie%2Fbroadcaster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razzie%2Fbroadcaster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razzie%2Fbroadcaster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/razzie","download_url":"https://codeload.github.com/razzie/broadcaster/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razzie%2Fbroadcaster/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28439701,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T22:37:52.437Z","status":"ssl_error","status_checked_at":"2026-01-14T22:37:31.496Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["broadcast","broadcaster","eventstream","golang","library","server-sent-events","sse"],"created_at":"2026-01-15T00:25:33.860Z","updated_at":"2026-01-15T00:25:34.722Z","avatar_url":"https://github.com/razzie.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# github.com/razzie/broadcaster\n\n## Summary\nThe scope of this library is to take an input Go channel (producer) and broadcast the objects sent over it to an arbitrary amount of listeners (consumers).\n\nListeners are channels of the same type as the input channel. They can be opened and closed at any time and these operations block until the listener is opened/closed.\n\nAn incoming object from the input channel is always sent to all current listeners before the next object is consumed. If there are no listeners, the incoming object is dropped, unless the broadcaster is set to blocking mode. It is possible to configure a timeout so blocking listeners won't clog the broadcaster.\n\nClosing the input channel closes all listeners and subsequent calls to ``Listen()`` return ``ErrBroadcasterClosed`` error.\n\n### Server Sent Events\nAs an extra feature, the library supports the creation of a http.Handler that broadcasts incoming objects from one or more input channels (event sources).\n\n## Feature table\n| Instantiation                            | Input type          | On-demand | Multi-source | Converter | SSE |\n| ---------------------------------------- | ------------------- | --------- | ------------ | --------- | --- |\n| NewBroadcaster[T]                        | \u003c-chan T            | no        | no           | no        | no  |\n| NewConverterBroadcaster[In, Out]         | \u003c-chan In           | no        | no           | yes       | no  |\n| NewOndemandBroadcaster[T]                | Source[T]           | yes       | no           | no        | no  |\n| NewOndemandConverterBroadcaster[In, Out] | Source[In]          | yes       | no           | yes       | no  |\n| NewMultiBroadcaster[K, T]                | MultiSource[K, T]   | yes       | yes          | no        | no  |\n| NewMultiConverterBroadcaster[K, In, Out] | MultiSource[K, In]  | yes       | yes          | yes       | no  |\n| NewSSEBroadcaster                        | \u003c-chan Event        | no        | yes*         | yes*      | yes |\n| NewMultiSSEBroadcaster[K]                | MultiEventSource[K] | yes       | yes          | yes*      | yes |\n\n\\* SSE broadcasters use the marshaler from an event source and support multiple sources when used with `BundleEventSources`\n\n## API reference\n### Broadcaster interface, instantiation and options\n```go\ntype Broadcaster[T any] interface {\n\tListen(opts ...ListenerOption) (\u003c-chan T, CancelFunc, error)\n\tIsClosed() bool\n\tDone() \u003c-chan struct{}\n}\n\nfunc NewBroadcaster[T any](input \u003c-chan T, opts ...BroadcasterOption) Broadcaster[T]\n\nfunc WithTimeout(timeout time.Duration) BroadcasterOption\nfunc WithListenerBufferSize(bufSize int) BroadcasterOption\nfunc WithBlocking(blocking bool) BroadcasterOption\nfunc WithIdleTimeout(timeout time.Duration) BroadcasterOption\n\nfunc WithBufferSize(bufSize int) ListenerOption\nfunc WithContext(ctx context.Context) ListenerOption\nfunc WithTimeoutCallback(func()) ListenerOption\n```\n\n### Server Sent Events\n```go\ntype Event interface {\n\tRead() (name, data string)\n}\ntype Marshaler func(any) ([]byte, error)\n\nfunc NewEventSource[T any](input \u003c-chan T, eventName string, marshaler Marshaler) \u003c-chan Event\nfunc NewJsonEventSource[T any](input \u003c-chan T, eventName string) \u003c-chan Event\nfunc NewTextEventSource(input \u003c-chan string, eventName string) \u003c-chan Event\nfunc NewTemplateEventSource[T any](input \u003c-chan T, eventName string, t *template.Template, templateName string) \u003c-chan Event\nfunc BundleEventSources(srcs ...\u003c-chan Event) \u003c-chan Event\n\nfunc NewSSEBroadcaster(src \u003c-chan Event, opts ...BroadcasterOption) http.Handler\n```\n* `Marshaler` type is compatible with `json.Marshal` (which is used by default in case `marshaler` is left `nil`).\n* `eventName` can be an empty string.\n\n```go\nfunc ListenSSE(ctx context.Context, url string, opts ...SSEListenerOption) (\u003c-chan Event, error)\n\nfunc WithClient(client *http.Client) SSEListenerOption\nfunc WithMethod(method string) SSEListenerOption\nfunc WithBody(body io.Reader, contentType string) SSEListenerOption\nfunc WithHeader(key, value0 string, values ...string) SSEListenerOption\nfunc WithEventsBufferSize(bufSize int) SSEListenerOption\n```\n\n### On-demand broadcasters\n```go\ntype Source[T any] func() (\u003c-chan T, error)\nfunc NewOndemandBroadcaster[T any](src Source[T], opts ...BroadcasterOption) Broadcaster[T]\n\ntype OndemandEventSource func() (\u003c-chan Event, error)\nfunc NewOndemandSSEBroadcaster(src OndemandEventSource, opts ...BroadcasterOption) http.Handler\n```\n\n### Multi-source broadcasters\n```go\ntype MultiSource[K comparable, T any] func(K) (\u003c-chan T, CancelFunc, error)\n\ntype MultiEventSource[K comparable] interface {\n\tGetKey(*http.Request) (K, error)\n\tGetEventSource(K) (\u003c-chan Event, CancelFunc, error)\n}\n\ntype MultiBroadcaster[K comparable, T any] interface {\n\tListen(key K, opts ...ListenerOption) (\u003c-chan T, CancelFunc, error)\n}\n\nfunc NewMultiBroadcaster[K comparable, T any](src MultiSource[K, T], opts ...BroadcasterOption) MultiBroadcaster[K, T]\nfunc NewMultiSSEBroadcaster[K comparable](src MultiEventSource[K], opts ...BroadcasterOption) http.Handler\n```\n\n### Converter broadcasters\n```go\ntype Converter[In, Out any] func(In) (Out, bool)\n\nfunc NewConverterBroadcaster[In, Out any](input \u003c-chan In, conv Converter[In, Out], opts ...BroadcasterOption) Broadcaster[Out]\nfunc NewOndemandConverterBroadcaster[In, Out any](src Source[In], conv Converter[In, Out], opts ...BroadcasterOption) Broadcaster[Out]\nfunc NewMultiConverterBroadcaster[K comparable, In, Out any](src MultiSource[K, In], conv Converter[In, Out], opts ...BroadcasterOption) MultiBroadcaster[K, Out]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frazzie%2Fbroadcaster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frazzie%2Fbroadcaster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frazzie%2Fbroadcaster/lists"}