├── .gitignore
├── LICENSE
├── MANIFEST.in
├── README.md
├── __init__.py
├── celery_tasktigger
├── __init__.py
└── decorator.py
├── example.py
├── images
└── logo.jpg
└── setup.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Python template
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *.py[cod]
6 | *$py.class
7 |
8 | # C extensions
9 | *.so
10 |
11 | # Distribution / packaging
12 | .Python
13 | env/
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .coverage
43 | .coverage.*
44 | .cache
45 | nosetests.xml
46 | coverage.xml
47 | *,cover
48 | .hypothesis/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 |
58 | # Flask instance folder
59 | instance/
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # IPython Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # dotenv
80 | .env
81 |
82 | # virtualenv
83 | venv/
84 | ENV/
85 |
86 | # Spyder project settings
87 | .spyderproject
88 |
89 | # Rope project settings
90 | .ropeproject
91 |
92 | # ide
93 | .idea
94 |
95 | images/*.gif
96 | images/*.lpop
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Boyle Gu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE
2 | include README.md
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | celery-task-tigger
2 | ====
3 |
4 | []()
5 | []()
6 | []()
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
A controllable timing task widgets with Celery
15 |
16 | ## About
17 |
18 | As is known to all, Celery have a already provides periodic task and it's very perfit. But, Assume this case: After my task was called, I hope it's task can frequency of execution, and when celery task was started.
19 |
20 | The above case, Periodic task is hard to practice, Becacuse it's depend on celery beat. ``celery-task-tigger`` do it over simple packaging or implement for solution to do it.
21 |
22 |
23 | ## Installation
24 |
25 | ~~~python
26 | pip install celery-task-tigger
27 |
28 | ~~~
29 |
30 | ## Useage
31 |
32 | Assume you have aleady install celery and can do it.
33 |
34 | ### Bases
35 |
36 | Option `max_times` is must be appoint.
37 |
38 | ~~~python
39 | from celery_tasktigger.decorator import tigger_task
40 |
41 | @app.task(bind=True)
42 | @tigger_task(max_times='forever') # forever is expressed unlimited time
43 | def add(self, x, y):
44 | return x + y
45 |
46 | ~~~
47 |
48 | ### max_times
49 |
50 | Option `max_times`: The maximum number of execute the task times.
51 |
52 | Type: ***int***
53 |
54 | > Note: The value ***'forever'*** is expressed unlimited time.
55 |
56 | Example:
57 |
58 | ~~~python
59 | @app.task(bind=True)
60 | @tigger_task(max_times=3) # after execute 3 times, raise an exception
61 | def add(self, x, y):
62 | return x + y
63 |
64 | ~~~
65 |
66 | ### countdown
67 |
68 | Option `countdown`: You can also provide the countdown argument to execute.
69 |
70 | Type: ***int***
71 |
72 | Default: 1 (seconds)
73 |
74 | Example:
75 |
76 | ~~~python
77 | @app.task(bind=True)
78 | @tigger_task(max_times='forever', countdown=3) # each execute in 3 seconds
79 | def add(self, x, y):
80 | return x + y
81 |
82 | ~~~
83 |
84 | OR
85 |
86 | ~~~python
87 | @app.task(bind=True)
88 | @tigger_task(max_times='forever')
89 | def add(self, x, y, countdown=3): # you also can define formal parameter in task
90 | return x + y
91 |
92 | ~~~
93 |
94 | ## How To Calling Task
95 |
96 | ~~~~python
97 | >> from example import add
98 | >> add.apply_async((1,2))
99 | ~~~~
100 |
101 | you can also delayed execute task, as follow:
102 |
103 | ~~~~python
104 | >> from example import add
105 | >> add.apply_async((1,2), countdown=4) # after 4 seconds, begin start task
106 | # add.apply_async((1,2),{'countdown': 2} countdown=4) ## after 4 seconds, begin start task and interval in 2 seconds
107 | ~~~~
108 |
109 | > About Celery Task, Please see below for details:
110 | > [Celery Calling-Tasks Document](http://docs.jinkan.org/docs/celery/userguide/calling.html)
111 |
112 | ## How To Stop
113 |
114 | if you appoint `max_times='forever'` or provides the bigger values of max_times, you must stop it in programe.
115 |
116 | ~~~~python
117 | >> result = add.apply_async((1,2))
118 | >> result.revoke()
119 | or
120 | >> from mycelery import app
121 | >> app.control.revoke('task_id')
122 | ~~~~
123 |
124 | > See below for details:
125 | > [Celery Document——FAQ](http://docs.jinkan.org/docs/celery/faq.html#can-i-cancel-the-execution-of-a-task)
126 |
127 | ## Some screenshots
128 |
129 | 
130 |
131 | ## Features
132 |
133 | - 100% full compatible with Celery 3 | 4
134 |
135 | - the frequency of execution for task
136 |
137 | - ...and many other stuff (o,0)
138 |
139 |
140 | ## Author
141 |
142 | - Boyle Gu
143 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
--------------------------------------------------------------------------------
/celery_tasktigger/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Handled exceptions raised by celery-task-tigger
3 |
4 | """
5 | from __future__ import unicode_literals
6 |
7 |
8 | class LoopCaptureTag(Exception):
9 | """ disguise a exception for cheat celery"""
10 |
11 | def __str__(self):
12 | return 'Start'
13 |
14 |
15 | class TimesValuesError(Exception):
16 | """check decorator params: max_times"""
17 |
18 | def __str__(self):
19 | return "params of tigger_task: max_times, isn't exist "
20 |
21 |
22 | def check_argument(**kwargs):
23 | countdown = kwargs.get('countdown', 1) # default 1 seconds
24 | max_times = kwargs.get('max_times')
25 | if not max_times:
26 | raise TimesValuesError()
27 | elif max_times == 'forever':
28 |
29 | """default 77777 times .
30 | Please be careful! if use, don't forget revoke it"""
31 |
32 | max_times = 77777
33 | elif not isinstance(max_times, int):
34 | raise TypeError("max_times must int type")
35 |
36 | return dict(countdown=countdown, max_times=max_times)
37 |
--------------------------------------------------------------------------------
/celery_tasktigger/decorator.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2016 Boyle Gu
3 | # Licensed under The MIT License (MIT)
4 | # http://opensource.org/licenses/MIT
5 | #
6 | from __future__ import absolute_import, unicode_literals
7 | from functools import wraps
8 |
9 | from celery_tasktigger import LoopCaptureTag, check_argument
10 |
11 |
12 | def tigger_task(**tigger_kwargs):
13 | """
14 | Fully compatible with Celery
15 |
16 | :param tigger_kwargs: countdown # Execute in x seconds (default 1 seconds )
17 | :param tigger_kwargs: max_times # Max x times
18 | """
19 |
20 | def _decorator(func):
21 | @wraps(func)
22 | def wrapper(self, *args, **kwargs):
23 | check_args = None
24 | try:
25 | countdown = kwargs.get('countdown')
26 | if countdown:
27 | tigger_kwargs.update({'countdown': countdown})
28 | check_args = check_argument(**tigger_kwargs)
29 | func(self, *args, **kwargs)
30 | raise LoopCaptureTag()
31 | except LoopCaptureTag as exc:
32 | raise self.retry(exc=exc, countdown=check_args['countdown'],
33 | max_retries=check_args['max_times'])
34 |
35 | return wrapper
36 |
37 | return _decorator
38 |
--------------------------------------------------------------------------------
/example.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 |
3 | from celery import Celery
4 |
5 | from celery_tasktigger.decorator import tigger_task
6 |
7 | app = Celery('example', backend='amqp', broker='amqp://127.0.0.1:5672//')
8 |
9 | # upgrade celery 4.0
10 | app.conf.update(
11 | result_backend='amqp',
12 | result_expires=18000, # 5 hours.
13 | )
14 |
15 |
16 | # celery -A example worker -l info
17 | @app.task(bind=True)
18 | @tigger_task(max_times='forever', countdown=3)
19 | def add(self, x, y):
20 | return x + y
21 |
--------------------------------------------------------------------------------
/images/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boylegu/celery-task-tigger/8951da61e6bebc17c7a3c4611695822a733608d2/images/logo.jpg
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import os
2 | try:
3 | from setuptools import setup
4 | except ImportError:
5 | from distutils.core import setup
6 |
7 |
8 | __version_info__ = (0, 4)
9 | __version__ = '.'.join([str(v) for v in __version_info__])
10 |
11 | with open(os.path.join(os.path.dirname(__file__), 'README.md')) as readme:
12 | README = readme.read()
13 |
14 | os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
15 |
16 | setup(
17 | name='celery-task-tigger',
18 | version=__version__,
19 | packages=['celery_tasktigger'],
20 | include_package_data=True,
21 | license='MIT License',
22 | description='A controllable timing task widgets with Celery.',
23 | long_description=README,
24 | url='https://github.com/boylegu/celery-task-tigger',
25 | author='BoyleGu',
26 | author_email='gubaoer@hotmail.com',
27 | classifiers=[
28 | 'Development Status :: 5 - Production/Stable',
29 | 'Intended Audience :: Developers',
30 | 'License :: OSI Approved :: MIT License',
31 | 'Operating System :: OS Independent',
32 | 'Programming Language :: Python',
33 | 'Programming Language :: Python :: 2',
34 | 'Programming Language :: Python :: 2.7',
35 | 'Programming Language :: Python :: 3',
36 | 'Programming Language :: Python :: 3.4',
37 | 'Programming Language :: Python :: 3.5',
38 | 'Programming Language :: Python :: Implementation :: CPython',
39 | 'Topic :: Internet :: WWW/HTTP',
40 | 'Topic :: Software Development :: Libraries',
41 | ],
42 | )
43 |
--------------------------------------------------------------------------------