fix: preserve unmanaged first-seen timestamps

Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-09-12 13:33:05 +00:00
committed by GitHub
co-authored by genichin
parent be2e73a2d6
commit f9284d1de8
4 changed files with 49 additions and 4 deletions
@@ -99,3 +99,30 @@ class TestCRUDRoundTrip:
rows_b = pg_unmanaged_store.list_states(instance_key="inst-B", lifecycle_state="all")
assert len(rows_a) == 1 and rows_a[0]["lifecycle_state"] == "resolved"
assert len(rows_b) == 1 and rows_b[0]["quantity"] == 7
def test_reactivated_state_preserves_original_first_seen(self, pg_unmanaged_store):
t1 = datetime(2026, 9, 7, 0, 0, tzinfo=UTC)
t2 = t1 + timedelta(minutes=1)
t3 = t2 + timedelta(minutes=1)
pg_unmanaged_store.observe(
instance_key="inst-A",
symbol="008110",
quantity=3,
observed_at=t1,
)
pg_unmanaged_store.resolve_absent(
instance_key="inst-A",
observed_symbols=set(),
observed_at=t2,
)
reopened = pg_unmanaged_store.observe(
instance_key="inst-A",
symbol="008110",
quantity=5,
observed_at=t3,
)
assert reopened["transition"] == "detected"
assert reopened["state"]["first_seen_at"] == t1
assert reopened["state"]["last_seen_at"] == t3
@@ -109,6 +109,22 @@ def test_in_memory_store_isolates_same_symbol_by_instance():
assert state_b["quantity"] == 7
def test_in_memory_store_preserves_first_seen_when_resolved_symbol_reappears():
store = InMemoryUnmanagedPositionStore()
t1 = datetime(2026, 9, 7, 0, 0, tzinfo=UTC)
t2 = t1 + timedelta(minutes=1)
t3 = t2 + timedelta(minutes=1)
store.observe(instance_key=INSTANCE, symbol="008110", quantity=3, observed_at=t1)
store.resolve_absent(instance_key=INSTANCE, observed_symbols=set(), observed_at=t2)
reopened = store.observe(instance_key=INSTANCE, symbol="008110", quantity=5, observed_at=t3)
assert reopened["transition"] == "detected"
assert reopened["state"]["first_seen_at"] == t1
assert reopened["state"]["last_seen_at"] == t3
assert reopened["state"]["quantity_changed_at"] == t3
def test_reconcile_core_holdings_suppresses_repeated_unmanaged_alarm_spam():
repo, svc = _wire()
emitter, transport = _make_emitter()
@@ -58,11 +58,11 @@ class PostgreSQLUnmanagedPositionStore:
cur.execute(
"UPDATE unmanaged_position_state "
"SET quantity = %s, lifecycle_state = 'active', "
" first_seen_at = %s, last_seen_at = %s, quantity_changed_at = %s, "
" resolved_at = NULL, updated_at = %s "
" last_seen_at = %s, quantity_changed_at = %s, resolved_at = NULL, "
" updated_at = %s "
"WHERE instance_key = %s AND symbol = %s "
f"RETURNING {_STATE_COLUMNS}",
(quantity, now, now, now, now, instance_key, symbol),
(quantity, now, now, now, instance_key, symbol),
)
elif int(previous["quantity"]) != int(quantity):
transition = "quantity_changed"
+3 -1
View File
@@ -629,7 +629,9 @@ class InMemoryUnmanagedPositionStore:
"symbol": symbol,
"quantity": quantity,
"lifecycle_state": "active",
"first_seen_at": now,
"first_seen_at": (
existing.get("first_seen_at", now) if existing is not None else now
),
"last_seen_at": now,
"quantity_changed_at": now,
"resolved_at": None,