18058c4515
Follow-up on the #58818 cron-drain fix. The housekeeping ticker uses the same loop-scheduled-future pattern as cron — it refreshes the channel directory via safe_schedule_threadsafe(build_channel_directory(...), loop) and blocks on fut.result(timeout=30). The original fix swapped its join(5) for _await_thread_exit(5), which is a strict improvement (the loop stays alive so the future can run) but the 5s bound is shorter than the 30s future, so a refresh in flight at shutdown was still abandoned. Bound the housekeeping drain at 35s (30s future + margin) via a dedicated _HOUSEKEEPING_SHUTDOWN_DRAIN_TIMEOUT constant. Not user-facing (self-heals next tick) but keeps the cooperative drain honest across both threads.