type-c-interface: Add notification traits - #932
Conversation
Add notification traits to allow services to decouple from the notion of a channel-like object. This makes our code more flexible and makes it easier to implement certain types of custom functionality. assisted-by:claude-opus-4.8
There was a problem hiding this comment.
Pull request overview
This PR introduces notification traits in type-c-interface to decouple Type-C components from a concrete “channel sender” abstraction, enabling alternative notification backends (blocking vs non-blocking) while keeping call sites consistent. It updates type-c-service to depend on these notifier traits for both per-port events and service-wide events (e.g., debug accessory, UCSI connector change). It also updates tests and examples to wrap existing channel senders in notifier adapters via .into(), preserving existing behavior while making the wiring more flexible.
Changes:
- Add
type_c_interface::{port,service}::notification::{Notifier, Error}traits and errors, plus adapter newtypes that implementNotifierforSender/NonBlockingSender. - Refactor
type-c-serviceregistration and event emission paths to use notifier traits instead of directly callingtry_sendon channels. - Update tests/examples/macros to wrap existing senders into notifiers (
NonBlockingSenderNotifier).
Step-by-step Review Guide
-
New notification traits (interface-level)
- Review
type-c-interface/src/service/notification.rsandtype-c-interface/src/port/notification.rsfor the intended contract (backpressure signaling vs blocking behavior). - Review the adapter implementations in
type-c-interface/src/service/event.rsandtype-c-interface/src/port/event.rs:NonBlockingSenderNotifiermapstry_sendfailure toError::WouldBlock.SenderNotifierawaitssendand currently always returnsOk(()), which can introduce blocking semantics.
- Review
-
Service refactor to call notifiers
- Review
type-c-service/src/service/registration.rsto confirm the service now registersServiceNotifiertypes rather than event senders. - Review
type-c-service/src/service/mod.rswhere the service calls notifier methods inline while processing events, and note the impact if any notifier implementation blocks.
- Review
-
Controller refactor (per-port notifications)
- Review
type-c-service/src/controller/mod.rsand related controller trait impls (pd.rs,power.rs, etc.) to see that the per-port “type-c sender” becomes aPortNotifier. - Confirm the semantics of previously non-blocking
try_sendsites now depend on which notifier adapter is used.
- Review
-
Tests/examples wiring
- Review the test/common and examples changes to ensure they consistently wrap existing senders into
NonBlockingSenderNotifiervia.into(), maintaining non-blocking behavior.
- Review the test/common and examples changes to ensure they consistently wrap existing senders into
Potential Issues
| # | Severity | File | Description | Code |
|---|---|---|---|---|
| 1 | 🔴 High | type-c-service/src/service/mod.rs:80-95 |
Service awaits each notifier inline; using the new blocking SenderNotifier adapters can stall the service event loop under backpressure. Consider constraining registrations to non-blocking notifiers or isolating blocking listeners behind a task/queue boundary. |
for notifier in self.registration.notifiers() { ... .await ... } |
| 2 | 🟡 Medium | type-c-interface/src/service/notification.rs:16-17 |
Public notifier trait doesn’t document whether notify_* futures may block; this is important because call sites may be time-sensitive. |
pub trait Notifier<'port> { ... -> impl Future ... } |
| 3 | 🟡 Medium | type-c-interface/src/port/notification.rs:19-20 |
Same contract ambiguity for port notifications; blocking implementations can add latency/stall controller/state-machine paths. | pub trait Notifier { ... -> impl Future ... } |
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| type-c-service/tests/common/mod.rs | Switch test wiring to wrap port/service senders into notifier adapters. |
| type-c-service/src/service/ucsi.rs | Route UCSI change indicator emission through the new service notifier API. |
| type-c-service/src/service/registration.rs | Refactor registration from event senders to service notifiers. |
| type-c-service/src/service/mod.rs | Replace broadcast-event cloning with notifier calls; implement NotificationHandler. |
| type-c-service/src/controller/ucsi.rs | Update controller port generic parameter from sender to port notifier. |
| type-c-service/src/controller/type_c.rs | Update controller port generic parameter from sender to port notifier. |
| type-c-service/src/controller/retimer.rs | Update controller port generic parameter from sender to port notifier. |
| type-c-service/src/controller/power.rs | Update controller port generic parameter from sender to port notifier; notify via notifier. |
| type-c-service/src/controller/pd.rs | Send VDM/DP-status/alert notifications via PortNotifier instead of try_send. |
| type-c-service/src/controller/mod.rs | Rename stored sender field to notifier and notify status-changed via notifier. |
| type-c-service/src/controller/max_sink_voltage.rs | Update controller port generic parameter from sender to port notifier. |
| type-c-service/src/controller/macros.rs | Provide notifier type aliases and wrap senders into notifiers in macro expansion. |
| type-c-service/src/controller/electrical_disconnect.rs | Update controller port generic parameter from sender to port notifier. |
| type-c-interface/src/service/notification.rs | Add service notification trait + error type (new file). |
| type-c-interface/src/service/mod.rs | Export the new service::notification module. |
| type-c-interface/src/service/event.rs | Add service notifier adapter newtypes for Sender/NonBlockingSender. |
| type-c-interface/src/port/notification.rs | Add port notification + handler traits and error type (new file). |
| type-c-interface/src/port/mod.rs | Export the new port::notification module. |
| type-c-interface/src/port/event.rs | Add port notifier adapter newtypes for Sender/NonBlockingSender. |
| examples/std/src/lib/type_c/mock_controller.rs | Update mock controller port type to use port notifier adapter. |
| examples/rt685s-evk/src/bin/type_c.rs | Update example wiring to register service notifiers and port notifiers. |
| examples/rt685s-evk/src/bin/type_c_cfu.rs | Update CFU example wiring to register service notifiers and port notifiers. |
| /// Service notifier trait | ||
| pub trait Notifier<'port> { |
| /// Port notifier trait | ||
| pub trait Notifier { |
| /// Send an event to all registered listeners | ||
| fn broadcast_event(&mut self, event: ServiceEvent<'port, Reg::Port>) { | ||
| for sender in self.registration.event_senders() { | ||
| if sender.try_send(event.clone()).is_none() { | ||
| error!("Failed to send event to listener"); | ||
| async fn notify_debug_accessory(&mut self, port: &'port Reg::Port, connected: bool) { | ||
| for notifier in self.registration.notifiers() { | ||
| if let Err(e) = notifier.notify_debug_accessory(port, connected).await { | ||
| error!("Failed to notify debug accessory: {:#?}", e); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| async fn notify_ucsi_change_indicator(&mut self, port: &'port Reg::Port, port_id: GlobalPortId, notify_opm: bool) { | ||
| for notifier in self.registration.notifiers() { | ||
| if let Err(e) = notifier.notify_ucsi_change_indicator(port, port_id, notify_opm).await { | ||
| error!("Failed to notify UCSI change indicator: {:#?}", e); | ||
| } | ||
| } | ||
| } |
Add notification traits to allow services to decouple from the notion of a channel-like object. This makes our code more flexible and makes it easier to implement certain types of custom functionality.
assisted-by:claude-opus-4.8