78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
"""Jadwal distribusi harian: jalankan distribute.py pada jam DISTRIBUTE_HOUR.
|
|
|
|
Menunggu hingga batas `DISTRIBUTE_HOUR` berikutnya (waktu lokal via `TZ`)
|
|
lalu memanggil `distribute.main()`. Loop tak pernah keluar — service dijaga
|
|
hidup oleh restart_policy swarm. Gagal distribusi dicatat lalu lanjut ke hari
|
|
berikutnya (⊥ membunuh loop). Tanpa `VEX_BP_PRIVATE_KEY` run nyata raise
|
|
RuntimeError yang jelas — ditangkap, dicetak, dicoba lagi besok.
|
|
|
|
Berbeda dengan scan: ⊥ ada "distribusi-awal" saat start (SCAN_RUN_ON_START) —
|
|
membayar di container start berisiko memakai snapshot basi; distribusi hanya
|
|
berjalan pada jam terjadwal.
|
|
|
|
Scheduler helper (`next_boundary`, `_wait_db`) sengaja diduplikasi dari
|
|
`scan_loop.py` (bukan di-import) karena kedua image Docker terpisah:
|
|
`Dockerfile.dist` ⊥ membawa `scan_loop.py`/`get_voters.py`.
|
|
"""
|
|
|
|
import os
|
|
import time
|
|
from datetime import datetime, timedelta
|
|
|
|
import db
|
|
import distribute
|
|
|
|
|
|
def next_boundary(now, hours):
|
|
"""datetime berikutnya pada jam-jam `hours` yang lebih besar dari `now`.
|
|
|
|
Sama dengan `scan_loop.next_boundary` (mirror agar image dist mandiri).
|
|
"""
|
|
for h in hours:
|
|
cand = now.replace(hour=h, minute=0, second=0, microsecond=0)
|
|
if cand > now:
|
|
return cand
|
|
# semua jam hari ini sudah lewat → besok jam pertama
|
|
nxt = now + timedelta(days=1)
|
|
return nxt.replace(hour=hours[0], minute=0, second=0, microsecond=0)
|
|
|
|
|
|
def _wait_db(timeout=120):
|
|
"""Tunggu basis data siap (mariadb baru boot) sebelum loop."""
|
|
start = time.monotonic()
|
|
while time.monotonic() - start < timeout:
|
|
try:
|
|
db.queryone('SELECT 1')
|
|
return
|
|
except Exception:
|
|
time.sleep(3)
|
|
raise RuntimeError('basis data tak siap setelah menunggu')
|
|
|
|
|
|
def _run_distribute(label):
|
|
print(f'[{label}] memulai distribusi...', flush=True)
|
|
try:
|
|
distribute.main()
|
|
except Exception as exc:
|
|
print(f'[Error] Distribusi gagal: {exc}', flush=True)
|
|
|
|
|
|
def main():
|
|
hour = int(os.getenv('DISTRIBUTE_HOUR', '10'))
|
|
if not 0 <= hour <= 23:
|
|
raise ValueError(f'DISTRIBUTE_HOUR tak valid: {hour!r}')
|
|
print(f'Jadwal distribusi: jam {hour} (waktu lokal)')
|
|
_wait_db()
|
|
while True:
|
|
now = datetime.now()
|
|
target = next_boundary(now, [hour])
|
|
wait = (target - now).total_seconds()
|
|
print(f'{now.isoformat(timespec="seconds")} tidur {wait / 3600:.2f} jam '
|
|
f'sampai {target.isoformat(timespec="seconds")}', flush=True)
|
|
time.sleep(max(wait, 0))
|
|
_run_distribute('distribusi terjadwal')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|