stack: service distribute (Dockerfile.dist + distribute_loop.py, harian DISTRIBUTE_HOUR)
This commit is contained in:
1 parent
f77681793f
commit
4e02701887
5 files changed
+130
-7
No files matched your search
@@ -0,0 +1,77 @@
|
||||
"""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()
|
||||
Reference in new issue
Block a user