From 4b2da3ba7c5665c9523075ea7b585a6e21a88476 Mon Sep 17 00:00:00 2001 From: Matthieu Baerts Date: Thu, 20 Aug 2026 12:07:35 +0200 Subject: [PATCH 1/2] contest: retry later when unable to load input files The contest service was unable to load the 'branch_info' input file twice yesterday. Probably because it was being updated: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) Catch the error, and retry later. Signed-off-by: Matthieu Baerts --- pw_contest.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/pw_contest.py b/pw_contest.py index f118bb1..3277a13 100755 --- a/pw_contest.py +++ b/pw_contest.py @@ -275,18 +275,24 @@ def patch_state_update(pw, state: dict, link: str): def main_loop(pw) -> int: config = parse_configs() + refresh = int(config.get('cfg', 'refresh')) try: with open(config.get('state', 'patch_state'), "rb") as fp: patch_state = json.load(fp) except FileNotFoundError: patch_state = {'series':{}, 'prs':{}} - with open(config.get('input', 'branch_info'), "rb") as fp: - branches = json.load(fp) - with open(config.get('input', 'results'), "rb") as fp: - results = json.load(fp) - with open(config.get('input', 'filters'), "rb") as fp: - filters = json.load(fp) + + try: + with open(config.get('input', 'branch_info'), "rb") as fp: + branches = json.load(fp) + with open(config.get('input', 'results'), "rb") as fp: + results = json.load(fp) + with open(config.get('input', 'filters'), "rb") as fp: + filters = json.load(fp) + except (FileNotFoundError, json.decoder.JSONDecodeError) as e: + log("Unable to read input files, retry later:", str(e)) + return refresh results_by_branch = results_pivot(filters, results) branch_outcome = branch_summarize(filters, results_by_branch) @@ -304,7 +310,7 @@ def main_loop(pw) -> int: with open(config.get('state', 'patch_state'), 'w') as fp: json.dump(patch_state, fp) - return int(config.get('cfg', 'refresh')) + return refresh def parse_configs(): From d8171b99b83871471c8be11b66470399dac18439 Mon Sep 17 00:00:00 2001 From: Matthieu Baerts Date: Thu, 20 Aug 2026 12:10:17 +0200 Subject: [PATCH 2/2] contest: retry max 4 times to load input files Just to be able to see that there is something wrong going on. After this arbitrary limit, the service will crash, and this will be more visible than letting the service retrying over and over without actually updating Patchwork. The limit is set to 4, which should correspond to 5 minutes before reporting an error with these files if they stay corrupted for some reasons. Signed-off-by: Matthieu Baerts --- pw_contest.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pw_contest.py b/pw_contest.py index 3277a13..e84af99 100755 --- a/pw_contest.py +++ b/pw_contest.py @@ -273,7 +273,7 @@ def patch_state_update(pw, state: dict, link: str): log_end_sec() -def main_loop(pw) -> int: +def main_loop(pw, retries: int) -> int: config = parse_configs() refresh = int(config.get('cfg', 'refresh')) @@ -292,7 +292,7 @@ def main_loop(pw) -> int: filters = json.load(fp) except (FileNotFoundError, json.decoder.JSONDecodeError) as e: log("Unable to read input files, retry later:", str(e)) - return refresh + return refresh, retries + 1 results_by_branch = results_pivot(filters, results) branch_outcome = branch_summarize(filters, results_by_branch) @@ -310,7 +310,7 @@ def main_loop(pw) -> int: with open(config.get('state', 'patch_state'), 'w') as fp: json.dump(patch_state, fp) - return refresh + return refresh, 0 def parse_configs(): @@ -328,11 +328,17 @@ def main() -> None: force_single_thread=True) pw = Patchwork(config) + retries = 0 # We could do a file system watch here, because the inputs are all local. while True: log("Running at " + str(datetime.datetime.now())) - delay = main_loop(pw) + delay, retries = main_loop(pw, retries) + + if retries > 4: + log("Multiple succeeding errors, stop here") + sys.exit(1) + try: time.sleep(delay) except KeyboardInterrupt: