-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
160 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
# Migration guide: v2.0.0 | ||
|
||
Version 2.0.0 introduces some breaking changes. This page aims to help you migrate to this new major version. The relevant changes are: | ||
|
||
- The deprecated `connect` and `disconnect` methods have been removed | ||
- The deprecated `filtered_messages` and `unfiltered_messages` methods have been removed | ||
- User-managed queues for incoming messages have been replaced with a single client-wide queue | ||
- Some arguments to the `Client` have been renamed or removed | ||
|
||
## Changes to the client lifecycle | ||
|
||
The deprecated `connect` and `disconnect` methods have been removed. The best way to connect and disconnect from the broker is through the client's context manager: | ||
|
||
```python | ||
import asyncio | ||
import aiomqtt | ||
|
||
|
||
async def main(): | ||
async with aiomqtt.Client("test.mosquitto.org") as client: | ||
await client.publish("temperature/outside", payload=28.4) | ||
|
||
|
||
asyncio.run(main()) | ||
``` | ||
|
||
If your use case does not allow you to use a context manager, you can use the client’s `__aenter__` and `__aexit__` methods almost interchangeably in place of the removed `connect` and `disconnect` methods. | ||
|
||
The `__aenter__` and `__aexit__` methods are designed to be called by the `async with` statement when the execution enters and exits the context manager. However, we can also execute them manually: | ||
|
||
```python | ||
import asyncio | ||
import aiomqtt | ||
|
||
|
||
async def main(): | ||
client = aiomqtt.Client("test.mosquitto.org") | ||
await client.__aenter__() | ||
await client.publish("temperature/outside", payload=28.4) | ||
await client.__aexit__(None, None, None) | ||
|
||
|
||
asyncio.run(main()) | ||
``` | ||
|
||
`__aenter__` is equivalent to `connect`. `__aexit__` is equivalent to `disconnect` except that it forces disconnection instead of throwing an exception in case the client cannot disconnect cleanly. | ||
|
||
```{note} | ||
`__aexit__` expects three arguments: `exc_type`, `exc`, and `tb`. These arguments describe the exception that caused the context manager to exit, if any. You can pass `None` to all of these arguments in a manual call to `__aexit__`. | ||
``` | ||
|
||
## Changes to the message queue | ||
|
||
The `filtered_messages`, `unfiltered_messages`, and `messages` methods have been removed and replaced with a single client-wide message queue. | ||
|
||
A minimal example of printing all messages (unfiltered) looks like this: | ||
|
||
```python | ||
import asyncio | ||
import aiomqtt | ||
|
||
|
||
async def main(): | ||
async with aiomqtt.Client("test.mosquitto.org") as client: | ||
await client.subscribe("temperature/#") | ||
async for message in client.messages: | ||
print(message.payload) | ||
|
||
|
||
asyncio.run(main()) | ||
``` | ||
|
||
To handle messages from different topics differently, we can use `Topic.matches()`: | ||
|
||
```python | ||
import asyncio | ||
import aiomqtt | ||
|
||
|
||
async def main(): | ||
async with aiomqtt.Client("test.mosquitto.org") as client: | ||
await client.subscribe("temperature/#") | ||
await client.subscribe("humidity/#") | ||
async for message in client.messages: | ||
if message.topic.matches("humidity/inside"): | ||
print(f"[humidity/inside] {message.payload}") | ||
if message.topic.matches("+/outside"): | ||
print(f"[+/outside] {message.payload}") | ||
if message.topic.matches("temperature/#"): | ||
print(f"[temperature/#] {message.payload}") | ||
|
||
|
||
asyncio.run(main()) | ||
``` | ||
|
||
```{note} | ||
In our example, messages to `temperature/outside` are handled twice! | ||
``` | ||
|
||
The `filtered_messages`, `unfiltered_messages`, and `messages` methods created isolated message queues underneath, such that you could invoke them multiple times. From Version 2.0.0 on, the client maintains a single queue that holds all incoming messages, accessible via `Client.messages`. | ||
|
||
If you continue to need multiple queues (e.g. because you have special concurrency requirements), you can build a "distributor" on top: | ||
|
||
```python | ||
import asyncio | ||
import aiomqtt | ||
|
||
|
||
async def temperature_consumer(): | ||
while True: | ||
message = await temperature_queue.get() | ||
print(f"[temperature/#] {message.payload}") | ||
|
||
|
||
async def humidity_consumer(): | ||
while True: | ||
message = await humidity_queue.get() | ||
print(f"[humidity/#] {message.payload}") | ||
|
||
|
||
temperature_queue = asyncio.Queue() | ||
humidity_queue = asyncio.Queue() | ||
|
||
|
||
async def distributor(client): | ||
# Sort messages into the appropriate queues | ||
async for message in client.messages: | ||
if message.topic.matches("temperature/#"): | ||
temperature_queue.put_nowait(message) | ||
elif message.topic.matches("humidity/#"): | ||
humidity_queue.put_nowait(message) | ||
|
||
|
||
async def main(): | ||
async with aiomqtt.Client("test.mosquitto.org") as client: | ||
await client.subscribe("temperature/#") | ||
await client.subscribe("humidity/#") | ||
# Use a task group to manage and await all tasks | ||
async with asyncio.TaskGroup() as tg: | ||
tg.create_task(distributor(client)) | ||
tg.create_task(temperature_consumer()) | ||
tg.create_task(humidity_consumer()) | ||
|
||
|
||
asyncio.run(main()) | ||
``` | ||
|
||
## Changes to client arguments | ||
|
||
- The `queue_class` and `queue_maxsize` arguments to `filtered_messages`, `unfiltered_messages`, and `messages` have been moved to the `Client` and have been renamed to `queue_type` and `max_queued_incoming_messages` | ||
- The `max_queued_messages` client argument has been renamed to `max_queued_outgoing_messages` | ||
- The deprecated `message_retry_set` client argument has been removed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters