We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Don't publish messages to exporter exchange if exporter service is not enabled and running
While working on #3648 and I noticed `st2.exporter.work` queue grows indefinitely.

The reason for that is that exporter service is optional and doesn't run by default.

We should modify the code to only publish messages to that exchange if exporter service is enabled and running (otherwise this queue will keep growing indefinitely and this could eventually cause issues).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `st2common/st2common/transport/bootstrap_utils.py`
Content:
```
1 # Licensed to the StackStorm, Inc ('StackStorm') under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import socket
17 
18 import retrying
19 from oslo_config import cfg
20 from kombu import Connection
21 
22 from st2common import log as logging
23 from st2common.transport import utils as transport_utils
24 from st2common.transport.actionexecutionstate import ACTIONEXECUTIONSTATE_XCHG
25 from st2common.transport.announcement import ANNOUNCEMENT_XCHG
26 from st2common.transport.connection_retry_wrapper import ConnectionRetryWrapper
27 from st2common.transport.execution import EXECUTION_XCHG
28 from st2common.transport.liveaction import LIVEACTION_XCHG, LIVEACTION_STATUS_MGMT_XCHG
29 from st2common.transport.reactor import SENSOR_CUD_XCHG
30 from st2common.transport.reactor import TRIGGER_CUD_XCHG, TRIGGER_INSTANCE_XCHG
31 from st2common.transport import reactor
32 from st2common.transport.queues import ACTIONSCHEDULER_REQUEST_QUEUE
33 from st2common.transport.queues import ACTIONRUNNER_WORK_QUEUE
34 from st2common.transport.queues import ACTIONRUNNER_CANCEL_QUEUE
35 from st2common.transport.queues import EXPORTER_WORK_QUEUE
36 from st2common.transport.queues import NOTIFIER_ACTIONUPDATE_WORK_QUEUE
37 from st2common.transport.queues import RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE
38 from st2common.transport.queues import RULESENGINE_WORK_QUEUE
39 from st2common.transport.queues import STREAM_ANNOUNCEMENT_WORK_QUEUE
40 from st2common.transport.queues import STREAM_EXECUTION_WORK_QUEUE
41 from st2common.transport.queues import STREAM_LIVEACTION_WORK_QUEUE
42 
43 LOG = logging.getLogger('st2common.transport.bootstrap')
44 
45 __all__ = [
46     'register_exchanges',
47 
48     'EXCHANGES',
49     'QUEUES'
50 ]
51 
52 # List of exchanges which are pre-declared on service set up.
53 EXCHANGES = [
54     ACTIONEXECUTIONSTATE_XCHG,
55     ANNOUNCEMENT_XCHG,
56     EXECUTION_XCHG,
57     LIVEACTION_XCHG,
58     LIVEACTION_STATUS_MGMT_XCHG,
59     TRIGGER_CUD_XCHG,
60     TRIGGER_INSTANCE_XCHG,
61     SENSOR_CUD_XCHG
62 ]
63 
64 # List of queues which are pre-declared on service startup.
65 # All the queues need to be declared and bound up front so we can guarantee messages get routed
66 # and don't get lost even if there are no consumers online
67 QUEUES = [
68     ACTIONSCHEDULER_REQUEST_QUEUE,
69     ACTIONRUNNER_WORK_QUEUE,
70     ACTIONRUNNER_CANCEL_QUEUE,
71     EXPORTER_WORK_QUEUE,
72     NOTIFIER_ACTIONUPDATE_WORK_QUEUE,
73     RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE,
74     RULESENGINE_WORK_QUEUE,
75 
76     STREAM_ANNOUNCEMENT_WORK_QUEUE,
77     STREAM_EXECUTION_WORK_QUEUE,
78     STREAM_LIVEACTION_WORK_QUEUE,
79 
80     # Those queues are dynamically / late created on some class init but we still need to
81     # pre-declare them for redis Kombu backend to work.
82     reactor.get_trigger_cud_queue(name='st2.preinit', routing_key='init'),
83     reactor.get_sensor_cud_queue(name='st2.preinit', routing_key='init')
84 ]
85 
86 
87 def _do_register_exchange(exchange, connection, channel, retry_wrapper):
88     try:
89         kwargs = {
90             'exchange': exchange.name,
91             'type': exchange.type,
92             'durable': exchange.durable,
93             'auto_delete': exchange.auto_delete,
94             'arguments': exchange.arguments,
95             'nowait': False,
96             'passive': False
97         }
98         # Use the retry wrapper to increase resiliency in recoverable errors.
99         retry_wrapper.ensured(connection=connection,
100                               obj=channel,
101                               to_ensure_func=channel.exchange_declare,
102                               **kwargs)
103         LOG.debug('Registered exchange %s (%s).' % (exchange.name, str(kwargs)))
104     except Exception:
105         LOG.exception('Failed to register exchange: %s.', exchange.name)
106 
107 
108 def _do_predeclare_queue(channel, queue):
109     LOG.debug('Predeclaring queue for exchange "%s"' % (queue.exchange.name))
110 
111     bound_queue = None
112 
113     try:
114         bound_queue = queue(channel)
115         bound_queue.declare(nowait=False)
116         LOG.debug('Predeclared queue for exchange "%s"' % (queue.exchange.name))
117     except Exception:
118         LOG.exception('Failed to predeclare queue for exchange "%s"' % (queue.exchange.name))
119 
120     return bound_queue
121 
122 
123 def register_exchanges():
124     LOG.debug('Registering exchanges...')
125     connection_urls = transport_utils.get_messaging_urls()
126     with Connection(connection_urls) as conn:
127         # Use ConnectionRetryWrapper to deal with rmq clustering etc.
128         retry_wrapper = ConnectionRetryWrapper(cluster_size=len(connection_urls), logger=LOG)
129 
130         def wrapped_register_exchanges(connection, channel):
131             for exchange in EXCHANGES:
132                 _do_register_exchange(exchange=exchange, connection=connection, channel=channel,
133                                       retry_wrapper=retry_wrapper)
134 
135         retry_wrapper.run(connection=conn, wrapped_callback=wrapped_register_exchanges)
136 
137         def wrapped_predeclare_queues(connection, channel):
138             for queue in QUEUES:
139                 _do_predeclare_queue(channel=channel, queue=queue)
140 
141         retry_wrapper.run(connection=conn, wrapped_callback=wrapped_predeclare_queues)
142 
143 
144 def register_exchanges_with_retry():
145     def retry_if_io_error(exception):
146         return isinstance(exception, socket.error)
147 
148     retrying_obj = retrying.Retrying(
149         retry_on_exception=retry_if_io_error,
150         wait_fixed=cfg.CONF.messaging.connection_retry_wait,
151         stop_max_attempt_number=cfg.CONF.messaging.connection_retries
152     )
153     return retrying_obj.call(register_exchanges)
154
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/st2common/st2common/transport/bootstrap_utils.py b/st2common/st2common/transport/bootstrap_utils.py
--- a/st2common/st2common/transport/bootstrap_utils.py
+++ b/st2common/st2common/transport/bootstrap_utils.py
@@ -32,7 +32,6 @@
 from st2common.transport.queues import ACTIONSCHEDULER_REQUEST_QUEUE
 from st2common.transport.queues import ACTIONRUNNER_WORK_QUEUE
 from st2common.transport.queues import ACTIONRUNNER_CANCEL_QUEUE
-from st2common.transport.queues import EXPORTER_WORK_QUEUE
 from st2common.transport.queues import NOTIFIER_ACTIONUPDATE_WORK_QUEUE
 from st2common.transport.queues import RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE
 from st2common.transport.queues import RULESENGINE_WORK_QUEUE
@@ -68,7 +67,6 @@
     ACTIONSCHEDULER_REQUEST_QUEUE,
     ACTIONRUNNER_WORK_QUEUE,
     ACTIONRUNNER_CANCEL_QUEUE,
-    EXPORTER_WORK_QUEUE,
     NOTIFIER_ACTIONUPDATE_WORK_QUEUE,
     RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE,
     RULESENGINE_WORK_QUEUE,

{"golden_diff": "diff --git a/st2common/st2common/transport/bootstrap_utils.py b/st2common/st2common/transport/bootstrap_utils.py\n--- a/st2common/st2common/transport/bootstrap_utils.py\n+++ b/st2common/st2common/transport/bootstrap_utils.py\n@@ -32,7 +32,6 @@\n from st2common.transport.queues import ACTIONSCHEDULER_REQUEST_QUEUE\n from st2common.transport.queues import ACTIONRUNNER_WORK_QUEUE\n from st2common.transport.queues import ACTIONRUNNER_CANCEL_QUEUE\n-from st2common.transport.queues import EXPORTER_WORK_QUEUE\n from st2common.transport.queues import NOTIFIER_ACTIONUPDATE_WORK_QUEUE\n from st2common.transport.queues import RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE\n from st2common.transport.queues import RULESENGINE_WORK_QUEUE\n@@ -68,7 +67,6 @@\n     ACTIONSCHEDULER_REQUEST_QUEUE,\n     ACTIONRUNNER_WORK_QUEUE,\n     ACTIONRUNNER_CANCEL_QUEUE,\n-    EXPORTER_WORK_QUEUE,\n     NOTIFIER_ACTIONUPDATE_WORK_QUEUE,\n     RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE,\n     RULESENGINE_WORK_QUEUE,\n", "issue": "Don't publish messages to exporter exchange if exporter service is not enabled and running\nWhile working on #3648 and I noticed `st2.exporter.work` queue grows indefinitely.\r\n\r\nThe reason for that is that exporter service is optional and doesn't run by default.\r\n\r\nWe should modify the code to only publish messages to that exchange if exporter service is enabled and running (otherwise this queue will keep growing indefinitely and this could eventually cause issues).\n", "before_files": [{"content": "# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport socket\n\nimport retrying\nfrom oslo_config import cfg\nfrom kombu import Connection\n\nfrom st2common import log as logging\nfrom st2common.transport import utils as transport_utils\nfrom st2common.transport.actionexecutionstate import ACTIONEXECUTIONSTATE_XCHG\nfrom st2common.transport.announcement import ANNOUNCEMENT_XCHG\nfrom st2common.transport.connection_retry_wrapper import ConnectionRetryWrapper\nfrom st2common.transport.execution import EXECUTION_XCHG\nfrom st2common.transport.liveaction import LIVEACTION_XCHG, LIVEACTION_STATUS_MGMT_XCHG\nfrom st2common.transport.reactor import SENSOR_CUD_XCHG\nfrom st2common.transport.reactor import TRIGGER_CUD_XCHG, TRIGGER_INSTANCE_XCHG\nfrom st2common.transport import reactor\nfrom st2common.transport.queues import ACTIONSCHEDULER_REQUEST_QUEUE\nfrom st2common.transport.queues import ACTIONRUNNER_WORK_QUEUE\nfrom st2common.transport.queues import ACTIONRUNNER_CANCEL_QUEUE\nfrom st2common.transport.queues import EXPORTER_WORK_QUEUE\nfrom st2common.transport.queues import NOTIFIER_ACTIONUPDATE_WORK_QUEUE\nfrom st2common.transport.queues import RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE\nfrom st2common.transport.queues import RULESENGINE_WORK_QUEUE\nfrom st2common.transport.queues import STREAM_ANNOUNCEMENT_WORK_QUEUE\nfrom st2common.transport.queues import STREAM_EXECUTION_WORK_QUEUE\nfrom st2common.transport.queues import STREAM_LIVEACTION_WORK_QUEUE\n\nLOG = logging.getLogger('st2common.transport.bootstrap')\n\n__all__ = [\n    'register_exchanges',\n\n    'EXCHANGES',\n    'QUEUES'\n]\n\n# List of exchanges which are pre-declared on service set up.\nEXCHANGES = [\n    ACTIONEXECUTIONSTATE_XCHG,\n    ANNOUNCEMENT_XCHG,\n    EXECUTION_XCHG,\n    LIVEACTION_XCHG,\n    LIVEACTION_STATUS_MGMT_XCHG,\n    TRIGGER_CUD_XCHG,\n    TRIGGER_INSTANCE_XCHG,\n    SENSOR_CUD_XCHG\n]\n\n# List of queues which are pre-declared on service startup.\n# All the queues need to be declared and bound up front so we can guarantee messages get routed\n# and don't get lost even if there are no consumers online\nQUEUES = [\n    ACTIONSCHEDULER_REQUEST_QUEUE,\n    ACTIONRUNNER_WORK_QUEUE,\n    ACTIONRUNNER_CANCEL_QUEUE,\n    EXPORTER_WORK_QUEUE,\n    NOTIFIER_ACTIONUPDATE_WORK_QUEUE,\n    RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE,\n    RULESENGINE_WORK_QUEUE,\n\n    STREAM_ANNOUNCEMENT_WORK_QUEUE,\n    STREAM_EXECUTION_WORK_QUEUE,\n    STREAM_LIVEACTION_WORK_QUEUE,\n\n    # Those queues are dynamically / late created on some class init but we still need to\n    # pre-declare them for redis Kombu backend to work.\n    reactor.get_trigger_cud_queue(name='st2.preinit', routing_key='init'),\n    reactor.get_sensor_cud_queue(name='st2.preinit', routing_key='init')\n]\n\n\ndef _do_register_exchange(exchange, connection, channel, retry_wrapper):\n    try:\n        kwargs = {\n            'exchange': exchange.name,\n            'type': exchange.type,\n            'durable': exchange.durable,\n            'auto_delete': exchange.auto_delete,\n            'arguments': exchange.arguments,\n            'nowait': False,\n            'passive': False\n        }\n        # Use the retry wrapper to increase resiliency in recoverable errors.\n        retry_wrapper.ensured(connection=connection,\n                              obj=channel,\n                              to_ensure_func=channel.exchange_declare,\n                              **kwargs)\n        LOG.debug('Registered exchange %s (%s).' % (exchange.name, str(kwargs)))\n    except Exception:\n        LOG.exception('Failed to register exchange: %s.', exchange.name)\n\n\ndef _do_predeclare_queue(channel, queue):\n    LOG.debug('Predeclaring queue for exchange \"%s\"' % (queue.exchange.name))\n\n    bound_queue = None\n\n    try:\n        bound_queue = queue(channel)\n        bound_queue.declare(nowait=False)\n        LOG.debug('Predeclared queue for exchange \"%s\"' % (queue.exchange.name))\n    except Exception:\n        LOG.exception('Failed to predeclare queue for exchange \"%s\"' % (queue.exchange.name))\n\n    return bound_queue\n\n\ndef register_exchanges():\n    LOG.debug('Registering exchanges...')\n    connection_urls = transport_utils.get_messaging_urls()\n    with Connection(connection_urls) as conn:\n        # Use ConnectionRetryWrapper to deal with rmq clustering etc.\n        retry_wrapper = ConnectionRetryWrapper(cluster_size=len(connection_urls), logger=LOG)\n\n        def wrapped_register_exchanges(connection, channel):\n            for exchange in EXCHANGES:\n                _do_register_exchange(exchange=exchange, connection=connection, channel=channel,\n                                      retry_wrapper=retry_wrapper)\n\n        retry_wrapper.run(connection=conn, wrapped_callback=wrapped_register_exchanges)\n\n        def wrapped_predeclare_queues(connection, channel):\n            for queue in QUEUES:\n                _do_predeclare_queue(channel=channel, queue=queue)\n\n        retry_wrapper.run(connection=conn, wrapped_callback=wrapped_predeclare_queues)\n\n\ndef register_exchanges_with_retry():\n    def retry_if_io_error(exception):\n        return isinstance(exception, socket.error)\n\n    retrying_obj = retrying.Retrying(\n        retry_on_exception=retry_if_io_error,\n        wait_fixed=cfg.CONF.messaging.connection_retry_wait,\n        stop_max_attempt_number=cfg.CONF.messaging.connection_retries\n    )\n    return retrying_obj.call(register_exchanges)\n", "path": "st2common/st2common/transport/bootstrap_utils.py"}], "after_files": [{"content": "# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport socket\n\nimport retrying\nfrom oslo_config import cfg\nfrom kombu import Connection\n\nfrom st2common import log as logging\nfrom st2common.transport import utils as transport_utils\nfrom st2common.transport.actionexecutionstate import ACTIONEXECUTIONSTATE_XCHG\nfrom st2common.transport.announcement import ANNOUNCEMENT_XCHG\nfrom st2common.transport.connection_retry_wrapper import ConnectionRetryWrapper\nfrom st2common.transport.execution import EXECUTION_XCHG\nfrom st2common.transport.liveaction import LIVEACTION_XCHG, LIVEACTION_STATUS_MGMT_XCHG\nfrom st2common.transport.reactor import SENSOR_CUD_XCHG\nfrom st2common.transport.reactor import TRIGGER_CUD_XCHG, TRIGGER_INSTANCE_XCHG\nfrom st2common.transport import reactor\nfrom st2common.transport.queues import ACTIONSCHEDULER_REQUEST_QUEUE\nfrom st2common.transport.queues import ACTIONRUNNER_WORK_QUEUE\nfrom st2common.transport.queues import ACTIONRUNNER_CANCEL_QUEUE\nfrom st2common.transport.queues import NOTIFIER_ACTIONUPDATE_WORK_QUEUE\nfrom st2common.transport.queues import RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE\nfrom st2common.transport.queues import RULESENGINE_WORK_QUEUE\nfrom st2common.transport.queues import STREAM_ANNOUNCEMENT_WORK_QUEUE\nfrom st2common.transport.queues import STREAM_EXECUTION_WORK_QUEUE\nfrom st2common.transport.queues import STREAM_LIVEACTION_WORK_QUEUE\n\nLOG = logging.getLogger('st2common.transport.bootstrap')\n\n__all__ = [\n    'register_exchanges',\n\n    'EXCHANGES',\n    'QUEUES'\n]\n\n# List of exchanges which are pre-declared on service set up.\nEXCHANGES = [\n    ACTIONEXECUTIONSTATE_XCHG,\n    ANNOUNCEMENT_XCHG,\n    EXECUTION_XCHG,\n    LIVEACTION_XCHG,\n    LIVEACTION_STATUS_MGMT_XCHG,\n    TRIGGER_CUD_XCHG,\n    TRIGGER_INSTANCE_XCHG,\n    SENSOR_CUD_XCHG\n]\n\n# List of queues which are pre-declared on service startup.\n# All the queues need to be declared and bound up front so we can guarantee messages get routed\n# and don't get lost even if there are no consumers online\nQUEUES = [\n    ACTIONSCHEDULER_REQUEST_QUEUE,\n    ACTIONRUNNER_WORK_QUEUE,\n    ACTIONRUNNER_CANCEL_QUEUE,\n    NOTIFIER_ACTIONUPDATE_WORK_QUEUE,\n    RESULTSTRACKER_ACTIONSTATE_WORK_QUEUE,\n    RULESENGINE_WORK_QUEUE,\n\n    STREAM_ANNOUNCEMENT_WORK_QUEUE,\n    STREAM_EXECUTION_WORK_QUEUE,\n    STREAM_LIVEACTION_WORK_QUEUE,\n\n    # Those queues are dynamically / late created on some class init but we still need to\n    # pre-declare them for redis Kombu backend to work.\n    reactor.get_trigger_cud_queue(name='st2.preinit', routing_key='init'),\n    reactor.get_sensor_cud_queue(name='st2.preinit', routing_key='init')\n]\n\n\ndef _do_register_exchange(exchange, connection, channel, retry_wrapper):\n    try:\n        kwargs = {\n            'exchange': exchange.name,\n            'type': exchange.type,\n            'durable': exchange.durable,\n            'auto_delete': exchange.auto_delete,\n            'arguments': exchange.arguments,\n            'nowait': False,\n            'passive': False\n        }\n        # Use the retry wrapper to increase resiliency in recoverable errors.\n        retry_wrapper.ensured(connection=connection,\n                              obj=channel,\n                              to_ensure_func=channel.exchange_declare,\n                              **kwargs)\n        LOG.debug('Registered exchange %s (%s).' % (exchange.name, str(kwargs)))\n    except Exception:\n        LOG.exception('Failed to register exchange: %s.', exchange.name)\n\n\ndef _do_predeclare_queue(channel, queue):\n    LOG.debug('Predeclaring queue for exchange \"%s\"' % (queue.exchange.name))\n\n    bound_queue = None\n\n    try:\n        bound_queue = queue(channel)\n        bound_queue.declare(nowait=False)\n        LOG.debug('Predeclared queue for exchange \"%s\"' % (queue.exchange.name))\n    except Exception:\n        LOG.exception('Failed to predeclare queue for exchange \"%s\"' % (queue.exchange.name))\n\n    return bound_queue\n\n\ndef register_exchanges():\n    LOG.debug('Registering exchanges...')\n    connection_urls = transport_utils.get_messaging_urls()\n    with Connection(connection_urls) as conn:\n        # Use ConnectionRetryWrapper to deal with rmq clustering etc.\n        retry_wrapper = ConnectionRetryWrapper(cluster_size=len(connection_urls), logger=LOG)\n\n        def wrapped_register_exchanges(connection, channel):\n            for exchange in EXCHANGES:\n                _do_register_exchange(exchange=exchange, connection=connection, channel=channel,\n                                      retry_wrapper=retry_wrapper)\n\n        retry_wrapper.run(connection=conn, wrapped_callback=wrapped_register_exchanges)\n\n        def wrapped_predeclare_queues(connection, channel):\n            for queue in QUEUES:\n                _do_predeclare_queue(channel=channel, queue=queue)\n\n        retry_wrapper.run(connection=conn, wrapped_callback=wrapped_predeclare_queues)\n\n\ndef register_exchanges_with_retry():\n    def retry_if_io_error(exception):\n        return isinstance(exception, socket.error)\n\n    retrying_obj = retrying.Retrying(\n        retry_on_exception=retry_if_io_error,\n        wait_fixed=cfg.CONF.messaging.connection_retry_wait,\n        stop_max_attempt_number=cfg.CONF.messaging.connection_retries\n    )\n    return retrying_obj.call(register_exchanges)\n", "path": "st2common/st2common/transport/bootstrap_utils.py"}]}