-
Notifications
You must be signed in to change notification settings - Fork 72
poll_pending_deposits concurrency #516
Description
I'd like to poll deposits in parallel but it seems Polaris doesn't allow it.
I imagine that's the reason I get so many database is locked errors, but I have no concrete evidence yet.
Looking at this code section from polaris/management/commands/process_pending_deposits.py:
pending_deposits = (
Transaction.objects.filter(
status__in=[
Transaction.STATUS.pending_user_transfer_start,
Transaction.STATUS.pending_external,
],
kind=Transaction.KIND.deposit,
pending_execution_attempt=False,
)
.select_related("asset")
.select_for_update()
)
with django.db.transaction.atomic():
ready_transactions = rri.poll_pending_deposits(pending_deposits)
Transaction.objects.filter(
id__in=[t.id for t in ready_transactions]
).update(pending_execution_attempt=True)
I can see that Polaris selects the items for update, then uses an atomic block to pass the queryset.
Buy if I try, for example, to create multiple threads inside rri.poll_pending_deposits, one to poll each deposit, and do transaction.save() inside that thread, I get some kind of deadlock, code just freezes in the save():
def poll_pending_deposits(
self, pending_deposits: QuerySet, *args: List, **kwargs: Dict
) -> List[Transaction]:
if pending_deposits.count() == 0:
return []
with ThreadPool(pending_deposits.count()) as pool:
rets = pool.map(poll_pending_deposit, pending_deposits)
pool.close()
pool.join()
I might be doing it wrong, maybe I shouldn't be using threads, but since it's a management command, it's not really inside a worker process so it doesn't affect the web server.
How should I poll deposits in parallel?
Thanks