Add generic MqttClient trait with multi-backend support#83
Open
MathiasKoch wants to merge 12 commits intofeature/kvstore-shadow-persistencefrom
Open
Add generic MqttClient trait with multi-backend support#83MathiasKoch wants to merge 12 commits intofeature/kvstore-shadow-persistencefrom
MathiasKoch wants to merge 12 commits intofeature/kvstore-shadow-persistencefrom
Conversation
…ss impls Introduces MqttClient, MqttSubscription, and MqttMessage traits that abstract over different MQTT backends without lifetime parameters on the traits themselves. GATs with 'm lifetime tie subscriptions to client borrows, resolving the previous lifetime mismatch with embedded-mqtt. Also bumps nightly toolchain to 2025-12-01 for zmij compatibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace direct embedded_mqtt::MqttClient usage with crate::mqtt::MqttClient trait bounds via Mqtt<C> newtype wrapper. Implement ToPayload directly on jobs structs (Describe, Update, GetPending, StartNext) to enable zero-copy serialization through generic publish methods, and use MqttTransfer<S> wrapper to avoid HRTB issues with BlockTransfer. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace direct embedded_mqtt usage in the shadows module with the MqttClient trait abstraction, following the same pattern as the OTA migration. Also fixes broken Error::MqttError references in defender_metrics caused by the error enum change. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add mock MQTT implementation for testing (src/mqtt/mock.rs) - Update shadow tests to use real Shadow struct with MockMqttClient - Remove ShadowTestOnly struct (~60 lines) Tests now use production code, enabling future unit tests for cloud methods (wait_delta, update, etc.). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update integration test to use inferred type parameter instead of NoopRawMutex, and remove duplicate unused test fixture structs left over from rebase. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
subscribe() was only using the first topic and silently dropping the rest. Callers like shadows and provisioning subscribe to accepted/rejected pairs and expect messages from both. Create N individual StreamOperations and merge them via futures::stream::SelectAll.
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces a generic
MqttClienttrait that decouples all rustot services from concrete MQTT implementations. Four backend implementations are provided:embedded-mqtt(no_std/embassy),rumqttc(std/tokio), AWS Greengrass IPC, and a mock client for testing. All services — shadows, OTA, provisioning, defender metrics, and jobs — are migrated to accept anyMqttClientimplementation via generics.This enables the same application code to run across bare-metal embedded devices, Linux gateways, and Greengrass components by swapping the MQTT backend at compile time.
Design
MqttClient Trait (
src/mqtt/mod.rs)Key design decisions:
&selfmethods — Interior mutability allows sharing across async tasks without&mutexclusivitysubscribe<const N: usize>enables zero-cost static dispatchToPayload/DeferredPayload— Lazy serialization directly into the transmit buffer, avoiding intermediate allocationsBackend Implementations
embedded_mqttsrc/mqtt/embedded.rsrumqttcsrc/mqtt/rumqttc.rsgreengrasssrc/mqtt/greengrass.rssrc/mqtt/mock.rs+/#)futures::stream::SelectAllPayloadBridgeadapterService Migration
All services now accept
C: MqttClientas a generic parameter instead of depending on a specific MQTT implementation. TheMqtt<C>newtype wrapper provides service-specific trait implementations.Changelog
MqttClient,MqttSubscription,MqttMessage, andToPayloadtraits insrc/mqtt/embedded-mqtt,rumqttc,greengrass, andmockbackend implementationsMqttClientMqttClientMqttClientMqttClientShadowTestOnlywithMockMqttClientin shadow testsSelectAll'staticrequirement on topic string references