def update_subtasks_states(subtask: Subtask, client_public_key: bytes) -> None: if (subtask.state in [state.name for state in Subtask.ACTIVE_STATES] and subtask.next_deadline <= parse_timestamp_to_utc_datetime( get_current_utc_timestamp())): verify_file_status(subtask=subtask, client_public_key=client_public_key) _update_timed_out_subtask(subtask)
def update_all_timed_out_subtasks_of_a_client( client_public_key: bytes) -> None: """ Function looks for all subtasks in active state of client. All found subtasks are processed in separate transactions, locked in database, file status is verified (check additional conditions in verify_file_status) and subtask's state is updated in _update_timed_out_subtask """ encoded_client_public_key = b64encode(client_public_key) clients_subtask_list = Subtask.objects.filter( Q(requestor__public_key=encoded_client_public_key) | Q(provider__public_key=encoded_client_public_key), state__in=[state.name for state in Subtask.ACTIVE_STATES], ) # Check if files are uploaded for all clients subtasks. It is checked for all clients subtasks, not only timeouted. for subtask in clients_subtask_list: with transaction.atomic(using='control'): Subtask.objects.select_for_update().filter( subtask_id=subtask.subtask_id) verify_file_status(subtask=subtask, client_public_key=client_public_key) # Subtask may change it's state to passive (RESULT UPLOADED) in verify_file_status. In this case there # is no need to call _update_timed_out_subtask any more. Next_deadline will be set to None, so it is # necessary to check it before checking if deadline is exceeded. if subtask.next_deadline is not None and subtask.next_deadline <= parse_timestamp_to_utc_datetime( get_current_utc_timestamp()): _update_timed_out_subtask(subtask)
def update_timed_out_subtasks(client_public_key: bytes, ): verify_file_status(client_public_key) clients_subtask_list = Subtask.objects.filter( Q(requestor__public_key=b64encode(client_public_key)) | Q(provider__public_key=b64encode(client_public_key)), state__in=[state.name for state in Subtask.ACTIVE_STATES], next_deadline__lte=timezone.now()) for subtask in clients_subtask_list: if subtask.state == Subtask.SubtaskState.FORCING_REPORT.name: # pylint: disable=no-member update_subtask_state( subtask=subtask, state=Subtask.SubtaskState.REPORTED.name, # pylint: disable=no-member ) store_pending_message( response_type=PendingResponse.ResponseType. ForceReportComputedTaskResponse, client_public_key=subtask.provider.public_key_bytes, queue=PendingResponse.Queue.Receive, subtask=subtask, ) store_pending_message( response_type=PendingResponse.ResponseType. VerdictReportComputedTask, client_public_key=subtask.requestor.public_key_bytes, queue=PendingResponse.Queue.ReceiveOutOfBand, subtask=subtask, ) elif subtask.state == Subtask.SubtaskState.FORCING_RESULT_TRANSFER.name: # pylint: disable=no-member update_subtask_state( subtask=subtask, state=Subtask.SubtaskState.FAILED.name, # pylint: disable=no-member ) store_pending_message( response_type=PendingResponse.ResponseType. ForceGetTaskResultFailed, client_public_key=subtask.requestor.public_key_bytes, queue=PendingResponse.Queue.Receive, subtask=subtask, ) elif subtask.state == Subtask.SubtaskState.FORCING_ACCEPTANCE.name: # pylint: disable=no-member update_subtask_state( subtask=subtask, state=Subtask.SubtaskState.ACCEPTED.name, # pylint: disable=no-member ) store_pending_message( response_type=PendingResponse.ResponseType. SubtaskResultsSettled, client_public_key=subtask.provider.public_key_bytes, queue=PendingResponse.Queue.Receive, subtask=subtask, ) store_pending_message( response_type=PendingResponse.ResponseType. SubtaskResultsSettled, client_public_key=subtask.requestor.public_key_bytes, queue=PendingResponse.Queue.ReceiveOutOfBand, subtask=subtask, ) elif subtask.state == Subtask.SubtaskState.ADDITIONAL_VERIFICATION.name: # pylint: disable=no-member locked_subtask = Subtask.objects.select_for_update().get( pk=subtask.pk) task_to_compute = deserialize_message( locked_subtask.task_to_compute.data.tobytes()) # Worker makes a payment from requestor's deposit just like in the forced acceptance use case. core.payments.base.make_force_payment_to_provider( # pylint: disable=no-value-for-parameter requestor_eth_address=task_to_compute. requestor_ethereum_address, provider_eth_address=task_to_compute.provider_ethereum_address, value=task_to_compute.price, payment_ts=get_current_utc_timestamp(), ) update_subtask_state( subtask=locked_subtask, state=Subtask.SubtaskState.ACCEPTED.name, # pylint: disable=no-member ) store_pending_message( response_type=PendingResponse.ResponseType. SubtaskResultsSettled, client_public_key=locked_subtask.provider.public_key_bytes, queue=PendingResponse.Queue.ReceiveOutOfBand, subtask=locked_subtask, ) store_pending_message( response_type=PendingResponse.ResponseType. SubtaskResultsSettled, client_public_key=locked_subtask.requestor.public_key_bytes, queue=PendingResponse.Queue.ReceiveOutOfBand, subtask=locked_subtask, ) logging.log_changes_in_subtask_states( logger, client_public_key, clients_subtask_list.count(), )