Merge pull request 'implement retry' (#6) from y266shen/mirror-checker:feature-retry into master

Reviewed-on: #6
This commit is contained in:
Raymond Li 2022-03-26 20:24:41 -04:00
commit 4a3cedfb07
1 changed files with 31 additions and 9 deletions

40
main.py
View File

@ -8,11 +8,15 @@ import time
import sys import sys
import requests import requests
from multiprocessing import Pool, Manager from multiprocessing import Pool, Manager
from typing import Optional
from time import sleep, localtime, strftime
from projects import * from projects import *
import json import json
NUM_THREAD = 16 NUM_THREAD = 16
MAX_RETRY = 3
RETRY_TIMEOUT = 30 # In seconds
current_time = int(time.time()) current_time = int(time.time())
@ -21,33 +25,51 @@ def safe_print(*args, **kwargs):
# due to buffering. Make sure to always flush the output. # due to buffering. Make sure to always flush the output.
print(*args, **kwargs, flush=True) print(*args, **kwargs, flush=True)
def check_project(args): # Return None if no error occurs and a string for error message otherwise
def check_project(args) -> Optional[str]:
project, data = args project, data = args
try: try:
project_class = getattr(sys.modules[__name__], project) project_class = getattr(sys.modules[__name__], project)
# Skip projects we no longer mirror # Skip projects we no longer mirror
if data[project].get('exclude', False): if data[project].get('exclude', False):
return True return None
checker_result = project_class.check(data, project, current_time) checker_result = project_class.check(data, project, current_time)
if checker_result: if checker_result:
data[project]["out_of_sync_since"] = None data[project]["out_of_sync_since"] = None
safe_print(f"Success: {project} up-to-date") return None
return True
elif (data[project]["out_of_sync_since"] is not None elif (data[project]["out_of_sync_since"] is not None
and current_time - data[project]["out_of_sync_since"] > data[project]["out_of_sync_interval"]): and current_time - data[project]["out_of_sync_since"] > data[project]["out_of_sync_interval"]):
safe_print(f"Failure: {project} out-of-sync") time_str = strftime("%d %b %Y %H:%M:%S (local time)", localtime())
return False return f"{project} out-of-sync at {time_str}"
else: else:
data[project]["out_of_sync_since"] = current_time data[project]["out_of_sync_since"] = current_time
return True return None
except requests.exceptions.RequestException as err: except requests.exceptions.RequestException as err:
safe_print(f"Error: {project}\n{err}") return f"{project}\n{err}"
def check_project_with_retry(args) -> bool:
project, _ = args
errs = []
for _ in range(MAX_RETRY):
res = check_project(args)
if res == None:
safe_print(f"Success: {project} up-to-date")
return True
else:
errs.append(res)
# Do nothing, try again later
sleep(RETRY_TIMEOUT)
# Max try reached, print errors
safe_print(f"Error: {project}")
for reason in errs:
safe_print(f" {reason}")
return False return False
@ -61,7 +83,7 @@ def main():
sync_data = manager.dict({k: manager.dict(v) for k, v in data.items()}) sync_data = manager.dict({k: manager.dict(v) for k, v in data.items()})
with Pool(NUM_THREAD) as pool: with Pool(NUM_THREAD) as pool:
all_pass = all(pool.imap(check_project, ((k, sync_data) for k in data.keys()))) all_pass = all(pool.imap(check_project_with_retry, ((k, sync_data) for k in data.keys())))
with open(data_file, "w", encoding="utf-8") as file: with open(data_file, "w", encoding="utf-8") as file:
json.dump({k: dict(v) for k, v in sync_data.items()}, file, indent=' ') json.dump({k: dict(v) for k, v in sync_data.items()}, file, indent=' ')