PageSourceSearch

https://rabbitmq-website.pages.dev/assets/js/111463f7.5edc1f0b.js

js rabbitmq-website.pages.dev collected 2026-10-03 05:34:35 UTC 45,679 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkrabbitmq_website=self.webpackChunkrabbitmq_website||[]).push([["21355"],{41795(e,n,s){s.r(n),s.d(n,{metadata:()=>i,default:()=>h,frontMatter:()=>l,contentTitle:()=>o,toc:()=>a,assets:()=>d});var i=JSON.parse('{"id":"shovel-static","title":"Configuring Static Shovels","description":"\x3c!--","source":"@site/docs/shovel-static.md","sourceDirName":".","slug":"/shovel-static","permalink":"/docs/next/shovel-static","draft":false,"unlisted":false,"editUrl":"https://github.com/rabbitmq/rabbitmq-website/tree/main/docs/shovel-static.md","tags":[],"version":"current","frontMatter":{"title":"Configuring Static Shovels"},"sidebar":"docsSidebar","previous":{"title":"Dynamic Shovels","permalink":"/docs/next/shovel-dynamic"},"next":{"title":"STOMP Plugin","permalink":"/docs/next/stomp"}}'),r=s(74848),t=s(28453);let l={title:"Configuring Static Shovels"},o="Configuring Static Shovels",d={},a=[{value:"Overview",id:"overview",level:2},{value:"Configuration",id:"configuration",level:2},{value:"The Source and The Destination",id:"the-source-and-the-destination",level:3},{value:"General Source Keys",id:"general-source-keys",level:3},{value:"AMQP 0-9-1 Source Keys",id:"amqp-0-9-1-source-keys",level:3},{value:"Predeclared topology",id:"predeclared-topology",level:4},{value:"AMQP 1.0 Source Keys",id:"amqp-10-source-keys",level:3},{value:"Local Shovel Source Keys",id:"local-shovel-source-keys",level:3},{value:"Predeclared Topology",id:"predeclared-topology",level:4},{value:"Destination",id:"destination",level:2},{value:"General Destination Keys",id:"general-destination-keys",level:3},{value:"AMQP 0-9-1 Destination Keys",id:"amqp-0-9-1-destination-keys",level:3},{value:"AMQP 1.0 Destination Keys",id:"amqp-10-destination-keys",level:3},{value:"Local Shovel Destination Keys",id:"local-shovel-destination-keys",level:3},{value:"Example Configuration",id:"example-config",level:2},{value:"Example Configuration (1.0 Source - 0.9.1 Destination)",id:"example-config-amqp10-amqp091",level:2},{value:"Example Configuration (0.9.1 Source \u2014 1.0 Destination)",id:"example-config-amqp091-amqp10",level:2}];function c(e){let n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",p:"p",pre:"pre",strong:"strong",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"configuring-static-shovels",children:"Configuring Static Shovels"})}),"\n",(0,r.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,r.jsxs)(n.p,{children:["This guide focuses on statically configured shovels. It assumes\nfamiliarity with the key concepts behind the ",(0,r.jsx)(n.a,{href:"./shovel",children:"Shovel plugin"}),"."]}),"\n",(0,r.jsxs)(n.admonition,{type:"tip",children:[(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"./shovel-dynamic",children:"Dynamic shovels"})," is the modern shovel type. When in doubt,\nprefer dynamic shovels."]}),(0,r.jsxs)(n.p,{children:["To make sure that some shovels start after cluster formation, combine\ndynamic shovels with ",(0,r.jsx)(n.a,{href:"./definitions#import-on-boot",children:"definition import on boot"}),"."]})]}),"\n",(0,r.jsxs)(n.p,{children:["Unlike with ",(0,r.jsx)(n.a,{href:"./shovel-dynamic",children:"dynamic shovels"}),", static shovels are configured using the ",(0,r.jsx)(n.a,{href:"./configure",children:"advanced configuration file"}),".\nThey are started on node boot and are primarily useful for permanently\nrunning workloads. Any changes to static shovel configuration would require\na node restart, which makes them highly inflexible."]}),"\n",(0,r.jsxs)(n.p,{children:["Most users ",(0,r.jsx)(n.strong,{children:"should prefer dynamic shovels"})," to static ones for their flexibility\nand ease of automation. Generating a dynamic shovel definition (a JSON document) is usually\neasier compared to a static shovel definition (which uses Erlang terms)."]}),"\n",(0,r.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,r.jsxs)(n.p,{children:["The configuration for the Shovel plugin must be defined in the\n",(0,r.jsx)(n.a,{href:"./configure#advanced-config-file",children:"advanced configuration file"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["It consists of a single ",(0,r.jsx)(n.code,{children:"shovels"})," clause that lists the shovels that should\nbe started on node boot:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{rabbit, [\n  %% ...\n]},\n\n{rabbitmq_shovel, [\n  {shovels, [\n    {shovel_one, [\n      %% shovel_one properties ...\n    ]},\n    %% ...\n  ]}\n]}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["A (deliberately verbose) ",(0,r.jsx)(n.a,{href:"#example-config",children:"example configuration"})," can be found below."]}),"\n",(0,r.jsxs)(n.p,{children:["Each element of the ",(0,r.jsx)(n.code,{children:"shovels"}
1)," clause is a named static shovel.\nThe names in the list must be distinct."]}),"\n",(0,r.jsx)(n.p,{children:"A shovel definition looks like this at the top level:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{shovel_name, [\n  {source, [\n    %% protocol-specific source configuration goes here\n  ]},\n  {destination, [\n    %% protocol-specific destination configuration goes here\n  ]},\n  %% 'confirm' is the default acknowledgement mode\n  {ack_mode, confirm},\n  %% reconnect with a 5 second delay\n  {reconnect_delay, 5}\n]}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["where ",(0,r.jsx)("code",{children:(0,r.jsx)("em",{children:"shovel_name"})})," is the name of the\nshovel (an Erlang atom). The name should be enclosed in single quotes (",(0,r.jsx)(n.code,{children:"'"}),") if they do\nnot begin with a lower-case letter or if they contain\nother characters than alphanumeric characters, underscore\n(",(0,r.jsx)(n.code,{children:"_"}),"), or ",(0,r.jsx)(n.code,{children:"@"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"the-source-and-the-destination",children:"The Source and The Destination"}),"\n",(0,r.jsx)(n.p,{children:"A shovel transfers messages from a source to a destination."}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"source"})," and ",(0,r.jsx)(n.code,{children:"destination"})," keys are ",(0,r.jsx)(n.strong,{children:"mandatory"})," and contain nested protocol-specific keys. Currently AMQP 0.9.1 and AMQP 1.0 are two supported protocols.\nSource and destination do not have to use the same protocol.\nAll the other properties are optional."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"source"})," is a mandatory key and has different keys properties\nfor different protocols. Two properties are common across all\nprotocols: ",(0,r.jsx)(n.code,{children:"protocol"})," and ",(0,r.jsx)(n.code,{children:"uris"}),".\n",(0,r.jsx)(n.code,{children:"protocol"})," supports three values: ",(0,r.jsx)(n.code,{children:"amqp091"}),", ",(0,r.jsx)(n.code,{children:"amqp10"})," and ",(0,r.jsx)(n.code,{children:"local"}),",\nfor AMQP 0-9-1, AMQP 1.0 and local shovels respectively:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"%% for AMQP 0-9-1\n{protocol, amqp091}\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"uris"})," is a list of ",(0,r.jsx)("a",{href:"./uri-spec",children:"AMQP connection URIs"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{uris, [\n        "amqp://fred:[email protected]/my_vhost",\n        "amqp://john:[email protected]/my_vhost"\n       ]}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["The URI syntax is extended to include a query part to\npermit the configuration of additional connection parameters.\nSee the ",(0,r.jsx)(n.a,{href:"./uri-query-parameters",children:"query parameter reference"})," which\nare available to static shovels, such as TLS certificate and private key."]}),"\n",(0,r.jsx)(n.h3,{id:"general-source-keys",children:"General Source Keys"}),"\n",(0,r.jsx)(n.p,{children:"Some keys are supported by AMQP 0-9-1, AMQP 1.0 and local sources.\nThey are described in the table below."}),"\n",(0,r.jsxs)("table",{children:[(0,r.jsx)("caption",{children:"Common (Protocol-Independent) Static Shovel Keys (Properties)"}),(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Key"})}),(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Description"})})]})}),(0,r.jsxs)("tbody",{children:[(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"reconnect-delay"}),(0,r.jsxs)("td",{children:[(0,r.jsx)(n.p,{children:"The duration (in seconds) to wait before reconnecting to the\nbrokers after being disconnected at either end. Default is 1."}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{reconnect_delay, 5}\n"})}),(0,r.jsxs)(n.p,{children:["would delay for five seconds before reconnecting after failure. Value of ",(0,r.jsx)(n.code,{children:"0"}),"\nmeans no reconnection: the shovel will stop after first failure or unsuccessful\nconnection attempt."]})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"ack-mode"}),(0,r.jsxs)("td",{children:[(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["Determines how the shovel should ",(0,r.jsx)("a",{href:"./confirms",children:"acknowledge"})," consumed messages.\nValid values are ",(0,r.jsx)("code",{children:"on-confirm"}),", ",(0,r.jsx)("code",{children:"on-publish"}),", and ",(0,r.jsx)("code",{children:"no-ack"}),".\n",(0,r.jsx)("code",{children:"on-confirm"})," is used by default."]})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["If set to ",(0,r.jsx)("code",{children:"on-confirm"})," (the default), messages are\n",(0,r.jsx)("a",{href:"./confirms",children:"acknowledged"})," to the source broker after they have been confirmed\nby the destination. This handles network errors and broker\nfailures without losing messages, and is the slowest option."]})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["If set to ",(0,r.jsx)("code",{children:"on-publish"}),", messages are ",(0,r.jsx)("a",{href:"./confirms",children:"acknowledged"})," to\nthe source broker after they have been published at the\ndestination (but not yet confirmed). Messages may be lost in the event of network or broker failures."]})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["If set to ",(0,r.jsx)("code",{children:"no-ack"}),", ",(0,r.jsx)("a",{href:"./confirms",children:"automatic message acknowledgements"})," will be used.\nThis option will offer the highest throughput but is not safe (will lose messages in the event of network or broker failures)."]})})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"delete-after-duration"}),(0,r.jsxs)("td",{children:[(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"A time-to-live for the shovel, in seconds. When time is up, the shovel stops,\nregardless of how many messages it has transferred by that point. AMQP 0-9-1,\nAMQP 1.0 and local shovels all support this setting. The countdown starts when the shovel\nconnects to its source, and restarts if the shovel reconnects."})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{delete_after_duration, 3600}\n"})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["Values below a configurable minimum (60 seconds by default) are\nautomatically increased to it. The minimum is controlled by the\n",(0,r.jsx)("code",{children:"shovel.delete_after_duration_floor"})," key in\n",(0,r.jsx)("code",{children:"rabbitmq.conf"})," and cannot be set below 15 seconds. See\n",(0,r.jsx)("a",{href:"./shovel-dynamic#time-based-deletion",children:"Time-Based Deletion"}),"."]})})]})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"amqp-0-9-1-source-keys",children:"AMQP 0-9-1 Source Keys"}),"\n",(0,r.jsx)(n.p,{children:"AMQP 0-9-1-specific source keys are covered in a separate table:"}),"\n",(0,r.jsxs)("table",{children:[(0,r.jsx)("caption",{children:"AMQP 0-9-1 Source Keys (Properties)"}),(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Key"})}),(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Description"})})]})}),(0,r.jsxs)("tbody",{children:[(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"declarations"}),(0,r.jsxs)("td",{children:[(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"An optional list of AMQP 0-9-1 operations to be executed by the Shovel\nbefore it starts transferring messages. They are typically used to set\nup the topology."})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"  {declarations, [\n    %% declaration list\n  ]}\n"})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["The declarations follow method and property names used by the ",(0,r.jsx)("a",{href:"/client-libraries/erlang-client-user-guide",children:"RabbitMQ Erlang Client"}),"."]})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"A minimalistic declaration example:"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"  {declarations, [\n                   'queue.declare',\n                   {'queue.bind', [\n                                    {exchange, <<\"my_exchange\">>},\n                                    {queue,    <<>>}\n                                  ]}\n                 ]}\n"})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["will first declare an anonymous queue, and then bind it\nto the exchange c
1alled ",(0,r.jsx)("code",{children:'"my_exchange"'}),". The\nqueue name of ",(0,r.jsx)("code",{children:"<<>>"})," on method ",(0,r.jsx)("code",{children:"queue.bind"}),'\nmeans "use the queue last declared on this channel".']})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["Each element of the declaration list is either an AMQP 0-9-1 method\ngiven as single quoted atom such as ",(0,r.jsx)("code",{children:"'queue.declare'"}),",\nor a tuple with first element the method atom, and second element\na property list of parameters."]})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["If just the method name is used all the\nparameters take their defaults (as illustrated with\n",(0,r.jsx)("code",{children:"'queue.declare'"})," above)."]})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"If a tuple and property-list is supplied, then the\nproperties in the list specify some or all of the\nparameters explicitly."})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"Here is another example:"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{\'exchange.declare\', [\n                      {exchange, <<"my_exchange">>},\n                      {type, <<"direct">>},\n                      durable\n                     ]}\n'})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:['will declare a durable, direct exchange called\n"',(0,r.jsx)("code",{children:"my_exchange"}),'".']})})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"queue"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)("div",{children:[(0,r.jsx)(n.p,{children:"The name of the source queue as an Erlang binary value. This property is mandatory:"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{queue, <<"queue.1">>}\n'})})]}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:[(0,r.jsx)("code",{children:"queue.1"})," is the name of the queue\nto shovel messages from, as a binary string."]})}),(0,r.jsxs)("div",{children:[(0,r.jsxs)(n.p,{children:["This queue must exist. Use the resource ",(0,r.jsx)("code",{children:"declarations"}),"\ncovered above to declare the queue or ensure it exists. If\nthe value is ",(0,r.jsx)("code",{children:"<<>>"})," (the empty binary string) then the\n",(0,r.jsx)("em",{children:"most recently declared queue"})," in ",(0,r.jsx)("code",{children:"declarations"})," is used.\nThis allows anonymous queues to be declared and used."]}),(0,r.jsxs)(n.p,{children:["See also ",(0,r.jsx)(n.a,{href:"#predeclared-topology",children:"Predeclared Topology section"})," below."]})]})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"prefetch-count"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)(n.p,{children:["The maximum number of unacknowledged messages copied over a shovel at\nany one time. Default is ",(0,r.jsx)("code",{children:"1000"}),":"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{prefetch_count, 1000}\n"})})]})]})]})]}),"\n",(0,r.jsx)(n.h4,{id:"predeclared-topology",children:"Predeclared topology"}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"declarations"})," attribute is typically used to set up the topology. At the very least, it must set up the source queue."]}),"\n",(0,r.jsxs)(n.p,{children:["There are deployment scenarios where the topology is automatically ",(0,r.jsx)(n.a,{href:"./definitions#import-on-boot",children:"imported from a definitions file at boot time"}),". In these scenarios, we can configure the plugin to wait until the queue is available by adding the following line to the ",(0,r.jsx)(n.code,{children:"rabbitmq.conf"})," file:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ini",children:"shovel.topology.predeclared = true\n"})}),"\n",(0,r.jsxs)(n.p,{children:["With the above configuration, if a static shovel has no ",(0,r.jsx)(n.code,{children:"declarations"})," attribute or it is empty, the piugin will wait until the source's ",(0,r.jsx)(n.code,{children:"queue"})," is eventually declared."]}),"\n",(0,r.jsx)(n.h3,{id:"amqp-10-source-keys",children:"AMQP 1.0 Source Keys"}),"\n",(0,r.jsx)(n.p,{children:"AMQP 1.0 source settings are different from those of AMQP 0-9-1 sources."}),"\n",(0,r.jsxs)("table",{children:[(0,r.jsx)("caption",{children:"AMQP 1.0 Source Keys (Properties)"}),(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Key"})}),(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Description"})})]})}),(0,r.jsxs)("tbody",{children:[(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"source_address"}),(0,r.jsxs)("td",{children:[(0,r.jsx)(n.p,{children:"This represents the source address of the AMQP 1.0 link.\nThis key is mandatory:"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{source_address, <<"my-address">>}\n'})})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"prefetch-count"}),(0,r.jsxs)("td",{children:[(0,r.jsx)(n.p,{children:"This optional key sets the link credit amount that will\nbe granted to the receiving link. The credit will be automatically\nrenewed when it falls below a 10th of this value. The default is 1000.\nIt takes the form"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"  {prefetch_count, 10}\n"})})]})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"local-shovel-source-keys",children:"Local Shovel Source Keys"}),"\n",(0,r.jsx)(n.p,{children:"Local shovel's specific source keys are covered in a separate table:"}),"\n",(0,r.jsxs)("table",{children:[(0,r.jsx)("caption",{children:"Local Shovel Source Keys (Properties)"}),(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Key"})}),(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Description"})})]})}),(0,r.jsxs)("tbody",{children:[(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"declarations"}),(0,r.jsxs)("td",{children:[(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"An optional list of AMQP 0-9-1 operations to be executed by the Shovel\nbefore it starts transferring messages. They are typically used to set\nup the topology."})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"  {declarations, [\n    %% declaration list\n  ]}\n"})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["The declarations follow method and property names used by the ",(0,r.jsx)("a",{href:"/client-libraries/erlang-client-user-guide",children:"RabbitMQ Erlang Client"}),"."]})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"A minimalistic declaration example:"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"  {declarations, [\n                   'queue.declare',\n                   {'queue.bind', [\n                                    {exchange, <<\"my_exchange\">>},\n                                    {queue,    <<>>}\n                                  ]}\n                 ]}\n"})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["will first declare an anonymous queue, and then bind it\nto the exchange c
1alled ",(0,r.jsx)("code",{children:'"my_exchange"'}),". The\nqueue name of ",(0,r.jsx)("code",{children:"<<>>"})," on method ",(0,r.jsx)("code",{children:"queue.bind"}),'\nmeans "use the queue last declared on this channel".']})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["Each element of the declaration list is either an AMQP 0-9-1 method\ngiven as single quoted atom such as ",(0,r.jsx)("code",{children:"'queue.declare'"}),",\nor a tuple with first element the method atom, and second element\na property list of parameters."]})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["If just the method name is used all the\nparameters take their defaults (as illustrated with\n",(0,r.jsx)("code",{children:"'queue.declare'"})," above)."]})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"If a tuple and property-list is supplied, then the\nproperties in the list specify some or all of the\nparameters explicitly."})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"Here is another example:"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{\'exchange.declare\', [\n                      {exchange, <<"my_exchange">>},\n                      {type, <<"direct">>},\n                      durable\n                     ]}\n'})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:['will declare a durable, direct exchange called\n"',(0,r.jsx)("code",{children:"my_exchange"}),'".']})})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"queue"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)("div",{children:[(0,r.jsx)(n.p,{children:"The name of the source queue as an Erlang binary value. This property is mandatory:"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{queue, <<"queue.1">>}\n'})})]}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:[(0,r.jsx)("code",{children:"queue.1"})," is the name of the queue\nto shovel messages from, as a binary string."]})}),(0,r.jsxs)("div",{children:[(0,r.jsxs)(n.p,{children:["This queue must exist. Use the resource ",(0,r.jsx)("code",{children:"declarations"}),"\ncovered above to declare the queue or ensure it exists. If\nthe value is ",(0,r.jsx)("code",{children:"<<>>"})," (the empty binary string) then the\n",(0,r.jsx)("em",{children:"most recently declared queue"})," in ",(0,r.jsx)("code",{children:"declarations"})," is used.\nThis allows anonymous queues to be declared and used."]}),(0,r.jsxs)(n.p,{children:["See also ",(0,r.jsx)(n.a,{href:"#predeclared-topology",children:"Predeclared topology section"})," below."]})]})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"prefetch-count"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)(n.p,{children:["The maximum number of unacknowledged messages copied over a shovel at\nany one time. Default is ",(0,r.jsx)("code",{children:"1000"}),":"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{prefetch_count, 1000}\n"})})]})]})]})]}),"\n",(0,r.jsx)(n.h4,{id:"predeclared-topology",children:"Predeclared Topology"}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"declarations"})," attribute is typically used to set up the topology. At the very least, it must set up the source queue."]}),"\n",(0,r.jsxs)(n.p,{children:["There are deployment scenarios where the topology is automatically ",(0,r.jsx)(n.a,{href:"./definitions#import-on-boot",children:"imported from a definitions file at boot time"}),". In these scenarios, we can configure the plugin to wait until the queue is available by adding the following line to the ",(0,r.jsx)(n.code,{children:"rabbitmq.conf"})," file:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ini",children:"shovel.topology.predeclared = true\n"})}),"\n",(0,r.jsxs)(n.p,{children:["With the above configuration, if a static shovel has no ",(0,r.jsx)(n.code,{children:"declarations"})," attribute or it is empty, the piugin will wait until the source's ",(0,r.jsx)(n.code,{children:"queue"})," is eventually declared."]}),"\n",(0,r.jsx)(n.h2,{id:"destination",children:"Destination"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"destination"}
1)," is a mandatory key and has different keys properties\nfor different protocols. Two properties are common across all\nprotocols: ",(0,r.jsx)(n.code,{children:"protocol"})," and ",(0,r.jsx)(n.code,{children:"uris"}),".\n",(0,r.jsx)(n.code,{children:"protocol"})," supports three values: ",(0,r.jsx)(n.code,{children:"amqp091"}),", ",(0,r.jsx)(n.code,{children:"amqp10"})," and ",(0,r.jsx)(n.code,{children:"local"}),"\nfor AMQP 0-9-1, AMQP 1.0 and local shovels, respectively:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"%% for AMQP 0-9-1\n{protocol, amqp091}\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"uris"})," is a list of ",(0,r.jsx)("a",{href:"./uri-spec",children:"AMQP connection URIs"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{uris, [\n        "amqp://fred:[email protected]/my_vhost",\n        "amqp://john:[email protected]/my_vhost"\n       ]}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["The URI syntax is extended to include a query part to\npermit the configuration of additional connection parameters.\nSee the ",(0,r.jsx)(n.a,{href:"./uri-query-parameters",children:"query parameter reference"})," which\nare available to static shovels, such as TLS certificate and private key."]}),"\n",(0,r.jsx)(n.h3,{id:"general-destination-keys",children:"General Destination Keys"}),"\n",(0,r.jsxs)("table",{children:[(0,r.jsx)("caption",{children:"General Destination Keys (Properties)"}),(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Key"})}),(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Description"})})]})}),(0,r.jsx)("tbody",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"reconnect-delay"}),(0,r.jsxs)("td",{children:[(0,r.jsx)(n.p,{children:"The duration (in seconds) to wait before reconnecting to the\nbrokers after being disconnected at either end. Default is 1."}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{reconnect_delay, 5}\n"})}),(0,r.jsxs)(n.p,{children:["would delay for five seconds before reconnecting after failure. Value of ",(0,r.jsx)(n.code,{children:"0"}),"\nmeans no reconnection: the shovel will stop after first failure or unsuccessful\nconnection attempt."]})]})]})})]}),"\n",(0,r.jsx)(n.h3,{id:"amqp-0-9-1-destination-keys",children:"AMQP 0-9-1 Destination Keys"}),"\n",(0,r.jsxs)("table",{children:[(0,r.jsx)("caption",{children:"AMQP 0-9-1 Destination Keys (Properties)"}),(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Key"})}),(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Description"})})]})}),(0,r.jsxs)("tbody",{children:[(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"publish_properties"}),(0,r.jsxs)("td",{children:[(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["This optional key controls ",(0,r.jsx)("a",{href:"./publishers#message-properties",children:"message properties"}),"\nset or overridden by the shovel. It takes the following form"]})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{publish_properties, [\n  {delivery_mode, 2}\n]}\n"})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"where the properties in the list are set on the\nbasic properties of each message before it is re-published."})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"This specific example would mark all re-published messages as persistent:"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{publish_properties, [\n  {delivery_mode, 2}\n]}\n"})}),(0,r.jsxs)("div",{children:[(0,r.jsx)(n.p,{children:"By default the original properties of the message are preserved, but\nthis clause can be used to change or set any known property:"}),(0,r.jsxs)("ul",{children:[(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"content_type"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"content_encoding"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"headers"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"delivery_mode"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"priority"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"correlation_id"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"reply_to"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"expiration"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"message_id"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"timestamp"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"type"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"user_id"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"app_id"})}),(0,r.jsx)("li",{children:(0,r.jsx)("code",{children:"cluster_id"})})]})]})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"publish_fields"}),(0,r.jsxs)("td",{children:[(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["This optional key is similar to ",(0,r.jsx)("code",{children:"publish_properties"})," but controls the publishing settings\ninstead of message properties that are accessible to consumers. It takes the form of"]})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{publish_fields, [\n                    {exchange, <<"my_exchange">>},\n                    {routing_key, <<"from_shovel">>}\n                  ]}\n'})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["where the properties in the list are used to set the\n",(0,r.jsx)("em",{children:"fields"})," on the ",(0,r.jsx)("code",{children:"basic.publish"})," method\nused to re-publish messages."]})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"By default the messages are re-published using the original\nexchange name and routing key. By specifying"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{publish_fields, [\n                    {exchange, <<"my_exchange">>},\n                    {routing_key, <<"from_shovel">>}\n                  ]}\n'})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"messages would be re-published to an explicit exchange name\nwith an explicit, fixed routing key."})})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"add_timestamp_header"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)(n.p,{children:["This boolean key controls whether a custom header, ",(0,r.jsx)("code",{children:"x-shovelled-timestamp"}),",\nwill be added to the message before it is re-published:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{add_timestamp_header, true}\n"})}),(0,r.jsx)(n.p,{children:"This header value is timestamp (in seconds since epoch) when message had been shovelled.\nBy default the header is not added."})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"add_forward_headers"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)(n.p,{children:["When set to true the shovel will add a number of custom message headers: ",(0,r.jsx)("code",{children:"shovelled-by"}),", ",(0,r.jsx)("code",{children:"shovel-type"}),", ",(0,r.jsx)("code",{children:"shovel-name"}),",\nto provide some additional metadata about the transfer."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{add_forward_headers, true}\n"})})]})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"amqp-10-destination-keys",children:"AMQP 1.0 Destination Keys"}),"\n",(0,r.jsxs)("table",{children:[(0,r.jsx)("caption",{children:"AMQP 1.0 Destination Keys (Properties)"}),(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Key"})}),(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Description"})})]})}),(0,r.jsxs)("tbody",{children:[(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"target_address"}),(0,r.jsx)("td",{children:(0,r.jsxs)("div",{children:[(0,r.jsx)(n.p,{children:"This represents the target address of the sending AMQP 1.0 link:"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{target_address, <<"some-address">>}\n'})})]})})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"properties"}),(0,r.jsxs)("td",{children:[(0,r.jsx)(n.p,{children:"This optional key controls what additional properties will be added when re-publishing\nmessages. It takes the form of"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{properties, [\n  {content_typle, <<"application/json">>}\n]}\n'})}),(0,r.jsx)("div",{children:(0,r.jsxs)(n.p,{children:["The available keys include\n",(0,r.jsx)("code",{children:"message_id"}),", ",(0,r.jsx)("code",{children:"user_id"}),", ",(0,r.jsx)("code",{children:"to"}),", ",(0,r.jsx)("code",{children:"subject"}),", ",(0,r.jsx)("code",{children:"reply_to"}),", ",(0,r.jsx)("code",{children:"correlation_id"}),", ",(0,r.jsx)("code",{children:"content_type"}),", ",(0,r.jsx)("code",{children:"content_encoding"}),", ",(0,r.jsx)("code",{children:"absolute_expiry_time"}),", ",(0,r.jsx)("code",{children:"creation_time"}),".\nSee the AMQP 1.0 spec (\xa73.2.4) for the all the available keys and values."]})})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"application_properties"}),(0,r.jsxs)("td",{children:[(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"This optional key declares any additional application properties\nto be added when re-publishing a message. It takes the form of"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{application_properties, [\n  {<<"application-key-1">>, <<"value-1">>},\n  {<<"application-key-2">>, <<"value-2">>}\n]}\n'})}),(0,r.jsx)("div",{children:(0,r.jsx)(n.p,{children:"Keys and values should be binary strings as in the example below."})})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"add_timestamp_header"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)(n.p,{children:["This boolean key controls whether a ",(0,r.jsx)("code",{children:"creation_time"})," property\nwill be set on the message before it is re-published:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{add_timestamp_header, true}\n"})}),(0,r.jsx)(n.p,{children:"This value is timestamp (in seconds since epoch) when message had been shovelled.\nBy default the property is not set."})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"add_forward_headers"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)(n.p,{children:["When set to true the shovel will add application properties for the\nfollowing keys: ",(0,r.jsx)("code",{children:"shovelled-by"}),", ",(0,r.jsx)("code",{children:"shovel-type"}),", ",(0,r.jsx)("code",{children:"shovel-name"}),"\nto provide some additional metadata about the transfer."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{add_forward_headers, true}\n"})})]})]})]})]}),"\n",(0,r.jsx)(n.h3,{id:"local-shovel-destination-keys",children:"Local Shovel Destination Keys"}),"\n",(0,r.jsxs)("table",{children:[(0,r.jsx)("caption",{children:"Local Shovel Destination Keys (Properties)"}),(0,r.jsx)("thead",{children:(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Key"})}),(0,r.jsx)("td",{children:(0,r.jsx)("strong",{children:"Description"})})]})}),(0,r.jsxs)("tbody",{children:[(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"add_timestamp_header"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)(n.p,{children:["This boolean key controls whether a custom header, ",(0,r.jsx)("code",{children:"x-opt-shovelled-timestamp"}),",\nwill be added to the message before it is re-published:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{add_timestamp_header, true}\n"})}),(0,r.jsx)(n.p,{children:"This header value is timestamp (in seconds since epoch) when message had been shovelled.\nBy default the header is not added."})]})]}),(0,r.jsxs)("tr",{children:[(0,r.jsx)("td",{children:"add_forward_headers"}),(0,r.jsxs)("td",{children:[(0,r.jsxs)(n.p,{children:["When set to true the shovel will add a number of custom message headers: ",(0,r.jsx)("code",{children:"x-opt-shovelled-by"}),", ",(0,r.jsx)("code",{children:"x-opt-shovel-type"}),", ",(0,r.jsx)("code",{children:"x-opt-shovel-name"}),",\nto provide some additional metadata about the transfer."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"{add_forward_headers, true}\n"})})]})]})]})]}),"\n",(0,r.jsx)(n.h2,{id:"example-config",children:"Example Configuration"}),"\n",(0,r.jsx)(n.p,{children:"A reasonably complete static shovel configuration between AMQP 0.9.1 endpoints\nmight look like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{rabbitmq_shovel,\n  [ {shovels, [ {my_first_shovel,\n                  [ {source,\n                      [ {protocol, amqp091},\n                        {uris, [ "amqp://fred:[email protected]/my_vhost",\n                                  "amqp://john:[email protected]/my_vhost" ]},\n                        {declarations, [ {\'exchange.declare\',\n                                            [ {exchange, <<"my_fanout">>},\n                                              {type, <<"fanout">>},\n                                              durable\n                                            ]},\n                                          {\'queue.declare\',\n                                            [{arguments,\n                                                [{<<"x-message-ttl">>, long, 60000}]}]},\n                                          {\'queue.bind\',\n                                            [ {exchange, <<"my_fanout">>},\n                                              {queue,    <<>>}\n                                            ]}\n                                          ]},\n                        {queue, <<>>},\n                        {prefetch_count, 10}\n                      ]},\n                    {destination,\n                      [ {protocol, amqp091},\n                        {uris, ["amqp://"]},\n                        {declarations, [ {\'exchange.declare\',\n                                            [ {exchange, <<"my_direct">>},\n                                              {type, <<"direct">>},\n                                              durable\n                                            ]}\n                                        ]},\n                        {publish_properties, [ {delivery_mode, 2} ]}
1,\n                        {add_forward_headers, true},\n                        {publish_fields, [ {exchange, <<"my_direct">>},\n                                          {routing_key, <<"from_shovel">>}\n                                          ]}\n                          ]},\n                    {ack_mode, on_confirm},\n                    {reconnect_delay, 5}\n                  ]}\n              ]}\n  ]}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["The configuration above defines a single shovel called\n",(0,r.jsx)(n.code,{children:"'my_first_shovel'"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"'my_first_shovel'"})," will connect to a broker on\neither ",(0,r.jsx)(n.code,{children:"host1"})," or ",(0,r.jsx)(n.code,{children:"host2"})," (as source), and\ndirectly to the local broker as destination. It will reconnect\nto the other source broker on failure, after a delay of 5\nseconds."]}),"\n",(0,r.jsxs)(n.p,{children:["When connected to the source it will declare a direct, fanout exchange\ncalled ",(0,r.jsx)(n.code,{children:'"my_fanout"'}),", an anonymous queue with a ",(0,r.jsx)(n.a,{href:"./ttl#per-queue-message-ttl",children:"per-queue message ttl"}),",\nand bind the queue to the exchange."]}),"\n",(0,r.jsxs)(n.p,{children:["When connected to the destination (the local broker) it will declare a\ndurable, direct exchange called ",(0,r.jsx)(n.code,{children:'"my_direct"'}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["This shovel will re-publish messages sent to the anonymous queue on the\nsource to the local exchange with the fixed routing key\n",(0,r.jsx)(n.code,{children:'"from_shovel"'}),". The messages will be persistent and only\nacknowledged after receiving a publish confirm from the local broker."]}),"\n",(0,r.jsx)(n.p,{children:"The shovel consumer will not get more deliveries if there are at least ten\nunacknowledged messages at any moment in time."}),"\n",(0,r.jsx)(n.h2,{id:"example-config-amqp10-amqp091",children:"Example Configuration (1.0 Source - 0.9.1 Destination)"}),"\n",(0,r.jsx)(n.p,{children:"A reasonably complete shovel configuration between an AMQP 1.0 source and an\nAMQP 0.9.1 destination might look like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{rabbitmq_shovel,\n [ {shovels, [ {my_first_shovel,\n                [ {source,\n                   [ {protocol, amqp10},\n                     {uris, [ "amqp://fred:[email protected]/my_vhost",\n                            ]},\n                     {source_address, <<"my-source">>},\n                     {prefetch_count, 10}\n                   ]},\n                  {destination,\n                     [ {protocol, amqp091},\n                       {uris, ["amqp://"]},\n                       {declarations, [ {\'exchange.declare\',\n                                         [ {exchange, <<"my_direct">>},\n                                           {type, <<"direct">>},\n                                           durable\n                                         ]}\n                                      ]},\n                       {publish_properties, [ {delivery_mode, 2} ]},\n                       {add_forward_headers, true},\n                       {publish_fields, [ {exchange, <<"my_direct">>},\n                                          {routing_key, <<"from_shovel">>}\n                                        ]}\n                     ]},\n                  {ack_mode, on_confirm},\n                  {reconnect_delay, 5}\n                ]}\n             ]}\n ]}\n'})}),"\n",(0,r.jsx)(n.h2,{id:"example-config-amqp091-amqp10",children:"Example Configuration (0.9.1 Source \u2014 1.0 Destination)"}),"\n",(0,r.jsx)(n.p,{children:"A more extensive shovel configuration between an AMQP 0.9.1 Source and an\nAMQP 1.0 destination might look like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:'{rabbitmq_shovel,\n [{shovels, [{my_first_shovel,\n              {source,\n               [{protocol, amqp091},\n                {uris, ["amqp://fred:[email protected]/my_vhost",\n                        "amqp://john:[email protected]/my_vhost"]},\n                {declarations, [{\'exchange.declare\',\n                                   [{exch
1ange, <<"my_fanout">>},\n                                    {type, <<"fanout">>},\n                                    durable]},\n                                {\'queue.declare\',\n                                   [{arguments,\n                                      [{<<"x-message-ttl">>, long, 60000}]}]},\n                                {\'queue.bind\',\n                                   [{exchange, <<"my_fanout">>},\n                                    {queue,    <<>>}\n                                    ]}\n                               ]},\n                {queue, <<>>},\n                {prefetch_count, 10}\n               ]},\n              {destination,\n               [{protocol, amqp10},\n                %% Note: for plain text SASL authentication, use\n                % {uris, ["amqp://user:pass@host:5672?sasl=plain"]},\n                %% Note: this relies on default user credentials\n                %%       which has remote access restrictions, see\n                %%       ./access-control to learn more\n                {uris, ["amqp://host:5672"]},\n                {properties, [{user_id, <<"my-user">>}]},\n                {application_properties, [{<<"my-prop">>, <<"my-prop-value">>}]},\n                {add_forward_headers, true},\n                {target_address, <<"destination-queue">>}\n               ]},\n              {ack_mode, on_confirm},\n              {reconnect_delay, 5}\n             }]}\n ]}\n}\n'})})]})}function h(e={}){let{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},28453(e,n,s){s.d(n,{R:()=>l,x:()=>o});var i=s(96540);let r={},t=i.createContext(r);function l(e){let n=i.useContext(t);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.