[F37] mxaccess: AsbSession::subscribe_buffered returns Unsupported
ASB has no `SetBufferedUpdateInterval` analogue — the per-monitored-
item `MinimalMonitoredItem::sample_interval` plays the cadence-knob
role. Calling `subscribe_buffered` on an ASB session now returns
`Error::Unsupported { transport: TransportKind::Asb, operation: ... }`
synchronously, without touching the wire.
The error-construction logic is split into a free fn
`unsupported_subscribe_buffered_error()` so the gate's exact shape
is unit-testable without spinning up a live authenticator + transport
fake. New unit test asserts both the variant tag and that the
operation message names the unsupported method + hints at the
`sample_interval` analogue.
Workspace 758 → 759 tests, clippy clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,7 @@ use tokio::task::JoinHandle;
|
|||||||
use tokio_stream::wrappers::ReceiverStream;
|
use tokio_stream::wrappers::ReceiverStream;
|
||||||
|
|
||||||
use crate::transport_asb::AsbTransport;
|
use crate::transport_asb::AsbTransport;
|
||||||
use crate::{ConnectionError, Error};
|
use crate::{BufferedOptions, ConnectionError, Error, TransportKind};
|
||||||
|
|
||||||
/// Channel buffer for [`AsbSubscription`]'s publish-loop. 256 samples is
|
/// Channel buffer for [`AsbSubscription`]'s publish-loop. 256 samples is
|
||||||
/// generous for the typical sample-rate budget (1-100 Hz) — bounded so
|
/// generous for the typical sample-rate budget (1-100 Hz) — bounded so
|
||||||
@@ -345,6 +345,36 @@ impl AsbSession {
|
|||||||
join: Some(join),
|
join: Some(join),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `subscribe_buffered` is **not supported** on the ASB transport.
|
||||||
|
/// ASB has no buffered-cadence equivalent of NMX's
|
||||||
|
/// `SetBufferedUpdateInterval`; the per-monitored-item `SampleInterval`
|
||||||
|
/// (see [`mxaccess_asb::MinimalMonitoredItem::sample_interval`])
|
||||||
|
/// already plays the rate-limit role — set it on each
|
||||||
|
/// `MonitoredItem` passed to [`Self::add_monitored_items`] instead.
|
||||||
|
///
|
||||||
|
/// Returns [`Error::Unsupported`] synchronously, without touching
|
||||||
|
/// the wire. F37.
|
||||||
|
pub async fn subscribe_buffered(
|
||||||
|
&self,
|
||||||
|
_reference: &str,
|
||||||
|
_options: BufferedOptions,
|
||||||
|
) -> Result<AsbSubscription, Error> {
|
||||||
|
Err(unsupported_subscribe_buffered_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// F37 — typed `Error::Unsupported` returned by
|
||||||
|
/// [`AsbSession::subscribe_buffered`]. Extracted into a free fn so the
|
||||||
|
/// gate's exact shape is unit-testable without constructing a full
|
||||||
|
/// `AsbSession` (which requires a live authenticator + transport).
|
||||||
|
fn unsupported_subscribe_buffered_error() -> Error {
|
||||||
|
Error::Unsupported {
|
||||||
|
operation: std::borrow::Cow::Borrowed(
|
||||||
|
"AsbSession::subscribe_buffered (use MinimalMonitoredItem::sample_interval; ASB has no SetBufferedUpdateInterval analogue)",
|
||||||
|
),
|
||||||
|
transport: TransportKind::Asb,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inner publish-loop body — testable in isolation by passing any
|
/// Inner publish-loop body — testable in isolation by passing any
|
||||||
@@ -477,6 +507,36 @@ mod tests {
|
|||||||
assert_stream_send_unpin::<AsbSubscription>();
|
assert_stream_send_unpin::<AsbSubscription>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// F37 — the `Error::Unsupported` returned by
|
||||||
|
/// `AsbSession::subscribe_buffered` carries `TransportKind::Asb`
|
||||||
|
/// and an operation message mentioning `subscribe_buffered`.
|
||||||
|
/// Targets the helper directly so the test doesn't need to spin
|
||||||
|
/// up a live authenticator / transport.
|
||||||
|
#[test]
|
||||||
|
fn subscribe_buffered_unsupported_error_shape() {
|
||||||
|
let err = unsupported_subscribe_buffered_error();
|
||||||
|
match err {
|
||||||
|
Error::Unsupported {
|
||||||
|
transport,
|
||||||
|
operation,
|
||||||
|
} => {
|
||||||
|
assert!(
|
||||||
|
matches!(transport, TransportKind::Asb),
|
||||||
|
"expected TransportKind::Asb, got {transport:?}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
operation.contains("subscribe_buffered"),
|
||||||
|
"operation should name the unsupported method, got {operation:?}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
operation.contains("sample_interval"),
|
||||||
|
"operation should hint at the ASB analogue, got {operation:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
other => panic!("expected Error::Unsupported, got {other:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fake_value(idx: i32) -> MonitoredItemValue {
|
fn fake_value(idx: i32) -> MonitoredItemValue {
|
||||||
MonitoredItemValue {
|
MonitoredItemValue {
|
||||||
item: ItemIdentity::absolute_by_name(format!("Tag{idx}")),
|
item: ItemIdentity::absolute_by_name(format!("Tag{idx}")),
|
||||||
|
|||||||
Reference in New Issue
Block a user