async def _handle_offchain_reference_i_d_command( self, request_sender_address: str, request: offchain.CommandRequestObject) -> Dict[str, Any]: ref_id_command_object = from_dict(request.command, ReferenceIDCommandObject) # Check if reference ID is duplicate try: self.app.validate_unique_reference_id( ref_id_command_object.reference_id) except ValueError: msg = f"Reference ID {ref_id_command_object.reference_id} already exists" raise command_error(ErrorCode.duplicate_reference_id, msg) # Check if receiver has a diem ID in this wallet try: account = self.app.store.find( Account, diem_id=ref_id_command_object.receiver) except NotFoundError: raise command_error( ErrorCode.invalid_receiver, f"Receiver with Diem ID {ref_id_command_object.receiver} not found", field="receiver", ) self.app.store.create( ReferenceID, account_id=account.id, reference_id=ref_id_command_object.reference_id, ) return to_dict( ReferenceIDCommandResultObject( receiver_address=self.app.diem_account.account_identifier(), ))
def save_command(self, command: offchain.Command) -> None: """save command locks prior command by reference id, validate and save new command. in a production implementation, the lock should be database / distributed lock to ensure atomic process(read and write) command by the reference id. """ lock = self.lock(command.reference_id()) if not lock.acquire(blocking=False): msg = f"command(reference_id={command.reference_id()}) is locked" raise offchain.command_error(offchain.ErrorCode.conflict, msg) try: prior = self.saved_commands.get(command.reference_id()) if command == prior: return command.validate(prior) self.saved_commands[command.reference_id()] = command if command.is_inbound(): self._enqueue_follow_up_action(command) else: # outbound self.task_queue.append(lambda app: app._send_request(command)) finally: lock.release()