Convert order cleaning task into admin command

This commit is contained in:
Reckless_Satoshi 2022-01-17 10:11:44 -08:00
parent eddd4674f6
commit 0db73c7c82
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
6 changed files with 87 additions and 68 deletions

View File

@ -113,6 +113,7 @@ class Logics():
elif order.status == Order.Status.WFB:
order.status = Order.Status.EXP
cls.cancel_bond(order.maker_bond)
order.maker = None
order.taker = None
order.save()
@ -127,6 +128,7 @@ class Logics():
return True
elif order.status == Order.Status.TAK:
cls.cancel_bond(order.taker_bond)
cls.kick_taker(order)
return True
@ -149,6 +151,7 @@ class Logics():
# If maker is seller, settle the bond and order goes to expired
if maker_is_seller:
cls.settle_bond(order.maker_bond)
cls.return_bond(order.taker_bond)
order.status = Order.Status.EXP
order.maker = None
order.taker = None
@ -167,19 +170,20 @@ class Logics():
elif order.status == Order.Status.WFI:
# The trade could happen without a buyer invoice. However, this user
# is most likely AFK since he did not submit an invoice; will most
# likely desert the contract as well.
# is likely AFK since he did not submit an invoice; will probably
# desert the contract as well.
maker_is_buyer = cls.is_buyer(order, order.maker)
# If maker is buyer, settle the bond and order goes to expired
if maker_is_buyer:
cls.settle_bond(order.maker_bond)
cls.return_bond(order.taker_bond)
order.status = Order.Status.EXP
order.maker = None
order.taker = None
order.save()
return True
# If maker is seller, settle the taker's bond order goes back to public
# If maker is seller settle the taker's bond, order goes back to public
else:
cls.settle_bond(order.taker_bond)
order.status = Order.Status.PUB
@ -203,14 +207,13 @@ class Logics():
profile.penalty_expiration = timezone.now() + timedelta(seconds=PENALTY_TIMEOUT)
profile.save()
# Delete the taker_bond payment request, and make order public again
if LNNode.cancel_return_hold_invoice(order.taker_bond.payment_hash):
order.status = Order.Status.PUB
order.taker = None
order.taker_bond = None
order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB])
order.save()
return True
# Make order public again
order.status = Order.Status.PUB
order.taker = None
order.taker_bond = None
order.expires_at = order.created_at + timedelta(seconds=Order.t_to_expire[Order.Status.PUB])
order.save()
return True
@classmethod
def open_dispute(cls, order, user=None):
@ -369,6 +372,7 @@ class Logics():
LNPayment "order.taker_bond" is deleted() '''
elif order.status == Order.Status.TAK and order.taker == user:
# adds a timeout penalty
cls.cancel_bond(order.taker_bond)
cls.kick_taker(order)
return True, None
@ -495,6 +499,7 @@ class Logics():
# Do not gen and kick out the taker if order is older than expiry time
if order.expires_at < timezone.now():
cls.cancel_bond(order.taker_bond)
cls.kick_taker(order)
return False, {'bad_request':'Invoice expired. You did not confirm taking the order in time.'}
@ -615,9 +620,31 @@ class Logics():
def return_bond(bond):
'''returns a bond'''
if LNNode.cancel_return_hold_invoice(bond.payment_hash):
if bond == None:
return
try:
LNNode.cancel_return_hold_invoice(bond.payment_hash)
bond.status = LNPayment.Status.RETNED
return True
except Exception as e:
if 'invoice already settled' in str(e):
bond.status = LNPayment.Status.SETLED
return True
def cancel_bond(bond):
'''cancel a bond'''
# Same as return bond, but used when the invoice was never accepted
if bond == None:
return True
try:
LNNode.cancel_return_hold_invoice(bond.payment_hash)
bond.status = LNPayment.Status.CANCEL
return True
except Exception as e:
if 'invoice already settled' in str(e):
bond.status = LNPayment.Status.SETLED
return True
def pay_buyer_invoice(order):
''' Pay buyer invoice'''

View File

@ -0,0 +1,41 @@
from django.core.management.base import BaseCommand, CommandError
import time
from api.models import Order
from api.logics import Logics
from django.utils import timezone
class Command(BaseCommand):
help = 'Follows all active hold invoices'
# def add_arguments(self, parser):
# parser.add_argument('debug', nargs='+', type=boolean)
def handle(self, *args, **options):
''' Continuously checks order expiration times for 1 hour. If order
has expires, it calls the logics module for expiration handling.'''
do_nothing = [Order.Status.DEL, Order.Status.UCA,
Order.Status.EXP, Order.Status.FSE,
Order.Status.DIS, Order.Status.CCA,
Order.Status.PAY, Order.Status.SUC,
Order.Status.FAI, Order.Status.MLD,
Order.Status.TLD]
while True:
time.sleep(5)
queryset = Order.objects.exclude(status__in=do_nothing)
queryset = queryset.filter(expires_at__lt=timezone.now()) # expires at lower than now
debug = {}
debug['num_expired_orders'] = len(queryset)
debug['expired_orders'] = []
for idx, order in enumerate(queryset):
context = str(order)+ " was "+ Order.Status(order.status).label
if Logics.order_expires(order): # Order send to expire here
debug['expired_orders'].append({idx:context})
self.stdout.write(str(timezone.now()))
self.stdout.write(str(debug))

View File

@ -1,7 +1,6 @@
from distutils.log import debug
from re import L
from xmlrpc.client import boolean
from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone
from api.lightning.node import LNNode
from decouple import config
from base64 import b64decode
@ -53,9 +52,9 @@ class Command(BaseCommand):
try:
request = LNNode.invoicesrpc.LookupInvoiceMsg(payment_hash=bytes.fromhex(hold_lnpayment.payment_hash))
response = stub.LookupInvoiceV2(request, metadata=[('macaroon', MACAROON.hex())])
hold_lnpayment.status = lnd_state_to_lnpayment_status[response.state]
# If it fails at finding the invoice it has definetely been canceled.
# If it fails at finding the invoice it has been canceled.
# On RoboSats DB we make a distinction between cancelled and returned (LND does not)
except:
hold_lnpayment.status = LNPayment.Status.CANCEL
@ -76,9 +75,10 @@ class Command(BaseCommand):
'old_status': old_status,
'new_status': new_status,
}})
debug['time']=time.time()-t0
self.stdout.write(str(debug))
self.stdout.write(str(timezone.now())+str(debug))

View File

@ -30,50 +30,6 @@ def users_cleansing():
'num_deleted': len(deleted_users),
'deleted_users': deleted_users,
}
return results
@shared_task(name="orders_expire")
def orders_expire(rest_secs):
'''
Continuously checks order expiration times for 1 hour. If order
has expires, it calls the logics module for expiration handling.
'''
import time
from .models import Order
from .logics import Logics
from datetime import timedelta
from django.utils import timezone
now = timezone.now()
end_time = now + timedelta(minutes=60)
context = []
while now < end_time:
queryset = Order.objects.exclude(status=Order.Status.EXP).exclude(status=Order.Status.UCA).exclude(status= Order.Status.CCA)
queryset = queryset.filter(expires_at__lt=now) # expires at lower than now
for order in queryset:
try: # TODO Fix, it might fail if returning an already returned bond.
info = str(order)+ " was "+ Order.Status(order.status).label
if Logics.order_expires(order): # Order send to expire here
context.append(info)
except:
pass
# Allow for some thread rest.
time.sleep(rest_secs)
# Update 'now' for a new loop
now = timezone.now()
results = {
'num_expired': len(context),
'expired_orders_context': context,
'rest_param': rest_secs,
}
return results
@shared_task(name='follow_send_payment')

View File

@ -5,7 +5,7 @@ import numpy as np
market_cache = {}
# @ring.dict(market_cache, expire=5) #keeps in cache for 5 seconds
@ring.dict(market_cache, expire=5) #keeps in cache for 5 seconds
def get_exchange_rates(currencies):
'''
Params: list of currency codes.

View File

@ -39,11 +39,6 @@ app.conf.beat_schedule = {
'task': 'cache_external_market_prices',
'schedule': timedelta(seconds=60),
},
'orders_expire': { # Continuous order expire removal (1 hour long process, every hour reports results)
'task': 'orders_expire',
'schedule': timedelta(hours=1),
'args': [5], # Rest between checks (secs)
},
}
app.conf.timezone = 'UTC'