"""RedisState against a real server, enabled by FLUKSIO_TEST_REDIS_HOST (and optional PORT).""" import os import uuid import pytest from fluksio.flow.state import RedisState @pytest.fixture def state(): host = os.environ.get("FLUKSIO_TEST_REDIS_HOST") if not host: pytest.skip("Set FLUKSIO_TEST_REDIS_HOST to run Redis integration checks") port = int(os.environ.get("FLUKSIO_TEST_REDIS_PORT", "6379")) state = RedisState(host, port, namespace=f"test-state-{uuid.uuid4().hex}", ttl=600) try: yield state finally: state.clear() state.close() def test_a_ttl_expires_counters_and_the_names_set(state): state.set("heat.temp", 21) state.increment("__version__:heat.a") state.increment_multi(["__version__:heat.b"]) state.record({"heat.v": 1}, {}, ["__version__:heat.c"], 0.0) keys = state.keys() assert "__names__" in keys and "__version__:heat.c" in keys assert all(state._client.ttl(state._key(k)) > 0 for k in keys) def test_a_compare_and_swap_names_what_it_wrote(state): state.set("heat.a", 1) assert state.compare_and_swap_multi({"heat.a": 1}, {"heat.b": 2}) assert "heat.b" in state.message_names() def test_a_compare_and_swap_loses_to_a_write_after_its_read(state, monkeypatch): state.set("heat.a", 1) note = RedisState._note def racing_note(self, pipe, keys): # Another writer lands between the compare and EXEC. self._client.set(self._key("heat.a"), b"2") note(self, pipe, keys) monkeypatch.setattr(RedisState, "_note", racing_note) assert not state.compare_and_swap_multi({"heat.a": 1}, {"heat.a": 3}) assert state.get("heat.a") == 2