{"id":13443088,"url":"https://github.com/pma/amqp","last_synced_at":"2026-02-19T07:03:08.021Z","repository":{"id":19064130,"uuid":"22290867","full_name":"pma/amqp","owner":"pma","description":"Idiomatic Elixir client for RabbitMQ","archived":false,"fork":false,"pushed_at":"2025-09-30T20:03:11.000Z","size":440,"stargazers_count":691,"open_issues_count":1,"forks_count":128,"subscribers_count":11,"default_branch":"main","last_synced_at":"2026-02-16T08:44:27.013Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Elixir","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/pma.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2014-07-26T16:26:36.000Z","updated_at":"2026-01-21T12:55:52.000Z","dependencies_parsed_at":"2022-07-13T01:03:17.341Z","dependency_job_id":"556eec72-5aa9-4bfe-a9b6-f975e9294c32","html_url":"https://github.com/pma/amqp","commit_stats":{"total_commits":309,"total_committers":56,"mean_commits":5.517857142857143,"dds":0.4563106796116505,"last_synced_commit":"0b630ac81be91b223e6152495e64e9a96a327b62"},"previous_names":[],"tags_count":56,"template":false,"template_full_name":null,"purl":"pkg:github/pma/amqp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pma%2Famqp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pma%2Famqp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pma%2Famqp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pma%2Famqp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pma","download_url":"https://codeload.github.com/pma/amqp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pma%2Famqp/sbom","scorecard":{"id":738552,"data":{"date":"2025-08-11","repo":{"name":"github.com/pma/amqp","commit":"b5195c5949a34f14404ee28e9a6f936ffb067ab9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.2,"checks":[{"name":"Code-Review","score":1,"reason":"Found 4/30 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":9,"reason":"9 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 9","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/elixir.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/pma/amqp/elixir.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/elixir.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/pma/amqp/elixir.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/elixir.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/pma/amqp/elixir.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/elixir.yml:65: update your workflow using https://app.stepsecurity.io/secureworkflow/pma/amqp/elixir.yml/main?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/elixir.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-vq52-99r9-h5pw","Warn: Project is vulnerable to: GHSA-9fm9-hp7p-53mf"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T16:38:47.986Z","repository_id":19064130,"created_at":"2025-08-22T16:38:47.986Z","updated_at":"2025-08-22T16:38:47.986Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29605808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T06:47:36.664Z","status":"ssl_error","status_checked_at":"2026-02-19T06:45:47.551Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":[],"created_at":"2024-07-31T03:01:55.892Z","updated_at":"2026-02-19T07:03:07.991Z","avatar_url":"https://github.com/pma.png","language":"Elixir","funding_links":[],"categories":["Elixir","Queue"],"sub_categories":[],"readme":"# AMQP\n\n[![Build Status](https://github.com/pma/amqp/actions/workflows/elixir.yml/badge.svg?branch=main)](https://github.com/pma/amqp/actions/workflows/elixir.yml?query=branch%3Amain)\n[![Module Version](https://img.shields.io/hexpm/v/amqp.svg)](https://hex.pm/packages/amqp)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/amqp/)\n[![Total Download](https://img.shields.io/hexpm/dt/amqp.svg)](https://hex.pm/packages/amqp)\n[![Last Updated](https://img.shields.io/github/last-commit/pma/amqp.svg)](https://github.com/pma/amqp/commits/main)\n[![License](https://img.shields.io/hexpm/l/amqp.svg)](https://github.com/pma/amqp/blob/main/LICENSE)\n\nA simple Elixir wrapper for the Erlang RabbitMQ 3/4 client (AMQP 0.9.1).\n\nThe API is based on Langohr, a Clojure client for RabbitMQ.\n\n## Upgrading guides\n\nTo upgrade from the old version, please read our upgrade guides:\n\n* [0.x to 1.x](https://github.com/pma/amqp/wiki/Upgrade-from-0.X-to-1.0)\n* [1.x to 2.x](https://github.com/pma/amqp/wiki/2.0-Release-Notes#breaking-changes-and-upgrade-guide)\n* [2.x to 3.x](https://github.com/pma/amqp/wiki/3.0-Release-Notes#breaking-changes-and-upgrade-guide)\n* [3.X to 4.x](https://github.com/pma/amqp/wiki/4.0-Release-Notes)\n\n## Usage\n\nAdd AMQP as a dependency in your `mix.exs` file.\n\n```elixir\ndef deps do\n  [\n    {:amqp, \"~\u003e 4.1\"}\n  ]\nend\n```\n\nElixir will start `amqp` automatically if you use Elixir 1.6+.\n\nIf that's not the case (use `Application.started_applications/0` to check), try\nadding `:amqp` to `applications` or `extra_applications` in your `mix.exs`, or\ncall `Application.ensure_started(:amqp)` at the start.\n\nAfter you're done, run `mix deps.get` in your shell to fetch and compile AMQP.\nThen start an interactive Elixir shell with `iex -S mix`.\n\n```elixir\niex\u003e {:ok, conn} = AMQP.Connection.open()\n# {:ok, %AMQP.Connection{pid: #PID\u003c0.165.0\u003e}}\n\niex\u003e {:ok, chan} = AMQP.Channel.open(conn)\n# {:ok, %AMQP.Channel{conn: %AMQP.Connection{pid: #PID\u003c0.165.0\u003e}, pid: #PID\u003c0.177.0\u003e}\n\niex\u003e AMQP.Queue.declare(chan, \"test_queue\")\n# {:ok, %{consumer_count: 0, message_count: 0, queue: \"test_queue\"}}\n\niex\u003e AMQP.Exchange.declare(chan, \"test_exchange\")\n# :ok\n\niex\u003e AMQP.Queue.bind(chan, \"test_queue\", \"test_exchange\")\n# :ok\n\niex\u003e AMQP.Basic.publish(chan, \"test_exchange\", \"\", \"Hello, World!\")\n# :ok\n\niex\u003e {:ok, payload, meta} = AMQP.Basic.get(chan, \"test_queue\")\niex\u003e payload\n# \"Hello, World!\"\n\niex\u003e AMQP.Queue.subscribe(chan, \"test_queue\", fn payload, _meta -\u003e IO.puts(\"Received: #{payload}\") end)\n# {:ok, \"amq.ctag-5L8U-n0HU5doEsNTQpaXWg\"}\n\niex\u003e AMQP.Basic.publish(chan, \"test_exchange\", \"\", \"Hello, World!\")\n# :ok\n# Received: Hello, World!\n```\n\n### Set up a consumer GenServer\n\n```elixir\ndefmodule Consumer do\n  use GenServer\n  use AMQP\n\n  def start_link do\n    GenServer.start_link(__MODULE__, [], [])\n  end\n\n  @exchange    \"gen_server_test_exchange\"\n  @queue       \"gen_server_test_queue\"\n  @queue_error \"#{@queue}_error\"\n\n  def init(_opts) do\n    {:ok, conn} = Connection.open(\"amqp://guest:guest@localhost\")\n    {:ok, chan} = Channel.open(conn)\n    setup_queue(chan)\n\n    # Limit unacknowledged messages to 10\n    :ok = Basic.qos(chan, prefetch_count: 10)\n    # Register the GenServer process as a consumer\n    {:ok, _consumer_tag} = Basic.consume(chan, @queue)\n    {:ok, chan}\n  end\n\n  # Confirmation sent by the broker after registering this process as a consumer\n  def handle_info({:basic_consume_ok, %{consumer_tag: consumer_tag}}, chan) do\n    {:noreply, chan}\n  end\n\n  # Sent by the broker when the consumer is unexpectedly cancelled (such as after a queue deletion)\n  def handle_info({:basic_cancel, %{consumer_tag: consumer_tag}}, chan) do\n    {:stop, :normal, chan}\n  end\n\n  # Confirmation sent by the broker to the consumer process after a Basic.cancel\n  def handle_info({:basic_cancel_ok, %{consumer_tag: consumer_tag}}, chan) do\n    {:noreply, chan}\n  end\n\n  def handle_info({:basic_deliver, payload, %{delivery_tag: tag, redelivered: redelivered}}, chan) do\n    # You might want to run payload consumption in separate Tasks in production\n    consume(chan, tag, redelivered, payload)\n    {:noreply, chan}\n  end\n\n  defp setup_queue(chan) do\n    {:ok, _} = Queue.declare(chan, @queue_error, durable: true)\n    # Messages that cannot be delivered to any consumer in the main queue will be routed to the error queue\n    {:ok, _} = Queue.declare(chan, @queue,\n                             durable: true,\n                             arguments: [\n                               {\"x-dead-letter-exchange\", :longstr, \"\"},\n                               {\"x-dead-letter-routing-key\", :longstr, @queue_error}\n                             ]\n                            )\n    :ok = Exchange.fanout(chan, @exchange, durable: true)\n    :ok = Queue.bind(chan, @queue, @exchange)\n  end\n\n  defp consume(channel, tag, redelivered, payload) do\n    number = String.to_integer(payload)\n    if number \u003c= 10 do\n      :ok = Basic.ack channel, tag\n      IO.puts \"Consumed a #{number}.\"\n    else\n      :ok = Basic.reject channel, tag, requeue: false\n      IO.puts \"#{number} is too big and was rejected.\"\n    end\n\n  rescue\n    # Requeue unless it's a redelivered message.\n    # This means we will retry consuming a message once in case of exception\n    # before we give up and have it moved to the error queue\n    #\n    # You might also want to catch :exit signal in production code.\n    # Make sure you call ack, nack or reject otherwise consumer will stop\n    # receiving messages.\n    exception -\u003e\n      :ok = Basic.reject channel, tag, requeue: not redelivered\n      IO.puts \"Error converting #{payload} to integer\"\n  end\nend\n```\n\n```elixir\niex\u003e Consumer.start_link\n{:ok, #PID\u003c0.261.0\u003e}\niex\u003e {:ok, conn} = AMQP.Connection.open\n{:ok, %AMQP.Connection{pid: #PID\u003c0.165.0\u003e}}\niex\u003e {:ok, chan} = AMQP.Channel.open(conn)\n{:ok, %AMQP.Channel{conn: %AMQP.Connection{pid: #PID\u003c0.165.0\u003e}, pid: #PID\u003c0.177.0\u003e}\niex\u003e AMQP.Basic.publish chan, \"gen_server_test_exchange\", \"\", \"5\"\n:ok\nConsumed a 5.\niex\u003e AMQP.Basic.publish chan, \"gen_server_test_exchange\", \"\", \"42\"\n:ok\n42 is too big and was rejected.\niex\u003e AMQP.Basic.publish chan, \"gen_server_test_exchange\", \"\", \"Hello, World!\"\n:ok\nError converting Hello, World! to integer\nError converting Hello, World! to integer\n```\n\n### Configuration\n\n#### Connections and channels\n\nYou can define a connection and channel in your config and AMQP will\nautomatically:\n\n* Open the connection and channel at the start of the application\n* Automatically try to reconnect if they're disconnected\n\n```elixir\nconfig :amqp,\n  connections: [\n    myconn: [url: \"amqp://guest:guest@myhost:12345\"],\n  ],\n  channels: [\n    mychan: [connection: :myconn]\n  ]\n```\n\nYou can access the connection/channel via `AMQP.Application`.\n\n```elixir\niex\u003e {:ok, chan} = AMQP.Application.get_channel(:mychan)\niex\u003e :ok = AMQP.Basic.publish(chan, \"\", \"\", \"Hello\")\n```\n\nWhen a channel is down and reconnected, you have to ensure your consumer\nsubscribes to the channel again.\n\nSee the documentation for `AMQP.Application.get_connection/1` and\n`AMQP.Application.get_channel/1` for more details.\n\n### Types of arguments and headers\n\nThe parameter `arguments` in `Queue.declare`, `Exchange.declare`,\n`Basic.consume` and the parameter `headers` in `Basic.publish` are a list of\ntuples in the form `{name, type, value}`, where `name` is a binary containing\nthe argument/header name, `type` is an atom describing the AMQP field type, and\n`value` is a term compatible with the AMQP field type.\n\nThe valid AMQP field types are:\n\n`:longstr` | `:signedint` | `:decimal` | `:timestamp` | `:table` | `:byte` | `:double` | `:float` | `:long` | `:short` | `:bool` | `:binary` | `:void` | `:array`\n\nValid argument names in `Queue.declare` include:\n\n* \"x-expires\"\n* \"x-message-ttl\"\n* \"x-dead-letter-routing-key\"\n* \"x-dead-letter-exchange\"\n* \"x-max-length\"\n* \"x-max-length-bytes\"\n\nValid argument names in `Basic.consume` include:\n\n* \"x-priority\"\n* \"x-cancel-on-ha-failover\"\n\nValid argument names in `Exchange.declare` include:\n\n* \"alternate-exchange\"\n\n## Troubleshooting / FAQ\n\n#### Is amqp 4.x compatible with RabbitMQ 3.x?\n\nYes, it is.\n\nThis library uses [the official Erlang RabbitMQ client](https://hex.pm/packages/amqp_client) under the hood.\nAs long as the client works with the old RabbitMQ version, our library will also support the old version.\n\nHere is [the comment](https://github.com/rabbitmq/rabbitmq-server/issues/12510#issuecomment-2442175567) from the RabbitMQ team.\n\n#### Does the library support AMQP 1.0?\n\nNo, it doesn't. This library supports only AMQP 0.9.1, and we have no plans to support 1.0 at this time.\n\nRabbitMQ 4 now officially supports AMQP 1.0 along with 0.9.1. You might get some benefits from using this protocol.\n\n- https://www.rabbitmq.com/blog/2024/08/05/native-amqp\n- https://www.rabbitmq.com/blog/2024/08/21/amqp-benchmarks\n- https://www.rabbitmq.com/blog/2024/09/02/amqp-flow-control\n\nSince the AMQP 1.0 protocol design is significantly different from 0.9.1, we also think it's a good idea to start from scratch instead of building on top of this library. \n\n\n#### Consumer stops receiving messages\n\nIt usually happens when your code doesn't send an acknowledgement (ack, nack, or\nreject) after receiving a message.\n\nIf you use GenServer for your consumer, try storing the number of messages the server is currently processing in the GenServer state.\n\nIf the number equals `prefetch_count`, those messages were left without\nacknowledgements, which is why the consumer has stopped receiving more\nmessages.\n\nAlso, review the following points:\n\n- how exceptions are handled when they're raised\n- how `:exit` signals are handled when they're thrown\n- what could happen when message processing takes a long time\n\nAlso, make sure that the consumer monitors the channel pid. When the channel is\ngone, you have to reopen it and subscribe to the new channel again.\n\n#### The version compatibility\n\nCheck out [this article](https://github.com/pma/amqp/wiki/Versions-and-Compatibilities) to find out the compatibility with Elixir, OTP and RabbitMQ.\n\n#### Heartbeats\n\nIf the connection is dropped automatically, consider enabling heartbeats.\n\nYou can set the `heartbeat` option when you open a connection.\n\nFor more details, read [this article](http://www.rabbitmq.com/heartbeats.html#tcp-proxies)\n\n\n\n## Copyright and License\n\nCopyright (c) 2014 Paulo Almeida\n\nThis library is MIT licensed. See the\n[LICENSE](https://github.com/pma/amqp/blob/main/LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpma%2Famqp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpma%2Famqp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpma%2Famqp/lists"}