mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 10:56:24 +00:00
Convert order cleaning task into admin command
This commit is contained in:
parent
eddd4674f6
commit
0db73c7c82
@ -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'''
|
||||
|
41
api/management/commands/clean_orders.py
Normal file
41
api/management/commands/clean_orders.py
Normal 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))
|
@ -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))
|
||||
|
||||
|
||||
|
44
api/tasks.py
44
api/tasks.py
@ -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')
|
||||
|
@ -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.
|
||||
|
@ -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'
|
Loading…
Reference in New Issue
Block a user