def check_past_payment(payments_root, payment_cycle): payment_dir = payment_dir_c(payments_root, payment_cycle) # legacy payments if os.path.isdir(payment_dir): return "Payment directory for cycle {} is present. No payment will be run for the cycle. Check '{}'".format( payment_cycle, payment_dir) # new payments are reported to csv files payment_file = payment_report_file_path(payments_root, payment_cycle, 0) if os.path.isfile(payment_file): return "Payment report for cycle {} is present. No payment will be run for the cycle. Check '{}'".format( payment_cycle, payment_file) payment_file_failed = payment_report_file_path(payments_root, payment_cycle, 1) if os.path.isfile(payment_file_failed): return "Payment failed report for cycle {} is present. No payment will be run for the cycle. Check '{}'".format( payment_cycle, payment_file_failed) payment_file_failed_bush = get_busy_file(payment_file_failed) if os.path.isfile(payment_file_failed_bush): return "Busy payment failed report for cycle {} is present. No payment will be run for the cycle. Check '{}'".format( payment_cycle, payment_file_failed_bush) return None # which means No past payment
def create_payment_report(self, nb_failed, nb_injected, payment_logs, payment_cycle, total_attempts): logger.info("Processing completed for {} payment items{}.".format( len(payment_logs), ", {} failed".format(nb_failed) if nb_failed > 0 else "")) report_file = payment_report_file_path(self.payments_dir, payment_cycle, nb_failed) CsvPaymentFileParser().write(report_file, payment_logs) logger.info("Payment report is created at '{}'".format(report_file)) for pl in payment_logs: logger.debug( "Payment done for address %s type %s amount {:>8.2f} paid %s". format(pl.amount / MUTEZ), pl.address, pl.type, pl.paid) if self.publish_stats and not self.dry_run and ( not self.args or is_mainnet(self.args.network)): stats_dict = self.create_stats_dict(nb_failed, nb_injected, payment_cycle, payment_logs, total_attempts) # publish stat_publish(stats_dict) return report_file
def test_retry_failed_payments(self): payment_queue = queue.Queue(100) retry_producer = RetryProducer(payment_queue, _DummyRpcRewardApi(), _TestPaymentProducer(), TEST_REPORT_TEMP_DIR) retry_producer.retry_failed_payments() self.assertEqual(1, len(payment_queue.queue)) payment_batch = payment_queue.get() self.assertEqual(10, payment_batch.cycle) self.assertEqual(31, len(payment_batch.batch)) self.assertEqual(5, len([row for row in payment_batch.batch if row.paid == PaymentStatus.FAIL])) nw = dict({'BLOCK_TIME_IN_SEC': 64}) payment_consumer = self.create_consumer(nw, payment_queue) payment_consumer._consume_batch(payment_batch) success_report = payment_report_file_path(TEST_REPORT_TEMP_DIR, 10, 0) self.assertTrue(os.path.isfile(success_report)) success_report_rows = CsvPaymentFileParser().parse(success_report, 10) nb_success = len([row for row in success_report_rows if row.paid == PaymentStatus.PAID]) nb_hash_xxx_op_hash = len([row for row in success_report_rows if row.hash == 'xxx_op_hash']) self.assertEqual(31, nb_success) self.assertEqual(5, nb_hash_xxx_op_hash)
def clean_failed_payment_reports(self, payment_cycle): # 1- generate path of a assumed failure report file # if it exists, remove it failure_report_file = payment_report_file_path(self.payments_dir, payment_cycle, 1) if os.path.isfile(failure_report_file): os.remove(failure_report_file) # 2- generate path of a assumed busy failure report file # if it exists, remove it failure_report_busy_file = get_busy_file(failure_report_file) if os.path.isfile(failure_report_busy_file): os.remove(failure_report_busy_file)
def test_retry_failed_payments(self): """This is a test about retrying failed operations. Input is a past payment report which contains 31 payment items, 26 of them were successful and 5 of them were failed. The final report should report 31 successful transactions. """ payment_queue = queue.Queue(100) retry_producer = RetryProducer( payment_queue, _DummyRpcRewardApi(), _TestPaymentProducer(), TEST_REPORT_TEMP_DIR, 10, ) retry_producer.retry_failed_payments() self.assertEqual(1, len(payment_queue.queue)) payment_batch = payment_queue.get() self.assertEqual(10, payment_batch.cycle) self.assertEqual(31, len(payment_batch.batch)) self.assertEqual( 5, len([ row for row in payment_batch.batch if row.paid == PaymentStatus.FAIL ]), ) nw = dict({"MINIMAL_BLOCK_DELAY": 30}) payment_consumer = self.create_consumer(nw, payment_queue) payment_consumer._consume_batch(payment_batch) success_report = payment_report_file_path(TEST_REPORT_TEMP_DIR, 10, 0) self.assertTrue(os.path.isfile(success_report)) success_report_rows = CsvPaymentFileParser().parse(success_report, 10) success_count = len([row for row in success_report_rows]) hash_xxx_op_count = len( [row for row in success_report_rows if row.hash == "xxx_op_hash"]) failed_reports_count = len([ file for file in os.listdir( os.path.join(TEST_REPORT_TEMP_DIR, "failed")) if os.path.isfile(file) ]) # Success is defined when the transactions are saved in the done folder self.assertEqual(31, success_count) self.assertEqual(5, hash_xxx_op_count) self.assertEqual(0, failed_reports_count)
def create_payment_report(self, nb_failed, payment_logs, payment_cycle): report_file = payment_report_file_path(self.payments_dir, payment_cycle, nb_failed) with open(report_file, "w") as f: csv_writer = csv.writer(f, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL) csv_writer.writerow(["address", "type", "payment", "hash", "paid"]) for payment_item in payment_logs: # write row to csv file csv_writer.writerow( [payment_item.address, payment_item.type, "{0:f}".format(payment_item.payment), payment_item.hash, "1" if payment_item.paid else "0"]) return report_file
def create_payment_report(self, nb_failed, payment_logs, payment_cycle, already_paid_items): logger.info("Processing completed for {} payment items{}.".format( len(payment_logs), ", {} failed".format(nb_failed) if nb_failed > 0 else "", )) logger.debug("Adding {} already paid items to the report".format( len(already_paid_items))) payouts = already_paid_items + payment_logs successful_payouts = [ x for x in payouts if x.paid != PaymentStatus.FAIL ] unsuccessful_payouts = [ x for x in payouts if x.paid == PaymentStatus.FAIL ] report_file = payment_report_file_path(self.payments_dir, payment_cycle, 0) CsvPaymentFileParser().write(report_file, successful_payouts) logger.info("Payment report is created at '{}'".format(report_file)) if nb_failed > 0: report_file = payment_report_file_path(self.payments_dir, payment_cycle, nb_failed) CsvPaymentFileParser().write(report_file, unsuccessful_payouts) logger.info( "Payment report is created at '{}'".format(report_file)) for pl in payment_logs: logger.debug( "Payment done for address {:s} type {:s} amount {:>10.6f} paid {:s}" .format(pl.address, pl.type, pl.amount / MUTEZ, pl.paid)) return report_file
def create_payment_report(self, nb_failed, payment_logs, payment_cycle): logger.info("Processing completed for {} payment items{}." .format(len(payment_logs), ", {} failed".format(nb_failed) if nb_failed > 0 else "")) report_file = payment_report_file_path(self.payments_dir, payment_cycle, nb_failed) CsvPaymentFileParser().write(report_file, payment_logs) logger.info("Payment report is created at '{}'".format(report_file)) for pl in payment_logs: logger.debug("Payment done for address {:s} type {:s} amount {:>10.6f} paid {:s}" .format(pl.address, pl.type, pl.amount / MUTEZ, pl.paid)) return report_file
def clean_failed_payment_reports(self, payment_cycle, success): # 1- generate path of a assumed failure report file # if it exists and payments were successful, remove it failure_report_file = payment_report_file_path(self.payments_dir, payment_cycle, 1) if success and os.path.isfile(failure_report_file): os.remove(failure_report_file) # 2- generate path of a assumed busy failure report file # if it exists, remove it ### # remove file failed/cycle.csv.BUSY file; # - if payment attempt was successful it is not needed anymore, # - if payment attempt was un-successful, new failedY/cycle.csv is already created. # Thus failed/cycle.csv.BUSY file is not needed and removing it is fine. failure_report_busy_file = get_busy_file(failure_report_file) if os.path.isfile(failure_report_busy_file): os.remove(failure_report_busy_file)