diff --git a/chain_service/services/progress_chain_runner.py b/chain_service/services/progress_chain_runner.py new file mode 100644 index 0000000..c8e4925 --- /dev/null +++ b/chain_service/services/progress_chain_runner.py @@ -0,0 +1,62 @@ +from .progress_action.factory import ProgressActionServiceFactory + +from chain_service.database.models.progress_chain import ( + ProgressChain, + BaseProgressAction, + ProgressActionStatusEnum, +) + +from chain_service.repositories.progress_chain import ProgressChainRepository + +from loguru import logger +from datetime import datetime + + +class ProgressChainRunnerService: + + def __init__( + self, + progress_chain_repository: ProgressChainRepository, + progress_action_service_factory: ProgressActionServiceFactory, + ): + self.progress_chain_repository = progress_chain_repository + self.progress_action_service_factory = progress_action_service_factory + + async def process(self, progress_chain: ProgressChain): + + if progress_chain.is_finished or progress_chain.has_failed: + logger.info(f"Skipping ProgressChain {progress_chain.id}") + return + + for progress_action in progress_chain.actions: + + if progress_action.status is ProgressActionStatusEnum.DONE: + continue + + if not await self.process_action(progress_chain, progress_action): + break + + async def process_action( + self, progress_chain: ProgressChain, progress_action: BaseProgressAction + ): + + try: + progress_action.started_at = datetime.utcnow() + + progress_action_service = self.progress_action_service_factory( + progress_action + ) + + await progress_action_service.process(progress_action) + progress_action.status = ProgressActionStatusEnum.DONE + return True + + except Exception as error: + logger.exception(f"Error during action process for {progress_chain.id}") + progress_action.status = ProgressActionStatusEnum.FAILED + progress_action.error_text = str(error) + return False + + finally: + progress_action.finished_at = datetime.utcnow() + await self.progress_chain_repository.upsert(progress_chain)