async update of annotation matches, fixes deadlock in load_subtitles

This commit is contained in:
j 2016-08-31 18:03:19 +02:00
parent 3913373c9b
commit 1c580a2df7
4 changed files with 23 additions and 18 deletions

View file

@ -134,6 +134,7 @@ class Annotation(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
from .tasks import update_matches from .tasks import update_matches
async = kwargs.pop('async', False)
set_public_id = not self.id or not self.public_id set_public_id = not self.id or not self.public_id
layer = self.get_layer() layer = self.get_layer()
@ -181,10 +182,12 @@ class Annotation(models.Model):
self.clip.save() self.clip.save()
# editAnnotations needs to be in snyc # editAnnotations needs to be in snyc
# load_subtitles can not be in sync
fn = update_matches.delay if async else update_matches
if layer.get('type') == 'place' or layer.get('hasPlaces'): if layer.get('type') == 'place' or layer.get('hasPlaces'):
update_matches(self.id, 'place') fn(self.id, 'place')
if layer.get('type') == 'event' or layer.get('hasEvents'): if layer.get('type') == 'event' or layer.get('hasEvents'):
update_matches(self.id, 'event') fn(self.id, 'event')
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
with transaction.atomic(): with transaction.atomic():

View file

@ -18,7 +18,10 @@ def update_matches(id, type):
elif type == 'event': elif type == 'event':
from event.models import Event as Model from event.models import Event as Model
try:
a = Annotation.objects.get(pk=id) a = Annotation.objects.get(pk=id)
except Annotation.DoesNotExist:
return
a_matches = getattr(a, type == 'place' and 'places' or 'events') a_matches = getattr(a, type == 'place' and 'places' or 'events')
# remove undefined matches that only have this annotation # remove undefined matches that only have this annotation
@ -33,8 +36,7 @@ def update_matches(id, type):
if a.findvalue: if a.findvalue:
names = {} names = {}
for n in Model.objects.all().values('id', 'name', 'alternativeNames'): for n in Model.objects.all().values('id', 'name', 'alternativeNames'):
names[n['id']] = [ox.decode_html(x) names[n['id']] = [ox.decode_html(x) for x in (n['name'],) + n['alternativeNames']]
for x in (n['name'],) + n['alternativeNames']]
value = a.findvalue.lower() value = a.findvalue.lower()
current = [p.id for p in a_matches.all()] current = [p.id for p in a_matches.all()]
@ -54,9 +56,9 @@ def update_matches(id, type):
if not filter(lambda n: n in name_matches, if not filter(lambda n: n in name_matches,
[n.lower() for n in p.get_super_matches()]): [n.lower() for n in p.get_super_matches()]):
new.append(i) new.append(i)
removed = list(filter(lambda p: p not in new, current)) removed = set(filter(lambda p: p not in new, current))
added = list(filter(lambda p: p not in current, new)) added = set(filter(lambda p: p not in current, new))
update = removed + added update = list(removed | added)
if update: if update:
for e in Model.objects.filter(id__in=update): for e in Model.objects.filter(id__in=update):
e.update_matches(Annotation.objects.filter(pk=a.id)) e.update_matches(Annotation.objects.filter(pk=a.id))

View file

@ -1632,7 +1632,7 @@ class Item(models.Model):
value=value, value=value,
user=user user=user
) )
annotation.save() annotation.save(async=True)
# otherwise add empty 5 seconds annotation every minute # otherwise add empty 5 seconds annotation every minute
if not subtitles_added: if not subtitles_added:
start = offset and int(offset / 60) * 60 + 60 or 0 start = offset and int(offset / 60) * 60 + 60 or 0
@ -1647,7 +1647,7 @@ class Item(models.Model):
value='', value='',
user=user user=user
) )
annotation.save() annotation.save(async=True)
offset += f.duration offset += f.duration
# remove left over clips without annotations # remove left over clips without annotations
Clip.objects.filter(item=self, annotations__id=None).delete() Clip.objects.filter(item=self, annotations__id=None).delete()