Give the Influx and MQTT nodes their two missing knobs
The Influx client was built with no timeout, so every query and write fell through to influxdb-client's own 10 s default — invisible to a flow and unchangeable. The param is in seconds like its peers; the client counts in milliseconds, so the call sites convert. The publisher backlog was a module constant, read once at import. It is the depth at which the oldest payload is dropped and the node goes degraded, and a node that bursts wants more than one that trickles, so it moves to Params and is read where the queue is built. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K1moruzue2kTJd3uVisgNk
This commit is contained in:
@@ -197,6 +197,47 @@ def test_a_flux_request_is_run_rather_than_written(monkeypatch):
|
||||
assert out == {"answer": {"rows": [], "range_s": 3600}}
|
||||
|
||||
|
||||
def test_the_configured_timeout_reaches_the_influx_client(monkeypatch):
|
||||
"""The client counts in milliseconds; the param is seconds like its peers."""
|
||||
import influxdb_client
|
||||
|
||||
from fluksio.flow.nodes import InfluxDbNode
|
||||
|
||||
seen: dict = {}
|
||||
|
||||
class FakeClient:
|
||||
def __init__(self, **kwargs):
|
||||
seen.update(kwargs)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *_):
|
||||
return False
|
||||
|
||||
def query_api(self):
|
||||
return self
|
||||
|
||||
def query(self, *_, **__):
|
||||
return []
|
||||
|
||||
monkeypatch.setattr(influxdb_client, "InfluxDBClient", FakeClient)
|
||||
|
||||
node = InfluxDbNode(
|
||||
provides=[MessageSpec(name="answer", dtype=DType.JSON)],
|
||||
params={
|
||||
"url": "http://influx",
|
||||
"token": "t",
|
||||
"org": "o",
|
||||
"bucket": "b",
|
||||
"timeout": 2.5,
|
||||
},
|
||||
)
|
||||
node._run_flux({"flux": 'from(bucket: "b")'})
|
||||
|
||||
assert seen["timeout"] == 2500
|
||||
|
||||
|
||||
def test_a_falsy_return_is_a_mistake_not_silence():
|
||||
"""Only None means "nothing to publish"."""
|
||||
from fluksio.flow.nodes import Node
|
||||
|
||||
@@ -119,3 +119,35 @@ def test_the_configured_timeout_reaches_the_broker_client(monkeypatch):
|
||||
asyncio.run(node._publish_once({"setpoint": 21.0}))
|
||||
|
||||
assert seen["timeout"] == 2.5
|
||||
|
||||
|
||||
def test_the_configured_backlog_reaches_the_publish_queue(monkeypatch):
|
||||
"""The depth is read when the queue is built, so it has to be per node."""
|
||||
import aiomqtt
|
||||
|
||||
class FakeClient:
|
||||
def __init__(self, **kwargs):
|
||||
pass
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *_):
|
||||
return False
|
||||
|
||||
monkeypatch.setattr(aiomqtt, "Client", FakeClient)
|
||||
|
||||
node = MqttNode(
|
||||
requires=[MessageSpec(name="setpoint", port="setpoint", dtype=DType.FLOAT)],
|
||||
params={"topic": {"setpoint": "heating/setpoint"}, "publish_queue_size": 8},
|
||||
)
|
||||
node.assign_flow("heating", "out")
|
||||
|
||||
async def scenario() -> int:
|
||||
await node.start_publisher()
|
||||
assert node._publish_queue is not None
|
||||
size = node._publish_queue.maxsize
|
||||
await node.stop_publisher()
|
||||
return size
|
||||
|
||||
assert asyncio.run(scenario()) == 8
|
||||
|
||||
Reference in New Issue
Block a user