From 5c1c7572d32af96acb517335e49c97736d632599 Mon Sep 17 00:00:00 2001 From: dsutanto Date: Wed, 19 Aug 2026 10:58:46 +0700 Subject: [PATCH] =?UTF-8?q?T56:=20jeda=20antar=20kirim=20distribusi=20(V63?= =?UTF-8?q?)=20=E2=80=94=20DISTRIBUTE=5FSEND=5FDELAY=20(default=2030s)=20A?= =?UTF-8?q?NTAR=20pemilih=20di=20send-loop,=20N=20pemilih=20=E2=86=92=20N?= =?UTF-8?q?=E2=88=921=20tidur=20(=E2=8A=A5=20setelah=20terakhir),=20real-r?= =?UTF-8?q?un=20saja=20(dry-run=20=E2=8A=96=20tidur);=20beri=20node/Hyperi?= =?UTF-8?q?on=20waktu=20mengejar=20indeks=20+=20meratakan=20beban=20broadc?= =?UTF-8?q?ast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 +++ config.py | 4 ++++ distribute.py | 13 +++++++++++-- docker-compose.yml | 1 + test_distribute.py | 22 ++++++++++++++++++++++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index fe12eef..385bf84 100644 --- a/.env.example +++ b/.env.example @@ -99,6 +99,9 @@ DISTRIBUTE_HOUR=10 DISTRIBUTE_WEEKDAY=wed,sat DISTRIBUTE_FIRST_RUN=2026-08-17 DISTRIBUTE_MAX_ATTEMPTS=3 +# Jeda (detik) ANTAR kirim transfer antar pemilih — beri node/Hyperion waktu +# mengejar indeks + meratakan beban broadcast. N pemilih → N−1 jeda per run. +DISTRIBUTE_SEND_DELAY=30 # Kill-switch: FALSE (default) = payout off; set TRUE untuk mengaktifkan # pembayaran. --dry-run tetap jalan walau off. DISTRIBUTE_ENABLED=false diff --git a/config.py b/config.py index e9709be..bfe8ce1 100644 --- a/config.py +++ b/config.py @@ -105,6 +105,10 @@ DASH_LIQUID_TTL = int(os.getenv('DASH_LIQUID_TTL', '60')) BP_PRIVATE_KEY = os.getenv('VEX_BP_PRIVATE_KEY', '') DISTRIBUTE_HOUR = int(os.getenv('DISTRIBUTE_HOUR', '10')) DISTRIBUTE_MAX_ATTEMPTS = int(os.getenv('DISTRIBUTE_MAX_ATTEMPTS', '3')) +# Jeda (detik) ANTAR kirim transfer antar pemilih (V63): send-loop distribusi +# tidur sebelum lanjut ke pemilih berikutnya — beri node/Hyperion waktu +# mengejar indeks + meratakan beban broadcast run panjang. Default 30. +DISTRIBUTE_SEND_DELAY = int(os.getenv('DISTRIBUTE_SEND_DELAY', '30')) # Kill-switch distribusi (V35): default OFF — payout hanya jalan saat diset # `true`. `--dry-run` tetap boleh jalan (read-only, ⊥ tanda tangan/tulis). DISTRIBUTE_ENABLED = os.getenv( diff --git a/distribute.py b/distribute.py index 992d342..ad0bd59 100644 --- a/distribute.py +++ b/distribute.py @@ -9,6 +9,8 @@ sebagai `pending` SEBELUM kirim (V21). Retry hanya baris `failed`; sebelum resend, txid diverifikasi di Hyperion agar transfer yang sempat mendarat tak terkirim ganda (V22). `--dry-run` menampilkan rencana tanpa tanda tangan (V26). Tidak ada freezing/carryover (V24): tiap run menghitung ulang segar. +V63: send-loop tidur `DISTRIBUTE_SEND_DELAY` (default 30s) ANTAR pemilih — +beri node/Hyperion waktu mengejar indeks + meratakan beban broadcast. """ import sys @@ -21,7 +23,8 @@ import requests import db import telegram from config import (API_NODES, BP_PRIVATE_KEY, HYPERION_NODES, - DISTRIBUTE_ENABLED, DISTRIBUTE_MAX_ATTEMPTS, TARGET_BP, + DISTRIBUTE_ENABLED, DISTRIBUTE_MAX_ATTEMPTS, + DISTRIBUTE_SEND_DELAY, TARGET_BP, TOKEN_CONTRACT, VEX_SYMBOL) VEX_PREC = Decimal('0.0001') @@ -286,7 +289,7 @@ def run_distribution(dry_run=False): flush=True) failed = [] sent_amount = 0.0 - for pid, owner, share in pending: + for idx, (pid, owner, share) in enumerate(pending): txid = None for attempt in range(1, DISTRIBUTE_MAX_ATTEMPTS + 1): try: @@ -336,6 +339,12 @@ def run_distribution(dry_run=False): print(f'[GAGAL] {owner}: {share} VEX — {exc}', flush=True) break time.sleep(2) + # V63: jeda ANTAR pemilih — beri node/Hyperion waktu mengejar indeks + # + meratakan beban broadcast run panjang. N pemilih → N−1 tidur + # (⊥ setelah pemilih terakhir); tetap jalan walau pemilih ini + # ditahan/gagal (pacing seragam). Dry-run ⊖ pernah sampai sini. + if idx < len(pending) - 1: + time.sleep(DISTRIBUTE_SEND_DELAY) status = 'ok' if not failed else 'partial' db.update_run_status(run_id, status, round(sent_amount, 4)) diff --git a/docker-compose.yml b/docker-compose.yml index a4f5649..a358f6d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -111,6 +111,7 @@ services: DISTRIBUTE_WEEKDAY: ${DISTRIBUTE_WEEKDAY:-wed,sat} DISTRIBUTE_FIRST_RUN: ${DISTRIBUTE_FIRST_RUN:-2026-08-17} DISTRIBUTE_MAX_ATTEMPTS: ${DISTRIBUTE_MAX_ATTEMPTS:-3} + DISTRIBUTE_SEND_DELAY: ${DISTRIBUTE_SEND_DELAY:-30} DISTRIBUTE_ENABLED: ${DISTRIBUTE_ENABLED:-false} HYPERION_API: ${HYPERION_API:-https://api.databisnis.id} volumes: diff --git a/test_distribute.py b/test_distribute.py index aa14836..19516c1 100644 --- a/test_distribute.py +++ b/test_distribute.py @@ -485,6 +485,28 @@ def main(): dist.verify_txid = _orig_verify dist.time.sleep = _orig_sleep + # ————— V63: jeda antar kirim — sleep `DISTRIBUTE_SEND_DELAY` ANTAR + # pemilih; N pemilih → N−1 tidur (⊥ setelah pemilih terakhir) ————— + make_voters_db(db.DB_PATH, [('aaa1', '1.0', 200.0, '2026-08-05T00:00:00', + fresh), + ('bbb2', '1.0', 300.0, '2026-08-05T00:00:00', + fresh), + ('ccc3', '1.0', 500.0, '2026-08-05T00:00:00', + fresh)]) + dist.fetch_balance = lambda: Decimal('100.0000') + dist.BP_PRIVATE_KEY = '5Ktest' + dist.DISTRIBUTE_MAX_ATTEMPTS = 3 + dist.build_signed_transfer = lambda to, amount, memo: FakeSigned('txD' + to) + dist.verify_txid = lambda txid: True + sleeps = [] + dist.time.sleep = lambda s: sleeps.append(s) + with redirect_stdout(io.StringIO()): + rc = dist.run_distribution(dry_run=False) + check('V63 run nyata exit 0 (jeda antar kirim)', rc == 0) + check('V63 3 pemilih → 2 jeda @ DISTRIBUTE_SEND_DELAY', + sleeps == [dist.DISTRIBUTE_SEND_DELAY] * 2) + dist.time.sleep = _orig_sleep + # ————— V35: kill-switch DISTRIBUTE_ENABLED=false → no-op ————— make_voters_db(db.DB_PATH, [('aaa1', '1.0', 1200.0, '2026-08-05T00:00:00', fresh)])