Add startup scheme

This commit is contained in:
Rene Arumetsa
2026-07-26 21:36:26 +03:00
parent c40c871a4b
commit 94fe57a596
5 changed files with 42 additions and 1 deletions

15
bot.py
View File

@@ -383,6 +383,21 @@ async def on_ready():
log.info("Logged in as %s (ID: %s)", bot.user, bot.user.id) log.info("Logged in as %s (ID: %s)", bot.user, bot.user.id)
economy.set_house(bot.user.id) economy.set_house(bot.user.id)
# PocketBase silently drops writes to fields missing from the collection
# schema, so surface any drift loudly instead of letting features no-op.
try:
missing = await economy.missing_schema_fields()
if missing:
log.error(
"PocketBase collection '%s' is missing %d schema field(s): %s "
"- writes to them are silently dropped! Run scripts/sync_pb_schema.py.",
config.PB_ECONOMY_COLLECTION, len(missing), ", ".join(missing),
)
else:
log.info("PocketBase schema check passed (%s)", config.PB_ECONOMY_COLLECTION)
except Exception as e:
log.warning("Could not verify PocketBase schema: %s", e)
_apply_profile_command_filters() _apply_profile_command_filters()
# Pull sheet data into cache # Pull sheet data into cache

View File

@@ -573,6 +573,15 @@ async def do_spam_jail(user_id: int) -> None:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Public helpers # Public helpers
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
async def missing_schema_fields() -> list[str]:
"""Compare the live PocketBase collection schema against every field the
bot persists. PocketBase silently drops writes to undeclared fields, so
any name returned here means broken features without error messages."""
live = await pb_client.get_collection_fields()
expected = set(_default_user()) | {"user_id"}
return sorted(expected - live)
async def get_all_users_raw() -> dict[str, "UserData"]: async def get_all_users_raw() -> dict[str, "UserData"]:
"""Return a snapshot of all user records.""" """Return a snapshot of all user records."""
records = await pb_client.list_all_records() records = await pb_client.list_all_records()

View File

@@ -147,6 +147,12 @@ async def update_record(record_id: str, data: dict[str, Any]) -> dict[str, Any]:
) )
async def get_collection_fields() -> set[str]:
"""Return the field names defined on the economy collection's schema."""
data = await _request("GET", f"{PB_URL}/api/collections/{ECONOMY_COLLECTION}")
return {f["name"] for f in data.get("fields", [])}
async def count_records() -> int: async def count_records() -> int:
"""Return the total number of records in the collection (single cheap request).""" """Return the total number of records in the collection (single cheap request)."""
data = await _request( data = await _request(

View File

@@ -73,6 +73,11 @@ class FakePocketBase:
async def count_records(self) -> int: async def count_records(self) -> int:
return len(self.records) return len(self.records)
async def get_collection_fields(self) -> set[str]:
if self.schema_fields is None:
return set(economy._default_user()) | {"user_id"}
return set(self.schema_fields)
# -- test helpers ------------------------------------------------------- # -- test helpers -------------------------------------------------------
def record_for(self, user_id: int) -> dict: def record_for(self, user_id: int) -> dict:
for record in self.records.values(): for record in self.records.values():
@@ -83,7 +88,7 @@ class FakePocketBase:
def _install(monkeypatch, fake: FakePocketBase) -> FakePocketBase: def _install(monkeypatch, fake: FakePocketBase) -> FakePocketBase:
for name in ("get_record", "create_record", "update_record", for name in ("get_record", "create_record", "update_record",
"list_all_records", "count_records"): "list_all_records", "count_records", "get_collection_fields"):
monkeypatch.setattr(pb_client, name, getattr(fake, name)) monkeypatch.setattr(pb_client, name, getattr(fake, name))
monkeypatch.setattr(economy, "HOUSE_ID", None) monkeypatch.setattr(economy, "HOUSE_ID", None)
monkeypatch.setattr(economy, "_house_pb_id", None) monkeypatch.setattr(economy, "_house_pb_id", None)

View File

@@ -100,6 +100,12 @@ class TestClaim:
class TestSchemaDetection: class TestSchemaDetection:
def test_missing_fields_reported(self, fake_pb_without_quest_fields):
assert run(economy.missing_schema_fields()) == ["quest_daily", "quest_weekly"]
def test_healthy_schema_reports_nothing(self, fake_pb):
assert run(economy.missing_schema_fields()) == []
def test_missing_quest_fields_warn_and_zero_progress( def test_missing_quest_fields_warn_and_zero_progress(
self, fake_pb_without_quest_fields, caplog self, fake_pb_without_quest_fields, caplog
): ):