mirror of
https://github.com/nikdoof/test-auth.git
synced 2025-12-14 06:42:16 +00:00
Added django_cron
This commit is contained in:
35
django_cron/.svn/all-wcprops
Normal file
35
django_cron/.svn/all-wcprops
Normal file
@@ -0,0 +1,35 @@
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 34
|
||||
/svn/!svn/ver/32/trunk/django_cron
|
||||
END
|
||||
base.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 42
|
||||
/svn/!svn/ver/32/trunk/django_cron/base.py
|
||||
END
|
||||
__init__.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 46
|
||||
/svn/!svn/ver/16/trunk/django_cron/__init__.py
|
||||
END
|
||||
signals.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 44
|
||||
/svn/!svn/ver/8/trunk/django_cron/signals.py
|
||||
END
|
||||
models.py
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 44
|
||||
/svn/!svn/ver/16/trunk/django_cron/models.py
|
||||
END
|
||||
README.txt
|
||||
K 25
|
||||
svn:wc:ra_dav:version-url
|
||||
V 45
|
||||
/svn/!svn/ver/16/trunk/django_cron/README.txt
|
||||
END
|
||||
198
django_cron/.svn/entries
Normal file
198
django_cron/.svn/entries
Normal file
@@ -0,0 +1,198 @@
|
||||
9
|
||||
|
||||
dir
|
||||
32
|
||||
http://django-cron.googlecode.com/svn/trunk/django_cron
|
||||
http://django-cron.googlecode.com/svn
|
||||
|
||||
|
||||
|
||||
2009-10-28T14:21:55.477932Z
|
||||
32
|
||||
jim.mixtake@gmail.com
|
||||
|
||||
|
||||
svn:special svn:externals svn:needs-lock
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
857153d3-df44-0410-aaef-ab1f86cdcd94
|
||||
|
||||
base.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-02-20T20:20:49.000000Z
|
||||
afab29654c6380b9c2ecd00fae92522c
|
||||
2009-10-28T14:21:55.477932Z
|
||||
32
|
||||
jim.mixtake@gmail.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4064
|
||||
|
||||
__init__.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-02-20T20:20:49.000000Z
|
||||
8492cf50017e7eff784fdfbe0cc8b3ba
|
||||
2009-06-02T13:59:46.682354Z
|
||||
16
|
||||
Jim.mixtake
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2566
|
||||
|
||||
signals.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-02-20T20:20:49.000000Z
|
||||
8e3eba63f720bd6d830fc89d7d6be693
|
||||
2008-10-26T12:02:48.705921Z
|
||||
5
|
||||
digitalxero
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1192
|
||||
|
||||
models.py
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-02-20T20:20:49.000000Z
|
||||
329f05f78f78465d4acfba95c42d32f7
|
||||
2009-06-02T13:59:46.682354Z
|
||||
16
|
||||
Jim.mixtake
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1632
|
||||
|
||||
README.txt
|
||||
file
|
||||
|
||||
|
||||
|
||||
|
||||
2010-02-20T20:20:49.000000Z
|
||||
801836776103697e20d5d9a9446cb28b
|
||||
2009-06-02T13:59:46.682354Z
|
||||
16
|
||||
Jim.mixtake
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1953
|
||||
|
||||
1
django_cron/.svn/format
Normal file
1
django_cron/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
9
|
||||
54
django_cron/.svn/text-base/README.txt.svn-base
Normal file
54
django_cron/.svn/text-base/README.txt.svn-base
Normal file
@@ -0,0 +1,54 @@
|
||||
= How to install djang-cron =
|
||||
|
||||
1. Put 'django_cron' into your python path
|
||||
|
||||
2. Add 'django_cron' to INSTALLED_APPS in your settings.py file
|
||||
|
||||
3. Add the following code to the beginning of your urls.py file (just after the imports):
|
||||
|
||||
import django_cron
|
||||
django_cron.autodiscover()
|
||||
|
||||
|
||||
4. Create a file called 'cron.py' inside each installed app that you want to add a recurring job to. The app must be installed via the INSTALLED_APPS in your settings.py or the autodiscover will not find it.
|
||||
|
||||
=== Important note ===
|
||||
|
||||
If you are using mod_python, you need to make sure your server is set up to server more than one request per instance, Otherwise it will kill django-cron before the tasks get started. The specific line to look for is in your 'httpd.conf' file:
|
||||
|
||||
|
||||
# THIS IS BAD!!! IT WILL CRIPPLE DJANGO-CRON
|
||||
MaxRequestsPerChild 1
|
||||
|
||||
|
||||
Change it to a value that is large enough that your cron jobs will get run at least once per instance. We're working on resolving this issue without dictating your server config.
|
||||
|
||||
In the meantime, django_cron is best used to execute tasks that occur relatively often (at least once an hour). Try setting MaxRequestsPerChild to 50, 100, or 200
|
||||
|
||||
# Depending on traffic, and your server config, a number between 50 and 500 is probably good
|
||||
# Note: the higher this number, the more memory django is likely to use. Be careful on shared hosting
|
||||
MaxRequestsPerChild 100
|
||||
|
||||
|
||||
== Example cron.py ==
|
||||
|
||||
from django_cron import cronScheduler, Job
|
||||
|
||||
# This is a function I wrote to check a feedback email address
|
||||
# and add it to our database. Replace with your own imports
|
||||
from MyMailFunctions import check_feedback_mailbox
|
||||
|
||||
class CheckMail(Job):
|
||||
"""
|
||||
Cron Job that checks the lgr users mailbox and adds any
|
||||
approved senders' attachments to the db
|
||||
"""
|
||||
|
||||
# run every 300 seconds (5 minutes)
|
||||
run_every = 300
|
||||
|
||||
def job(self):
|
||||
# This will be executed every 5 minutes
|
||||
check_feedback_mailbox()
|
||||
|
||||
cronScheduler.register(CheckMail)
|
||||
63
django_cron/.svn/text-base/__init__.py.svn-base
Normal file
63
django_cron/.svn/text-base/__init__.py.svn-base
Normal file
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
Copyright (c) 2007-2008, Dj Gilcrease
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
from base import Job, cronScheduler
|
||||
|
||||
def autodiscover():
|
||||
"""
|
||||
Auto-discover INSTALLED_APPS cron.py modules and fail silently when
|
||||
not present. This forces an import on them to register any cron jobs they
|
||||
may want.
|
||||
"""
|
||||
import imp
|
||||
from django.conf import settings
|
||||
|
||||
for app in settings.INSTALLED_APPS:
|
||||
# For each app, we need to look for an cron.py inside that app's
|
||||
# package. We can't use os.path here -- recall that modules may be
|
||||
# imported different ways (think zip files) -- so we need to get
|
||||
# the app's __path__ and look for cron.py on that path.
|
||||
|
||||
# Step 1: find out the app's __path__ Import errors here will (and
|
||||
# should) bubble up, but a missing __path__ (which is legal, but weird)
|
||||
# fails silently -- apps that do weird things with __path__ might
|
||||
# need to roll their own cron registration.
|
||||
try:
|
||||
app_path = __import__(app, {}, {}, [app.split('.')[-1]]).__path__
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
# Step 2: use imp.find_module to find the app's admin.py. For some
|
||||
# reason imp.find_module raises ImportError if the app can't be found
|
||||
# but doesn't actually try to import the module. So skip this app if
|
||||
# its admin.py doesn't exist
|
||||
try:
|
||||
imp.find_module('cron', app_path)
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
# Step 3: import the app's cron file. If this has errors we want them
|
||||
# to bubble up.
|
||||
__import__("%s.cron" % app)
|
||||
|
||||
# Step 4: once we find all the cron jobs, start the cronScheduler
|
||||
cronScheduler.execute()
|
||||
127
django_cron/.svn/text-base/base.py.svn-base
Normal file
127
django_cron/.svn/text-base/base.py.svn-base
Normal file
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
Copyright (c) 2007-2008, Dj Gilcrease
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
import cPickle
|
||||
from threading import Timer
|
||||
from datetime import datetime
|
||||
|
||||
from django.dispatch import dispatcher
|
||||
from django.conf import settings
|
||||
|
||||
from signals import cron_done
|
||||
import models
|
||||
|
||||
# how often to check if jobs are ready to be run (in seconds)
|
||||
# in reality if you have a multithreaded server, it may get checked
|
||||
# more often that this number suggests, so keep an eye on it...
|
||||
# default value: 300 seconds == 5 min
|
||||
polling_frequency = getattr(settings, "CRON_POLLING_FREQUENCY", 300)
|
||||
|
||||
class Job(object):
|
||||
# 86400 seconds == 24 hours
|
||||
run_every = 86400
|
||||
|
||||
def run(self, *args, **kwargs):
|
||||
self.job()
|
||||
cron_done.send(sender=self, *args, **kwargs)
|
||||
|
||||
def job(self):
|
||||
"""
|
||||
Should be overridden (this way is cleaner, but the old way - overriding run() - will still work)
|
||||
"""
|
||||
pass
|
||||
|
||||
class CronScheduler(object):
|
||||
def register(self, job_class, *args, **kwargs):
|
||||
"""
|
||||
Register the given Job with the scheduler class
|
||||
"""
|
||||
|
||||
job_instance = job_class()
|
||||
|
||||
if not isinstance(job_instance, Job):
|
||||
raise TypeError("You can only register a Job not a %r" % job_class)
|
||||
|
||||
job, created = models.Job.objects.get_or_create(name=str(job_instance.__class__))
|
||||
if created:
|
||||
job.instance = cPickle.dumps(job_instance)
|
||||
job.args = cPickle.dumps(args)
|
||||
job.kwargs = cPickle.dumps(kwargs)
|
||||
job.run_frequency = job_instance.run_every
|
||||
job.save()
|
||||
|
||||
def execute(self):
|
||||
"""
|
||||
Queue all Jobs for execution
|
||||
"""
|
||||
status, created = models.Cron.objects.get_or_create(pk=1)
|
||||
|
||||
# This is important for 2 reasons:
|
||||
# 1. It keeps us for running more than one instance of the
|
||||
# same job at a time
|
||||
# 2. It reduces the number of polling threads because they
|
||||
# get killed off if they happen to check while another
|
||||
# one is already executing a job (only occurs with
|
||||
# multi-threaded servers)
|
||||
if status.executing:
|
||||
return
|
||||
|
||||
status.executing = True
|
||||
try:
|
||||
status.save()
|
||||
except:
|
||||
# this will fail if you're debugging, so we want it
|
||||
# to fail silently and start the timer again so we
|
||||
# can pick up where we left off once debugging is done
|
||||
Timer(polling_frequency, self.execute).start()
|
||||
return
|
||||
|
||||
jobs = models.Job.objects.all()
|
||||
for job in jobs:
|
||||
if job.queued:
|
||||
time_delta = datetime.now() - job.last_run
|
||||
if (time_delta.seconds + 86400*time_delta.days) > job.run_frequency:
|
||||
inst = cPickle.loads(str(job.instance))
|
||||
args = cPickle.loads(str(job.args))
|
||||
kwargs = cPickle.loads(str(job.kwargs))
|
||||
|
||||
try:
|
||||
inst.run(*args, **kwargs)
|
||||
job.last_run = datetime.now()
|
||||
job.save()
|
||||
|
||||
except Exception:
|
||||
# if the job throws an error, just remove it from
|
||||
# the queue. That way we can find/fix the error and
|
||||
# requeue the job manually
|
||||
job.queued = False
|
||||
job.save()
|
||||
|
||||
status.executing = False
|
||||
status.save()
|
||||
|
||||
# Set up for this function to run again
|
||||
Timer(polling_frequency, self.execute).start()
|
||||
|
||||
|
||||
cronScheduler = CronScheduler()
|
||||
|
||||
39
django_cron/.svn/text-base/models.py.svn-base
Normal file
39
django_cron/.svn/text-base/models.py.svn-base
Normal file
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
Copyright (c) 2007-2008, Dj Gilcrease
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
from django.db import models
|
||||
from datetime import datetime
|
||||
|
||||
class Job(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
|
||||
# time between job runs (in seconds) // default: 1 day
|
||||
run_frequency = models.PositiveIntegerField(default=86400)
|
||||
last_run = models.DateTimeField(default=datetime.now())
|
||||
|
||||
instance = models.TextField()
|
||||
args = models.TextField()
|
||||
kwargs = models.TextField()
|
||||
queued = models.BooleanField(default=True)
|
||||
|
||||
class Cron(models.Model):
|
||||
executing = models.BooleanField(default=False)
|
||||
26
django_cron/.svn/text-base/signals.py.svn-base
Normal file
26
django_cron/.svn/text-base/signals.py.svn-base
Normal file
@@ -0,0 +1,26 @@
|
||||
"""
|
||||
Copyright (c) 2007-2008, Dj Gilcrease
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
from django.dispatch import Signal
|
||||
|
||||
cron_queued = Signal()
|
||||
cron_done = Signal(providing_args=["job"])
|
||||
54
django_cron/README.txt
Normal file
54
django_cron/README.txt
Normal file
@@ -0,0 +1,54 @@
|
||||
= How to install djang-cron =
|
||||
|
||||
1. Put 'django_cron' into your python path
|
||||
|
||||
2. Add 'django_cron' to INSTALLED_APPS in your settings.py file
|
||||
|
||||
3. Add the following code to the beginning of your urls.py file (just after the imports):
|
||||
|
||||
import django_cron
|
||||
django_cron.autodiscover()
|
||||
|
||||
|
||||
4. Create a file called 'cron.py' inside each installed app that you want to add a recurring job to. The app must be installed via the INSTALLED_APPS in your settings.py or the autodiscover will not find it.
|
||||
|
||||
=== Important note ===
|
||||
|
||||
If you are using mod_python, you need to make sure your server is set up to server more than one request per instance, Otherwise it will kill django-cron before the tasks get started. The specific line to look for is in your 'httpd.conf' file:
|
||||
|
||||
|
||||
# THIS IS BAD!!! IT WILL CRIPPLE DJANGO-CRON
|
||||
MaxRequestsPerChild 1
|
||||
|
||||
|
||||
Change it to a value that is large enough that your cron jobs will get run at least once per instance. We're working on resolving this issue without dictating your server config.
|
||||
|
||||
In the meantime, django_cron is best used to execute tasks that occur relatively often (at least once an hour). Try setting MaxRequestsPerChild to 50, 100, or 200
|
||||
|
||||
# Depending on traffic, and your server config, a number between 50 and 500 is probably good
|
||||
# Note: the higher this number, the more memory django is likely to use. Be careful on shared hosting
|
||||
MaxRequestsPerChild 100
|
||||
|
||||
|
||||
== Example cron.py ==
|
||||
|
||||
from django_cron import cronScheduler, Job
|
||||
|
||||
# This is a function I wrote to check a feedback email address
|
||||
# and add it to our database. Replace with your own imports
|
||||
from MyMailFunctions import check_feedback_mailbox
|
||||
|
||||
class CheckMail(Job):
|
||||
"""
|
||||
Cron Job that checks the lgr users mailbox and adds any
|
||||
approved senders' attachments to the db
|
||||
"""
|
||||
|
||||
# run every 300 seconds (5 minutes)
|
||||
run_every = 300
|
||||
|
||||
def job(self):
|
||||
# This will be executed every 5 minutes
|
||||
check_feedback_mailbox()
|
||||
|
||||
cronScheduler.register(CheckMail)
|
||||
63
django_cron/__init__.py
Normal file
63
django_cron/__init__.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
Copyright (c) 2007-2008, Dj Gilcrease
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
from base import Job, cronScheduler
|
||||
|
||||
def autodiscover():
|
||||
"""
|
||||
Auto-discover INSTALLED_APPS cron.py modules and fail silently when
|
||||
not present. This forces an import on them to register any cron jobs they
|
||||
may want.
|
||||
"""
|
||||
import imp
|
||||
from django.conf import settings
|
||||
|
||||
for app in settings.INSTALLED_APPS:
|
||||
# For each app, we need to look for an cron.py inside that app's
|
||||
# package. We can't use os.path here -- recall that modules may be
|
||||
# imported different ways (think zip files) -- so we need to get
|
||||
# the app's __path__ and look for cron.py on that path.
|
||||
|
||||
# Step 1: find out the app's __path__ Import errors here will (and
|
||||
# should) bubble up, but a missing __path__ (which is legal, but weird)
|
||||
# fails silently -- apps that do weird things with __path__ might
|
||||
# need to roll their own cron registration.
|
||||
try:
|
||||
app_path = __import__(app, {}, {}, [app.split('.')[-1]]).__path__
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
# Step 2: use imp.find_module to find the app's admin.py. For some
|
||||
# reason imp.find_module raises ImportError if the app can't be found
|
||||
# but doesn't actually try to import the module. So skip this app if
|
||||
# its admin.py doesn't exist
|
||||
try:
|
||||
imp.find_module('cron', app_path)
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
# Step 3: import the app's cron file. If this has errors we want them
|
||||
# to bubble up.
|
||||
__import__("%s.cron" % app)
|
||||
|
||||
# Step 4: once we find all the cron jobs, start the cronScheduler
|
||||
cronScheduler.execute()
|
||||
127
django_cron/base.py
Normal file
127
django_cron/base.py
Normal file
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
Copyright (c) 2007-2008, Dj Gilcrease
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
import cPickle
|
||||
from threading import Timer
|
||||
from datetime import datetime
|
||||
|
||||
from django.dispatch import dispatcher
|
||||
from django.conf import settings
|
||||
|
||||
from signals import cron_done
|
||||
import models
|
||||
|
||||
# how often to check if jobs are ready to be run (in seconds)
|
||||
# in reality if you have a multithreaded server, it may get checked
|
||||
# more often that this number suggests, so keep an eye on it...
|
||||
# default value: 300 seconds == 5 min
|
||||
polling_frequency = getattr(settings, "CRON_POLLING_FREQUENCY", 300)
|
||||
|
||||
class Job(object):
|
||||
# 86400 seconds == 24 hours
|
||||
run_every = 86400
|
||||
|
||||
def run(self, *args, **kwargs):
|
||||
self.job()
|
||||
cron_done.send(sender=self, *args, **kwargs)
|
||||
|
||||
def job(self):
|
||||
"""
|
||||
Should be overridden (this way is cleaner, but the old way - overriding run() - will still work)
|
||||
"""
|
||||
pass
|
||||
|
||||
class CronScheduler(object):
|
||||
def register(self, job_class, *args, **kwargs):
|
||||
"""
|
||||
Register the given Job with the scheduler class
|
||||
"""
|
||||
|
||||
job_instance = job_class()
|
||||
|
||||
if not isinstance(job_instance, Job):
|
||||
raise TypeError("You can only register a Job not a %r" % job_class)
|
||||
|
||||
job, created = models.Job.objects.get_or_create(name=str(job_instance.__class__))
|
||||
if created:
|
||||
job.instance = cPickle.dumps(job_instance)
|
||||
job.args = cPickle.dumps(args)
|
||||
job.kwargs = cPickle.dumps(kwargs)
|
||||
job.run_frequency = job_instance.run_every
|
||||
job.save()
|
||||
|
||||
def execute(self):
|
||||
"""
|
||||
Queue all Jobs for execution
|
||||
"""
|
||||
status, created = models.Cron.objects.get_or_create(pk=1)
|
||||
|
||||
# This is important for 2 reasons:
|
||||
# 1. It keeps us for running more than one instance of the
|
||||
# same job at a time
|
||||
# 2. It reduces the number of polling threads because they
|
||||
# get killed off if they happen to check while another
|
||||
# one is already executing a job (only occurs with
|
||||
# multi-threaded servers)
|
||||
if status.executing:
|
||||
return
|
||||
|
||||
status.executing = True
|
||||
try:
|
||||
status.save()
|
||||
except:
|
||||
# this will fail if you're debugging, so we want it
|
||||
# to fail silently and start the timer again so we
|
||||
# can pick up where we left off once debugging is done
|
||||
Timer(polling_frequency, self.execute).start()
|
||||
return
|
||||
|
||||
jobs = models.Job.objects.all()
|
||||
for job in jobs:
|
||||
if job.queued:
|
||||
time_delta = datetime.now() - job.last_run
|
||||
if (time_delta.seconds + 86400*time_delta.days) > job.run_frequency:
|
||||
inst = cPickle.loads(str(job.instance))
|
||||
args = cPickle.loads(str(job.args))
|
||||
kwargs = cPickle.loads(str(job.kwargs))
|
||||
|
||||
try:
|
||||
inst.run(*args, **kwargs)
|
||||
job.last_run = datetime.now()
|
||||
job.save()
|
||||
|
||||
except Exception:
|
||||
# if the job throws an error, just remove it from
|
||||
# the queue. That way we can find/fix the error and
|
||||
# requeue the job manually
|
||||
job.queued = False
|
||||
job.save()
|
||||
|
||||
status.executing = False
|
||||
status.save()
|
||||
|
||||
# Set up for this function to run again
|
||||
Timer(polling_frequency, self.execute).start()
|
||||
|
||||
|
||||
cronScheduler = CronScheduler()
|
||||
|
||||
39
django_cron/models.py
Normal file
39
django_cron/models.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
Copyright (c) 2007-2008, Dj Gilcrease
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
from django.db import models
|
||||
from datetime import datetime
|
||||
|
||||
class Job(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
|
||||
# time between job runs (in seconds) // default: 1 day
|
||||
run_frequency = models.PositiveIntegerField(default=86400)
|
||||
last_run = models.DateTimeField(default=datetime.now())
|
||||
|
||||
instance = models.TextField()
|
||||
args = models.TextField()
|
||||
kwargs = models.TextField()
|
||||
queued = models.BooleanField(default=True)
|
||||
|
||||
class Cron(models.Model):
|
||||
executing = models.BooleanField(default=False)
|
||||
26
django_cron/signals.py
Normal file
26
django_cron/signals.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""
|
||||
Copyright (c) 2007-2008, Dj Gilcrease
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
from django.dispatch import Signal
|
||||
|
||||
cron_queued = Signal()
|
||||
cron_done = Signal(providing_args=["job"])
|
||||
@@ -45,7 +45,7 @@ USE_I18N = True
|
||||
|
||||
# Absolute path to the directory that holds media.
|
||||
# Example: "/home/media/media.lawrence.com/"
|
||||
MEDIA_ROOT = '/home/nikdoof/dev/corpsso/media'
|
||||
MEDIA_ROOT = '/home/dreddit/www/login.dredd.it/login/media'
|
||||
|
||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||
# trailing slash if there is a path component (optional in other cases).
|
||||
@@ -86,6 +86,7 @@ INSTALLED_APPS = (
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'registration',
|
||||
'django_cron',
|
||||
'eve_proxy',
|
||||
'eve_api',
|
||||
'mumble',
|
||||
|
||||
Reference in New Issue
Block a user