Move to hour-resolution adverts

This commit is contained in:
Jack Kingsman
2026-02-23 16:34:34 -08:00
parent 88d5a76081
commit ef4c79bc80
6 changed files with 90 additions and 31 deletions
+31
View File
@@ -177,6 +177,13 @@ async def run_migrations(conn: aiosqlite.Connection) -> int:
await set_version(conn, 20)
applied += 1
# Migration 21: Enforce minimum 1-hour advert interval
if version < 21:
logger.info("Applying migration 21: enforce minimum 1-hour advert interval")
await _migrate_021_enforce_min_advert_interval(conn)
await set_version(conn, 21)
applied += 1
if applied > 0:
logger.info(
"Applied %d migration(s), schema now at version %d", applied, await get_version(conn)
@@ -1252,3 +1259,27 @@ async def _migrate_020_enable_wal_and_auto_vacuum(conn: aiosqlite.Connection) ->
logger.info("Journal mode set to %s", mode)
await conn.commit()
async def _migrate_021_enforce_min_advert_interval(conn: aiosqlite.Connection) -> None:
"""
Enforce minimum 1-hour advert interval.
Any advert_interval between 1 and 3599 is clamped up to 3600 (1 hour).
Zero (disabled) is left unchanged.
"""
# Guard: app_settings table may not exist if running against a very old schema
# (it's created in migration 9). The UPDATE is harmless if the table exists
# but has no rows, but will error if the table itself is missing.
cursor = await conn.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name='app_settings'"
)
if await cursor.fetchone() is None:
logger.debug("app_settings table does not exist yet, skipping advert_interval clamp")
return
await conn.execute(
"UPDATE app_settings SET advert_interval = 3600 WHERE advert_interval > 0 AND advert_interval < 3600"
)
await conn.commit()
logger.debug("Clamped advert_interval to minimum 3600 seconds")
+8
View File
@@ -41,6 +41,11 @@ _advert_task: asyncio.Task | None = None
# We still need to periodically check if it's been enabled
ADVERT_CHECK_INTERVAL = 60
# Minimum allowed advertisement interval (1 hour).
# Even if the database has a shorter value, we silently refuse to advertise
# more frequently than this.
MIN_ADVERT_INTERVAL = 3600
# Counter to pause polling during repeater operations (supports nested pauses)
_polling_pause_count: int = 0
@@ -384,6 +389,9 @@ async def send_advertisement(force: bool = False) -> bool:
logger.debug("Advertisement skipped: periodic advertising is disabled")
return False
# Enforce minimum interval floor
interval = max(interval, MIN_ADVERT_INTERVAL)
# Check if enough time has passed
elapsed = now - last_time
if elapsed < interval:
+7 -3
View File
@@ -52,7 +52,7 @@ class AppSettingsUpdate(BaseModel):
advert_interval: int | None = Field(
default=None,
ge=0,
description="Periodic advertisement interval in seconds (0 = disabled)",
description="Periodic advertisement interval in seconds (0 = disabled, minimum 3600)",
)
bots: list[BotConfig] | None = Field(
default=None,
@@ -111,8 +111,12 @@ async def update_settings(update: AppSettingsUpdate) -> AppSettings:
kwargs["sidebar_sort_order"] = update.sidebar_sort_order
if update.advert_interval is not None:
logger.info("Updating advert_interval to %d", update.advert_interval)
kwargs["advert_interval"] = update.advert_interval
# Enforce minimum 1-hour interval; 0 means disabled
interval = update.advert_interval
if 0 < interval < 3600:
interval = 3600
logger.info("Updating advert_interval to %d", interval)
kwargs["advert_interval"] = interval
if update.bots is not None:
validate_all_bots(update.bots)