From cfc1fcd62fa49f7d33a192496e0e8c00e5b79d30 Mon Sep 17 00:00:00 2001 From: Steve Lasker Date: Mon, 11 Dec 2023 07:43:43 -0800 Subject: [PATCH] Add a check_operation_status script (#4) * Add a check_operation_status script * python linting fixes * Address PR Feedback * Update scitt/check_operation_status.py Co-authored-by: Joe Gough <36932486+honourfish@users.noreply.github.com> Signed-off-by: Steve Lasker --- .vscode/settings.json | 5 ++ scitt/check_operation_status.py | 103 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 .vscode/settings.json create mode 100755 scitt/check_operation_status.py diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0f92541 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "datatrails" + ] +} \ No newline at end of file diff --git a/scitt/check_operation_status.py b/scitt/check_operation_status.py new file mode 100755 index 0000000..267cc38 --- /dev/null +++ b/scitt/check_operation_status.py @@ -0,0 +1,103 @@ +""" Module for checking when a statement has been anchored in the append-only ledger """ + +import os +import argparse + +from time import sleep as time_sleep + +import requests + + +# all timeouts and durations are in seconds +REQUEST_TIMEOUT = 30 +POLL_TIMEOUT = 360 +POLL_INTERVAL = 10 + + +def get_token_from_file(token_file_name: str) -> dict: + """ + gets the token from a file, + assume the contents of the file is the + whole authorization header: `Authorization: Bearer {token}` + """ + with open(token_file_name, mode="r", encoding="utf-8") as token_file: + auth_header = token_file.read().strip() + header, value = auth_header.split(": ") + return {header: value} + + +def get_operation_status(operation_id: str, headers: dict) -> dict: + """ + gets the operation status from the datatrails API for retrieving operation status + """ + + url = ( + f"https://app.datatrails.ai/archivist/v1/publicscitt/operations/{operation_id}" + ) + + response = requests.get(url, timeout=30, headers=headers) + response.raise_for_status() + + return response.json() + + +def poll_operation_status(operation_id: str, headers: dict) -> str: + """ + polls for the operation status to be 'succeeded'. + """ + + poll_attempts: int = int(POLL_TIMEOUT / POLL_INTERVAL) + + for _ in range(poll_attempts): + operation_status = get_operation_status(operation_id, headers) + + # pylint: disable=fixme + # TODO: ensure get_operation_status handles error cases from the rest request + if "status" in operation_status and operation_status["status"] == "succeeded": + return operation_status["entryID"] + + time_sleep(POLL_INTERVAL) + + raise TimeoutError("signed statement not registered within polling duration.") + + +def main(): + """Polls for the signed statement to be registered""" + + parser = argparse.ArgumentParser( + description="Polls for the signed statement to be registered" + ) + + # operation id + parser.add_argument( + "--operation-id", + type=str, + help="the operation-id from a registered statement", + ) + + # get default token file name + home = os.environ.get("HOME") + if home is None: + default_token_file_name: str = ".datatrails/bearer-token.txt" + else: + default_token_file_name: str = home + "/.datatrails/bearer-token.txt" + + # token file name + parser.add_argument( + "--token-file-name", + type=str, + help="filename containing the token in the format" + "of an auth header: `Authorization: Bearer {token}", + default=default_token_file_name, + ) + + args = parser.parse_args() + + headers = get_token_from_file(args.token_file_name) + + entry_id = poll_operation_status(args.operation_id, headers) + print(entry_id) + + +if __name__ == "__main__": + main()