1 from models import URLtoTaskID
2 from djcelery.models import TaskMeta
3 from django.template.loader import render_to_string
4
5 """
6 NOTES:
7 url entries should be unique -- a single url maps to a single task_id in a one-to-one fashion
8 this strategy allows the asynchronous models to serve as a cache for those apps that wish to use it as such
9
10 check_status_or_begin does not check to see if process is already complete
11 if the caller wants the process to be run ONLY IF it hasn't been completed already,
12 the caller should check process_is_complete instead
13
14 process_is_running (called on its own or from check_status_or_begin or process_is_running_or_complete) checks
15 only if status == 'STARTED', this seems like the safest strategy although it does have it's shortcomings.
16 When a task is triggered, it is stored in the celery_taskmeta table with status == PENDING, as soon as
17 a worker is assigned to that task, the status becomes STARTED, when the task is complete, status becomes SUCCESS.
18 If something goes wrong during the STARTED phase (celeryd is shut down, etc), then status becomes FAILURE.
19 If celeryd is not communicating with ghettoq, or not running at all, then the status will remain as PENDING.
20 If we assume that PENDING means STARTED, then we may be mislead into thinking a task is being processed,
21 when in fact it is sitting idle. This may only become apparent after waiting way-too-long for the task
22 to complete.
23 If we only check for STARTED, then each time the task is requested, we will add a new task to the queue. This
24 may back up the queue, but only in situations when there is something wrong to begin with. This will also
25 likely alert the user (or the developer) more immediately that something has gone wrong with celeryd (or ghettoq,
26 or whatever) since the returned statement will be something like 'the process has begun', even with subsequent
27 requests which should have changed the statement to something like 'the process is already running'. There is
28 also the slight chance that a task will be requested in such quick succession that a worker will not yet be assigned
29 to that task and the status will still be PENDING, in which case a new task will be added to the queue. This seems
30 a small price to pay for the more immediate recognition that there is indeed a problem. As the developer in this
31 case, I'd rather get the impression of a False Negative (thinking there may be a problem, when in fact there is none),
32 than a False Positive (given the impression that everything is fine, when in fact there is a problem). Also, the
33 user is more likely to notice a problem sooner in the case when there is a hint in the returned statement (that
34 the process has begun...yet again), than in the case when they must figure out there is a problem only because
35 the process is taking an inordinately long time (in many cases this could mean hours rather than minutes).
36 """
37
38 '''
39 begin_process starts the background process
40 if the process has already been run, the related URLtoTaskID entry is cleared and re-calculated
41 if the process is currently running, the related URLtoTaskID entry is cleared, and the process is started again
42 (in this case more than one identical process may be running at the same time -- to prevent this see NOTES above)
43 called by check_status_or_begin
44 '''
45 -def __begin_process(task_method, task_args=(), task_kwargs={}, polling_url=None, cache_results=True):
56
57 '''
58 check_status_or_begin
59 if the user has supplied neither the polling_url nor the task_id, it is assumed that they wish to start the process
60 (since no process_is_running check can be made without a process identifier anyway)
61 otherwise, if check_running is left to its default value of True, then a check will be made to see if the process is
62 already running, in which case a related message is returned to the user and the process is not re-started
63 if the process is not already running (or the user doesn't wish to check for that case), then the process will be
64 added to the queue, and a message indicating the process has begun will be returned to the user
65 if the process had already completed (status == SUCCESS rather than STARTED), it will be run again
66 if the caller wants the process to be run ONLY IF it hasn't been completed already,
67 the caller should check process_is_complete instead
68 '''
69 -def check_status_or_begin(task_method, task_args=(), task_kwargs={}, polling_url=None, task_id=None, check_running=True, cache_results=True):
79
80
86
87
94
95
96
103
104
111
112
119
120
127
128
136
137
144
145
146
157