basic waiter support; needs polishing
[wolnelektury.git] / apps / waiter / models.py
1 from os.path import join, abspath, exists
2 from django.db import models
3 from waiter.settings import WAITER_ROOT, WAITER_URL
4 from django.core.urlresolvers import reverse
5
6 class WaitedFile(models.Model):
7     path = models.CharField(max_length=255, unique=True, db_index=True)
8     task = models.CharField(max_length=64, null=True, editable=False)
9     description = models.CharField(max_length=255, null=True, blank=True)
10
11     @staticmethod
12     def abspath(path):
13         abs_path = abspath(join(WAITER_ROOT, path))
14         if not abs_path.startswith(WAITER_ROOT):
15             raise ValueError('Path not inside WAITER_ROOT.')
16         return abs_path
17
18     @classmethod
19     def exists(cls, path):
20         """Returns opened file or None.
21         
22         `path` is relative to WAITER_ROOT.
23         Won't open a path leading outside of WAITER_ROOT.
24         """
25         abs_path = cls.abspath(path)
26         # Pre-fetch objects to avoid minor race condition
27         relevant = [o.id for o in cls.objects.filter(path=path)]
28         print abs_path
29         if exists(abs_path):
30             cls.objects.filter(id__in=relevant).delete()
31             return True
32         else:
33             return False
34
35     @classmethod
36     def order(cls, path, task_creator, description=None):
37         """
38         Returns an URL for the user to follow.
39         If the file is ready, returns download URL.
40         If not, starts preparing it and returns waiting URL.
41         """
42         already = cls.exists(path)
43         if not already:
44             waited, created = cls.objects.get_or_create(path=path)
45             if created:
46                 # TODO: makedirs
47                 waited.task = task_creator(cls.abspath(path))
48                 print waited.task
49                 waited.description = description
50                 waited.save()
51             # TODO: it the task exists, if stale delete, send some mail and restart
52             return reverse("waiter", args=[path])
53         return join(WAITER_URL, path)