-
Notifications
You must be signed in to change notification settings - Fork 0
Use publisher device host fallback for analytics topic hash #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -55,13 +55,20 @@ def username_pw_set(self, username, password=None): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class DummyAnalyticsPublisher: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, host: str | None = None): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.cleaned = False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if host: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.client = type("PublisherClient", (), {"device_config": DummyDeviceConfig(host=host)})() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def cleanup(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.cleaned = True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class DummyDeviceConfig: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, host: str): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.host = host | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_mqtt_client_dispatch_basic(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| processed_messages = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -194,3 +201,68 @@ def stop(self_inner): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert started["value"] is True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert started["stopped"] is True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert dummy_publisher.cleaned is True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_analytics_topic_hash_changes_with_device_ip(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client_a = AxisAnalyticsMqttClient( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_host="broker", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_port=1883, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device_config=DummyDeviceConfig(host="192.168.0.10"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| analytics_data_source_key="stream-key", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message_callback=lambda _: None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| create_publisher=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client_b = AxisAnalyticsMqttClient( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_host="broker", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_port=1883, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device_config=DummyDeviceConfig(host="192.168.0.11"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| analytics_data_source_key="stream-key", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message_callback=lambda _: None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| create_publisher=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert client_a.topic != client_b.topic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_analytics_topic_hash_is_stable_for_same_stream_and_device_ip(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client_a = AxisAnalyticsMqttClient( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_host="broker", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_port=1883, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device_config=DummyDeviceConfig(host="192.168.0.10"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| analytics_data_source_key="stream-key", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message_callback=lambda _: None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| create_publisher=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client_b = AxisAnalyticsMqttClient( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_host="broker", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_port=1883, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device_config=DummyDeviceConfig(host="192.168.0.10"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| analytics_data_source_key="stream-key", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message_callback=lambda _: None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| create_publisher=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert client_a.topic == client_b.topic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_analytics_topic_hash_uses_publisher_device_ip_when_device_config_missing(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client_a = AxisAnalyticsMqttClient( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_host="broker", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_port=1883, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device_config=None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| analytics_data_source_key="stream-key", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message_callback=lambda _: None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| create_publisher=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| publisher=DummyAnalyticsPublisher(host="192.168.0.20"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client_b = AxisAnalyticsMqttClient( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_host="broker", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| broker_port=1883, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device_config=None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| analytics_data_source_key="stream-key", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message_callback=lambda _: None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| create_publisher=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| publisher=DummyAnalyticsPublisher(host="192.168.0.21"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert client_a.topic != client_b.topic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert client_a.topic != client_b.topic | |
| assert client_a.topic != client_b.topic | |
| def test_analytics_topic_hash_is_stable_when_no_device_ip_available(): | |
| """ | |
| When neither device_config nor a usable publisher host is available, | |
| the topic hash should fall back to the legacy behavior and be stable | |
| for the same stream key. | |
| """ | |
| client_a = AxisAnalyticsMqttClient( | |
| broker_host="broker", | |
| broker_port=1883, | |
| device_config=None, | |
| analytics_data_source_key="stream-key", | |
| message_callback=lambda _: None, | |
| create_publisher=False, | |
| ) | |
| client_b = AxisAnalyticsMqttClient( | |
| broker_host="broker", | |
| broker_port=1883, | |
| device_config=None, | |
| analytics_data_source_key="stream-key", | |
| message_callback=lambda _: None, | |
| create_publisher=False, | |
| ) | |
| # With no device IP available from either device_config or publisher, | |
| # the topic hash should be deterministic and identical for the same | |
| # stream key, preserving backwards-compatible behavior. | |
| assert client_a.topic == client_b.topic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
device_hostresolves to an empty string (e.g.,device_config=Noneand no usable host on the injectedpublisher), the newhash_input = f"{analytics_data_source_key}:{device_host}"changes the computed suffix compared to the previous behavior (sha256(analytics_data_source_key)). This breaks determinism/backwards-compatibility for callers that previously relied on the old hash in the no-host case. Consider only adding the:device_hostportion when a non-empty host is available (or otherwise keep the old hashing input when host is empty).