Skip to content

Commit 89c2264

Browse files
committed
Resolve conflict
2 parents 4a4ab55 + 9a7b3a7 commit 89c2264

28 files changed

Lines changed: 1038 additions & 59 deletions

.DS_Store

6 KB
Binary file not shown.

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,5 @@ dmypy.json
132132
utils/SMPPSim/
133133

134134
# vscode
135-
.vscode
135+
.vscode
136+
.DS_Store

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
- Retry messages if Turn rate limits us
88
- Warning logs for config errors, including (ignored) extra keys
99
- Log an error if the outbound request times out
10+
- Adding middleware support
11+
- Adding logging and unidecoder middleware
12+
- Calling BaseWorker setup on all child classes
1013

1114
### Fixed
1215
- Sphinx builds now fail on warnings, and all existing warnings/errors in the docs have been fixed

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Welcome to vumi2's documentation!
1515
transports
1616
applications
1717
message_caches
18+
middleware
1819

1920

2021

docs/middleware.rst

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
Middleware
2+
==========
3+
Middleware provides additional functionality that can be attached to any existing transport,
4+
application or dispatcher worker. For example, middleware could log inbound and outbound messages, decode a unicoded message,
5+
store delivery reports in a database or modify a message.
6+
7+
Attaching middleware to your worker is fairly straight forward. Just extend your YAML configuration file with lines like:Attaching middleware to your worker is fairly straight forward. Just extend your YAML configuration file with lines like:
8+
9+
.. code-block:: YAML
10+
11+
middlewares:
12+
- class_path: vumi2.middlewares.unidecoder.Unidecoder
13+
enable_for_connectors: ["mc_qa_expressway"]
14+
outbound_enabled: true
15+
16+
The middleware section contains a list of middleware items.
17+
Each item contains a :py:data:`class_path` class_path which is the full Python path to the class implementing the middleware,
18+
:py:data:`enable_for_connectors` enable_for_connectors this is the list of transports that the middleware will run on,
19+
and :py:data:`{type}_enabled` fields which describes which type of message the middleware is enabled on (inbound, outbound or event)
20+
21+
Multiple layers of middleware may be specified as follows:
22+
23+
.. code-block:: YAML
24+
25+
middlewares:
26+
- class_path: vumi2.middlewares.unidecoder.Unidecoder
27+
enable_for_connectors: ["mc_qa_expressway"]
28+
outbound_enabled: true
29+
- class_path: vumi2.middlewares.logging.LoggingMiddleware
30+
enable_for_connectors: ["mc_qa_expressway"]
31+
outbound_enabled: true
32+
inbound_enabled: true
33+
event_enabled: true
34+
35+
You can think of the layers of middleware sitting on top of the underlying transport or application worker.
36+
Messages being consumed by the worker enter from the top and are processed by the middleware in the order you
37+
have defined them and eventually reach the worker at the bottom. Messages published by the worker aren't handled by the middleware.
38+
Middleware only applies to consumed messages, not published messages.
39+
40+
Adding your middleware:
41+
42+
.. toctree::
43+
:maxdepth: 2
44+
45+
middleware/building_your_own_middleware
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Implementing your own middleware
2+
=================================
3+
4+
A middleware class provides three handler functions, one for processing each of the three kinds of messages transports, applications and dispatchers typically send and receive (i.e. inbound user messages, outbound user messages, event messages) and three enabled functions for each of the types of messages
5+
6+
Although transport and application middleware potentially both provide the same sets of handlers, the two make use of them in slightly different ways. Inbound messages and events are published by transports but consumed by applications while outbound messages are opposite.
7+
8+
A middleware is required to subclass BaseMiddleware. This is a convenient definition of and set of common functionality for middleware classes. Custom setup should be done in
9+
:py:meth:`setup()` instead (if required). The config class can be overidden by replacing the :py:data:`config` variable.
10+
You should overwrite :py:meth:`handle_inbound(self, msg, connection)`, :py:meth:`handle_outbound(self, msg, connection)`, :py:meth:`handle_event(self, event, connection)`. :py:meth:`handle_inbound` and :py:meth:`handle_outbound` return vumi2 Messages
11+
:py:meth:`handle_event` returns vumi2 Events
12+
13+
See logging and unidecoder examples
14+
15+
How your middleware is used inside Vumi:
16+
----------------------------------------
17+
18+
While writing complex middleware, it may help to understand how a middleware class is used by Vumi transports and applications.
19+
20+
When a transport or application is started a list of middleware to load is read from the configuration.
21+
An instance of each piece of middleware is created and then :py:meth:`setup()` is called on each middleware object in
22+
order within the :py:meth:`setup()` of the worker
23+
24+
:py:meth:`middleware_{type}_handler` function (e.g., middleware_outbound_handler) of BaseWorker of each message type. This function will:
25+
Filter the middleware list based on connector_name and the middleware's :py:meth:`{type}_enabled` method.
26+
Create a decorated handler function that sequentially applies each enabled middleware's :py:meth:`handle_{type}` method to the message.
27+
Return the decorated handler. This decorated handler is then used in setting up the connection

poetry.lock

Lines changed: 14 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ quart-trio = "^0.11.1"
2525
hypercorn = "^0.16.0"
2626
"smpp.pdu3" = "^0.6"
2727
httpx = "^0.26.0"
28+
unidecode = "^1.3.8"
2829
prometheus-client = "^0.22.1"
2930

3031
[tool.poetry.group.dev.dependencies]

src/vumi2/applications/junebug_message_api/junebug_message_api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from quart import request
88
from trio import move_on_after
99

10-
from vumi2.cli import class_from_string
10+
from vumi2.class_helpers import class_from_string
1111
from vumi2.messages import (
1212
Event,
1313
Message,
@@ -105,6 +105,7 @@ class JunebugMessageApi(BaseWorker):
105105
config: JunebugMessageApiConfig
106106

107107
async def setup(self) -> None:
108+
await super().setup()
108109
state_cache_class = class_from_string(self.config.state_cache_class)
109110
self.state_cache = state_cache_class(self.config.state_cache_config)
110111
self.connector = await self.setup_receive_inbound_connector(

src/vumi2/applications/static_reply/static_reply.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class StaticReplyApplication(BaseWorker):
2020
config: StaticReplyConfig
2121

2222
async def setup(self) -> None:
23+
await super().setup()
2324
self.connector = await self.setup_receive_inbound_connector(
2425
connector_name=self.config.transport_name,
2526
inbound_handler=self.handle_inbound_message,

0 commit comments

Comments
 (0)