{"id":16389316,"url":"https://github.com/marcelog/safe_bunny","last_synced_at":"2025-10-27T12:18:24.851Z","repository":{"id":11739604,"uuid":"14266729","full_name":"marcelog/safe_bunny","owner":"marcelog","description":"RabbitMQ delivery with local queuing","archived":false,"fork":false,"pushed_at":"2015-06-29T17:26:45.000Z","size":860,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-03T10:28:12.318Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Erlang","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/marcelog.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}},"created_at":"2013-11-09T22:53:25.000Z","updated_at":"2022-03-22T16:42:36.000Z","dependencies_parsed_at":"2022-07-10T16:47:26.526Z","dependency_job_id":null,"html_url":"https://github.com/marcelog/safe_bunny","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelog%2Fsafe_bunny","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelog%2Fsafe_bunny/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelog%2Fsafe_bunny/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcelog%2Fsafe_bunny/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcelog","download_url":"https://codeload.github.com/marcelog/safe_bunny/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240199179,"owners_count":19763820,"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":[],"created_at":"2024-10-11T04:32:21.397Z","updated_at":"2025-10-27T12:18:19.819Z","avatar_url":"https://github.com/marcelog.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# About\n\nRabbitMQ delivery with local queuing on failure. It's a bit of boiler plate code\nthat can be useful in lots of projects, and it's basically a small wrapper around\nthe publish function of the [rabbitmq erlang client](http://www.rabbitmq.com/erlang-client-user-guide.html).\n\nLet's say you have rabbitmq as your main event/commands bus for your project. Most\nof the time, rabbitmq will be there (available), but sometimes, you might experience\nconnectivity issues, or maybe the server is down, or something else went wrong, \nand you want to be as sure as possible that you will be able to send some important\nmessages, even if that means that they will *eventually* be sent, and not right away.\n\nsafe_bunny gives you a couple of queue alternatives to use when rabbitmq is\nnot available for whatever reason, while still allowing you to **fire-and-forget**\nmessages, and it will handle this automagically for you (or at least do its best\neffort).\n\nsafe_bunny includes the needed producers and consumers for the fallback queues.\n\n## Jenkins Job\nBe sure to checkout the [jenkins job page](http://ci.marcelog.name/job/safe_bunny/)\nto see metrics, tests, and documentation.\n\n## Example\n\n - safe_bunny is configured with queues mysql, redis, file, ets (in that order).\n - A publish fails with a **NO_ROUTE** error.\n - The first fallback queue is tried (in this case, mysql).\n - If the fallback queue fails or is not available, the next one is tried, until\n one succeeds or no more queues are available.\n - You get to choose which queues will be available and the order of preference.\n\n## Disclaimer\nNothing is safe. But this might give you a safer solution when using rabbitmq\nto send messages to your workers (meaning that will try to make the best possible\neffort to ensure an eventual delivery).\n\n# How it works\nUses [worker_pool](https://github.com/tigertext/worker_pool) to create a pool\nof connections to rabbitmq, all channels use [confirms](http://www.rabbitmq.com/confirms.html), so we are *pretty sure* that a given message could or could not be published.\n\nFor *safe* deliveries, the **mandatory** flag is set in the published messages, so\non failure these messages can be saved in one of the fallback queues for\nretrying the operation later.\n\n## Delivery \"modes\"\nFor delivering messages, you can choose between 3 different options.\n\n### Direct to MQ, no local queuing on failure.\nUse **safe_bunny:deliver_unsafe/3**. This will try to publish a message to the\ngiven exchange and routing key, and will not try to queue the message on failure.\n\n### Direct to MQ, local queueing on failure.\nUse **safe_bunny:deliver_safe/3**. Like the above, but will queue the message\nin the fallback queues on failure. Fallback queues are tryed in order, according\nto the **producers** option of the safe_bunny application.\n\n### Local queuing only. Consumers will try to send the messages to the MQ.\n\"Safest\" option (because you queue first). Use **safe_bunny:queue/3**. One of\nthe queue consumers should pick the new message and try to publish it via rabbitmq.\n\n## Available Queuing backends\n\n * mysql\n * redis\n * file\n * ets\n\n## Concurrency\n\n[Duomark's concurrency tools](https://github.com/duomark/dk_cxy) is used to\nimpose concurrency limits on the number of processes spawned for deliveries (either\nto local queues and rabbitmq). Each delivery will be handled by a separate process\nthat can be monitored until the limit is reached. Everything will be done 'inline'\n(i.e: the caller's process space) when exceeded.\n\n## Configuring it\n\nCheck out the [example configuration file](https://github.com/marcelog/safe_bunny/blob/master/priv/example.config).\n\n## Running it\n\n    application:start(safe_bunny).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcelog%2Fsafe_bunny","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcelog%2Fsafe_bunny","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcelog%2Fsafe_bunny/lists"}