Custom ManyRelatedManager?

173 views
Skip to first unread message

Andreas Hasenkopf

unread,
Aug 5, 2019, 11:28:03 AM8/5/19
to django...@googlegroups.com
Hi everyone,

on StackOverflow the question on how to overload the ManyRelatedManager
for ManyToMany relations has been asked multiple times, but none of the
answers seemed to be satisfying. So I would like to talk about it with you.

## My problem

The backend of my Django app gets triggered by events of a RabbitMQ
server. After pre-filtering the backend dispatches a Celery task to
process data from a remote system to which the event belongs.
Unfortunately events for the same object can arrive in bursts leading to
multiple Celery tasks processing the same objects almost simultaneously.

## My solution so far

In my custom ModelManager I explicitly use Postgres Advisory locks, e.g.
in `get_or_create`, which is working really well.

## Missing link

As my data model contains quite a few ManyToMany relations I would
prefer to define the usage of locks only once in the methods of a class
derived from ManyRelatedManager, e.g. in the `set` method.
So far I was unable to figure out how to do that. Any suggestions?

## Example

To give you a better understanding let's look at some code excerpts:

```
class ExtendedQuerySet(QuerySet):
def get_or_create(self, defaults=None, _deadlocks=5, **kwargs):
try:
with advisory_lock(self.model.__name__):
return super().get_or_create(defaults, **kwargs)
except DeadlockDetected as error:
# retry in a second...
...

class ExtendedManager(Manager.from_queryset(ExtendedQuerySet)):
pass

class Reference(models.Model):
# removed field definitions

objects = ExtendedManager()

class Request(models.Model):
# removed some field definitions
references = models.ManyToManyField(Reference)

objects = ExtendedManager()
```

If two Celery tasks try to call e.g.
`Reference.objects.get_o_create(...)` at the same time, the locks work
as expected. But e.g. calling `request.references.set(...)` can fail
(unique constraint violation) in the second Celery task due to a race
condition, that I would like to avoid using locks.


Thanks for your help.


Andreas

--
Andreas Hasenkopf
Phone: +49 151 11728439
Homepage: https://hasenkopf.xyz
GPG Pub Key: http://goo.gl/4mOsM

signature.asc
Reply all
Reply to author
Forward
0 new messages