{"id":13413385,"url":"https://github.com/mustafaturan/bus","last_synced_at":"2025-05-16T12:10:35.666Z","repository":{"id":41183354,"uuid":"183738244","full_name":"mustafaturan/bus","owner":"mustafaturan","description":"🔊Minimalist message bus implementation for internal communication with zero-allocation magic on Emit","archived":false,"fork":false,"pushed_at":"2023-05-14T03:59:03.000Z","size":92,"stargazers_count":346,"open_issues_count":0,"forks_count":25,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-08T18:06:12.383Z","etag":null,"topics":["eventbus","go","go-library","go-package","message-broker","message-bus","pubsub","zero-alloc","zero-allocation"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/mustafaturan/bus/v3?tab=doc","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mustafaturan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-04-27T06:41:53.000Z","updated_at":"2025-05-06T02:33:59.000Z","dependencies_parsed_at":"2023-02-01T05:15:55.714Z","dependency_job_id":null,"html_url":"https://github.com/mustafaturan/bus","commit_stats":{"total_commits":44,"total_committers":3,"mean_commits":"14.666666666666666","dds":"0.045454545454545414","last_synced_commit":"ea436a8ebd8ca6d26ac9b1e61aa131870e190b23"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaturan%2Fbus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaturan%2Fbus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaturan%2Fbus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mustafaturan%2Fbus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mustafaturan","download_url":"https://codeload.github.com/mustafaturan/bus/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254084588,"owners_count":22011906,"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":["eventbus","go","go-library","go-package","message-broker","message-bus","pubsub","zero-alloc","zero-allocation"],"created_at":"2024-07-30T20:01:39.137Z","updated_at":"2025-05-16T12:10:35.646Z","avatar_url":"https://github.com/mustafaturan.png","language":"Go","funding_links":[],"categories":["消息","Messaging","Relational Databases","消息系统","机器学习"],"sub_categories":["检索及分析资料库","Search and Analytic Databases","SQL 查询语句构建库","Advanced Console UIs"],"readme":"# 🔊 Bus\n\n[![GoDoc](https://godoc.org/github.com/mustafaturan/bus?status.svg)](https://godoc.org/github.com/mustafaturan/bus)\n[![Build Status](https://travis-ci.org/mustafaturan/bus.svg?branch=main)](https://travis-ci.org/mustafaturan/bus)\n[![Coverage Status](https://coveralls.io/repos/github/mustafaturan/bus/badge.svg?branch=main)](https://coveralls.io/github/mustafaturan/bus?branch=main)\n[![Go Report Card](https://goreportcard.com/badge/github.com/mustafaturan/bus)](https://goreportcard.com/report/github.com/mustafaturan/bus)\n[![GitHub license](https://img.shields.io/github/license/mustafaturan/bus.svg)](https://github.com/mustafaturan/bus/blob/main/LICENSE)\n\nBus is a minimalist event/message bus implementation for internal communication.\nIt is heavily inspired from my [event_bus](https://github.com/otobus/event_bus)\npackage for Elixir language.\n\n## API\n\nThe method names and arities/args are stable now. No change should be expected\non the package for the version `3.x.x` except any bug fixes.\n\n## Installation\n\nVia go packages:\n```go get github.com/mustafaturan/bus/v3```\n\n## Usage\n\n### Configure\n\nThe package requires a unique id generator to assign ids to events. You can\nwrite your own function to generate unique ids or use a package that provides\nunique id generation functionality.\n\nThe `bus` package respect to software design choice of the packages/projects. It\nsupports both singleton and dependency injection to init a `bus` instance.\n\n*Hint:*\nCheck the [demo project](https://github.com/mustafaturan/bus-sample-project) for\nthe singleton configuration.\n\nHere is a sample initilization using `monoton` id generator:\n\n```go\nimport (\n    \"github.com/mustafaturan/bus/v3\"\n    \"github.com/mustafaturan/monoton/v2\"\n    \"github.com/mustafaturan/monoton/v2/sequencer\"\n)\n\nfunc NewBus() *bus.Bus {\n    // configure id generator (it doesn't have to be monoton)\n    node        := uint64(1)\n    initialTime := uint64(1577865600000) // set 2020-01-01 PST as initial time\n    m, err := monoton.New(sequencer.NewMillisecond(), node, initialTime)\n    if err != nil {\n        panic(err)\n    }\n\n    // init an id generator\n    var idGenerator bus.Next = m.Next\n\n    // create a new bus instance\n    b, err := bus.NewBus(idGenerator)\n    if err != nil {\n        panic(err)\n    }\n\n    // maybe register topics in here\n    b.RegisterTopics(\"order.received\", \"order.fulfilled\")\n\n    return b\n}\n```\n\n### Register Event Topics\n\nTo emit events to the topics, topic names need to be registered first:\n\n```go\n// register topics\nb.RegisterTopics(\"order.received\", \"order.fulfilled\")\n```\n\n### Register Event Handlers\n\nTo receive topic events you need to register handlers; A handler basically\nrequires two vals which are a `Handle` function and topic `Matcher` regex\npattern.\n\n```go\nhandler := bus.Handler{\n    Handle: func(ctx context.Context, e bus.Event) {\n        // do something\n        // NOTE: Highly recommended to process the event in an async way\n    },\n    Matcher: \".*\", // matches all topics\n}\nb.RegisterHandler(\"a unique key for the handler\", handler)\n```\n\n### Emit Events\n\n```go\n// if txID val is blank, bus package generates one using the id generator\nctx := context.Background()\nctx = context.WithValue(ctx, bus.CtxKeyTxID, \"some-transaction-id-if-exists\")\n// with optional source\nctx = context.WithValue(ctx, bus.CtxKeySource, \"source-of-the-event\")\n\n// event topic name (must be registered before)\ntopic := \"order.received\"\n\n// interface{} data for event\norder := make(map[string]string)\norder[\"orderID\"]     = \"123456\"\norder[\"orderAmount\"] = \"112.20\"\norder[\"currency\"]    = \"USD\"\n\n// emit the event\nerr := b.Emit(ctx, topic, order)\n\nif err != nil {\n    // report the err\n    fmt.Println(err)\n}\n\n// emit the event with options\nerr := b.EmitWithOpts(ctx, topic, order, bus.WithTxID(\"some-tx-id\"))\n\nif err != nil {\n    // report the err\n    fmt.Println(err)\n}\n```\n\n### Processing Events\n\nWhen an event is emitted, the topic handlers receive the event synchronously.\nIt is highly recommended to process events asynchronous. Package leave the\ndecision to the packages/projects to use concurrency abstractions depending on\nuse-cases. Each handlers receive the same event as ref of `bus.Event` struct:\n\n```go\n// Event data structure\ntype Event struct {\n    ID         string      // identifier\n    TxID       string      // transaction identifier\n    Topic      string      // topic name\n    Source     string      // source of the event\n    OccurredAt time.Time   // creation time in nanoseconds\n    Data       interface{} // actual event data\n}\n```\n\n### Sample Project\n\nA [demo project](https://github.com/mustafaturan/bus-sample-project) with three\nconsumers which increments a `counter` for each event topic, `printer` consumer\nwhich prints all events and lastly `calculator` consumer which sums amounts.\n\n### Benchmarks\n\nCommand:\n```\ngo test -benchtime 10000000x -benchmem -run=^$ -bench=. github.com/mustafaturan/bus/v3\n```\n\nResults:\n```\ngoos: darwin\ngoarch: amd64\npkg: github.com/mustafaturan/bus/v3\ncpu: Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz\nBenchmarkEmit-4                      \t10000000\t       180.5 ns/op\t       8 B/op\t       0 allocs/op\nBenchmarkEmitWithoutTxID-4           \t10000000\t       244.6 ns/op\t      72 B/op\t       2 allocs/op\nBenchmarkEmitWithOpts-4              \t10000000\t       280.8 ns/op\t     112 B/op\t       4 allocs/op\nBenchmarkEmitWithOptsUnspecified-4   \t10000000\t       169.4 ns/op\t       8 B/op\t       0 allocs/op\nPASS\nok  \tgithub.com/mustafaturan/bus/v3\t8.884s\n```\n\n## Contributing\n\nAll contributors should follow [Contributing Guidelines](CONTRIBUTING.md) before creating pull requests.\n\n## Credits\n\n[Mustafa Turan](https://github.com/mustafaturan)\n\n## License\n\nApache License 2.0\n\nCopyright (c) 2021 Mustafa Turan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmustafaturan%2Fbus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmustafaturan%2Fbus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmustafaturan%2Fbus/lists"}