Owner preference: the bulk of TRADING_*/TRIGGER_* logic switches should live in the DB, not the compose file (keys + connection info stay in compose — the DB address cannot live inside the DB, and secrets don't belong in a table the stack can SELECT). Precedence at boot: compose env < overrides.env < config_overrides table; every entrypoint already routes through env_overrides.load(), which now applies the table last. Admin /api/config and profile-apply write the table (secrets whitelist unchanged); the config page shows source=database. DB down = silent fall-through to file/compose, boot never blocks on config. One-shot migration: python -m runtime.env_overrides seed-from-env run in any stack container to copy its current effective knobs into the table, after which the compose lines are dead weight strippable at the next redeploy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
42 lines
1.3 KiB
Python
42 lines
1.3 KiB
Python
"""DB-backed config overrides: table CRUD + boot precedence."""
|
|
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from runtime import env_overrides
|
|
from storage.event_store import EventStore
|
|
|
|
|
|
@pytest.fixture
|
|
def con():
|
|
s = EventStore(":memory:")
|
|
yield s.con
|
|
s.close()
|
|
|
|
|
|
def test_write_read_roundtrip_and_delete(con):
|
|
merged = env_overrides.write_db_overrides(
|
|
{"TRADING_MAX_ORDERS_PER_TICK": "3", "TRIGGER_RVOL_MIN": "1.5"}, con=con)
|
|
assert merged == {"TRADING_MAX_ORDERS_PER_TICK": "3", "TRIGGER_RVOL_MIN": "1.5"}
|
|
merged = env_overrides.write_db_overrides(
|
|
{"TRIGGER_RVOL_MIN": None, "TRADING_MAX_ORDERS_PER_TICK": "5"}, con=con)
|
|
assert merged == {"TRADING_MAX_ORDERS_PER_TICK": "5"}
|
|
|
|
|
|
def test_read_missing_table_is_empty(con):
|
|
assert env_overrides.read_db_overrides(con=con) == {}
|
|
|
|
|
|
def test_load_db_applies_onto_environ(con, monkeypatch):
|
|
env_overrides.write_db_overrides({"TRADING_TEST_KNOB_XYZ": "42"}, con=con)
|
|
monkeypatch.setattr(env_overrides, "_db_con", lambda: con)
|
|
monkeypatch.setenv("TRADING_TEST_KNOB_XYZ", "1") # compose value loses
|
|
n = env_overrides.load_db()
|
|
assert n == 1 and os.environ["TRADING_TEST_KNOB_XYZ"] == "42"
|
|
|
|
|
|
def test_load_db_kill_switch(monkeypatch):
|
|
monkeypatch.setenv("ENV_OVERRIDES_DB", "0")
|
|
assert env_overrides.load_db() == 0
|