meeting words come from the units table; the constants are now defaults
MEETING_DAY, MEETING_DAYS, MEETING_DAY_ABBR, PACK_TIME, TROOP_TIME, PACK_CLOCK and TROOP_CLOCK were the last thing a leader could not change without a commit. identity.meeting_words() derives all seven from the units rows; app.py refreshes the module globals from it on a 30-second TTL in a middleware, and the page templates - f-strings that read those globals when a route runs - are untouched. A row that cannot supply a word keeps the default, so a half-filled unit degrades to today's copy rather than a blank. The day words come from the pack row: the site's copy assumes both units meet the same night, and if that changes the copy needs rewriting, not a bigger constant. Proven on a throwaway container with a DB copy: patching pack73 to Thursday 18:15 changed the homepage, cubs, troop and meta description; patching back restored them. tests/smoke_identity.py 59 -> 66.
This commit is contained in:
+39
@@ -59,9 +59,47 @@ TROOP_TIME = "7:30 PM"
|
||||
PACK_CLOCK = "6:00"
|
||||
TROOP_CLOCK = "7:30"
|
||||
|
||||
# Since 2026-09-04 the seven meeting words above are DEFAULTS. The live values
|
||||
# come from the units table (edited by leaders through the console, P2) via
|
||||
# identity.meeting_words(), applied by the middleware below before every
|
||||
# request. A unit row that cannot supply a word leaves the default standing,
|
||||
# so the constants are still the right place to read what the site falls back
|
||||
# to - and PROGRAM_YEAR stays a plain constant.
|
||||
_MEETING_DEFAULTS = dict(MEETING_DAY=MEETING_DAY, MEETING_DAYS=MEETING_DAYS,
|
||||
MEETING_DAY_ABBR=MEETING_DAY_ABBR, PACK_TIME=PACK_TIME,
|
||||
TROOP_TIME=TROOP_TIME, PACK_CLOCK=PACK_CLOCK, TROOP_CLOCK=TROOP_CLOCK)
|
||||
_meeting_cache = {"at": 0.0}
|
||||
MEETING_TTL = 30
|
||||
|
||||
|
||||
def refresh_meeting_words(force=False):
|
||||
"""Re-derive the meeting words from the units table, at most every
|
||||
MEETING_TTL seconds. The page templates are f-strings that read these
|
||||
module globals when a route runs, so updating the globals is the whole
|
||||
wiring - no template changes. Any failure keeps the defaults."""
|
||||
global MEETING_DAY, MEETING_DAYS, MEETING_DAY_ABBR, PACK_TIME, TROOP_TIME, PACK_CLOCK, TROOP_CLOCK
|
||||
now = time.monotonic()
|
||||
if not force and now - _meeting_cache["at"] < MEETING_TTL:
|
||||
return
|
||||
_meeting_cache["at"] = now
|
||||
try:
|
||||
w = identity.meeting_words(identity.list_units(), _MEETING_DEFAULTS)
|
||||
except Exception as e:
|
||||
print("meeting words: keeping defaults: %s" % e, flush=True)
|
||||
return
|
||||
MEETING_DAY, MEETING_DAYS, MEETING_DAY_ABBR = w["MEETING_DAY"], w["MEETING_DAYS"], w["MEETING_DAY_ABBR"]
|
||||
PACK_TIME, TROOP_TIME = w["PACK_TIME"], w["TROOP_TIME"]
|
||||
PACK_CLOCK, TROOP_CLOCK = w["PACK_CLOCK"], w["TROOP_CLOCK"]
|
||||
|
||||
app = FastAPI(title="Pack & Troop 73")
|
||||
app.mount("/static", StaticFiles(directory="/app/static"), name="static")
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
async def _meeting_words_middleware(request, call_next):
|
||||
refresh_meeting_words()
|
||||
return await call_next(request)
|
||||
|
||||
# Creates the schema if absent and backfills the legacy leads.jsonl once.
|
||||
store.init(backfill_jsonl=LEADS)
|
||||
app.include_router(admin_api.router)
|
||||
@@ -1089,6 +1127,7 @@ def bootstrap_notify(url):
|
||||
|
||||
|
||||
identity.init()
|
||||
refresh_meeting_words(force=True)
|
||||
auth.PAGE = page
|
||||
app.include_router(auth.router)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user