simplecron 0.1.0a2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- simplecron-0.1.0a2/PKG-INFO +348 -0
- simplecron-0.1.0a2/README.md +313 -0
- simplecron-0.1.0a2/pyproject.toml +126 -0
- simplecron-0.1.0a2/src/simplecron/__init__.py +0 -0
- simplecron-0.1.0a2/src/simplecron/base.py +1008 -0
- simplecron-0.1.0a2/src/simplecron/context.py +7 -0
- simplecron-0.1.0a2/src/simplecron/exceptions.py +30 -0
- simplecron-0.1.0a2/src/simplecron/providers.py +140 -0
- simplecron-0.1.0a2/src/simplecron/typings.py +20 -0
- simplecron-0.1.0a2/src/simplecron/utils.py +70 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: simplecron
|
|
3
|
+
Version: 0.1.0a2
|
|
4
|
+
Summary: Simplecron is a simple and lightweight Python library for scheduling tasks using cron-like syntax.
|
|
5
|
+
Keywords: cron,scheduler
|
|
6
|
+
Author: John Pendenque, Daniel Bader
|
|
7
|
+
Author-email: John Pendenque <pendenquejohn@gmail.com>, Daniel Bader <mail@dbader.org>
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Operating System :: POSIX
|
|
10
|
+
Classifier: Operating System :: Unix
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
14
|
+
Classifier: Topic :: Utilities
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Natural Language :: English
|
|
21
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
|
|
22
|
+
Classifier: Operating System :: MacOS
|
|
23
|
+
Requires-Dist: asgiref>=3.11.1
|
|
24
|
+
Requires-Dist: pydantic>=2.13.4
|
|
25
|
+
Requires-Dist: pytz>=2026.2
|
|
26
|
+
Requires-Dist: redis>=8.0.1
|
|
27
|
+
Maintainer: John Pendenque
|
|
28
|
+
Maintainer-email: John Pendenque <pendenquejohn@gmail.com>
|
|
29
|
+
Requires-Python: >=3.14
|
|
30
|
+
Project-URL: Changelog, https://github.com/Zadigo/simplecron/blob/main/CHANGELOG.md
|
|
31
|
+
Project-URL: Documentation, https://github.com/Zadigo/simplecron/wiki
|
|
32
|
+
Project-URL: Homepage, https://github.com/Zadigo/simplecron
|
|
33
|
+
Project-URL: Repository, https://github.com/Zadigo/simplecron.git
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# Simple Cron
|
|
37
|
+
|
|
38
|
+
Simplecron is a simple and lightweight Python library for scheduling tasks using cron-like syntax. It allows you to define jobs that run at specific intervals or times, making it easy to automate repetitive tasks in your applications.
|
|
39
|
+
|
|
40
|
+
This project was inspired by [**schedule.**](https://github.com/dbader/schedule) and improved to add:
|
|
41
|
+
|
|
42
|
+
* Asynchronous functionnalities
|
|
43
|
+
* Redis, SQLite, Postgres provider support
|
|
44
|
+
|
|
45
|
+
## Creating a schedule
|
|
46
|
+
|
|
47
|
+
### Default scheduler
|
|
48
|
+
|
|
49
|
+
Simplecron uses a default scheduler that is created when the library is imported. You can create jobs using the `every` function, which creates a new job instance and attaches it to the default scheduler.
|
|
50
|
+
|
|
51
|
+
```Python
|
|
52
|
+
from simplecron import base
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def callback(job: base.Job, *args, **kwargs):
|
|
56
|
+
print("Hello, World!", job)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
base.every(1).second.do(callback)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
while True:
|
|
63
|
+
base.run_pending()
|
|
64
|
+
time.sleep(1)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The same code can be achieved using the `start_blocking` function, which simplifies the blocking loop:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from simplecron import base
|
|
71
|
+
|
|
72
|
+
def callback(job: base.Job, *args, **kwargs):
|
|
73
|
+
print("Hello, World!", job)
|
|
74
|
+
|
|
75
|
+
base.every(1).second.do(callback)
|
|
76
|
+
base.start_blocking()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
By calling `every`, a new job is created. `second` attaches the unit of time to the job and finally `do` attaches the callback function.
|
|
80
|
+
|
|
81
|
+
> [!NOTE]
|
|
82
|
+
> `start_blocking` is a blocking function, in other words, it will block the main thread and will not allow other code to run while it is executing.
|
|
83
|
+
|
|
84
|
+
### Custom scheduler
|
|
85
|
+
|
|
86
|
+
You can also create your own scheduler by instantiating the `BaseScheduler` class. This can allow you to have multiple schedulers running concurrently, each with its own set of jobs.
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from simplecron.base import BaseScheduler
|
|
90
|
+
|
|
91
|
+
s1 = BaseScheduler()
|
|
92
|
+
s2 = BaseScheduler()
|
|
93
|
+
|
|
94
|
+
# Adds a job to the first scheduler that runs every second
|
|
95
|
+
s1.every(1).second.do(lambda job: print("Scheduler 1:", job))
|
|
96
|
+
|
|
97
|
+
# Adds a job to the second scheduler that runs every 2 seconds
|
|
98
|
+
s2.every(2).seconds.do(lambda job: print("Scheduler 2:", job))
|
|
99
|
+
|
|
100
|
+
def main():
|
|
101
|
+
while True:
|
|
102
|
+
s1.run_pending_jobs()
|
|
103
|
+
s2.run_pending_jobs()
|
|
104
|
+
time.sleep(1)
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__":
|
|
107
|
+
main()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
<!--
|
|
111
|
+
The same code can be achieved using the `Schedulers` class with the `start_blocking` method, which allows you to run multiple schedulers consecutively in a blocking manner.
|
|
112
|
+
|
|
113
|
+
```Python
|
|
114
|
+
import asyncio
|
|
115
|
+
from simplecron.base import BaseScheduler, Job
|
|
116
|
+
from simplecron.runners import Schedulers
|
|
117
|
+
|
|
118
|
+
synchronizer = Schedulers()
|
|
119
|
+
|
|
120
|
+
def callback(job: Job, *args, **kwargs):
|
|
121
|
+
print("Hello, World!", job)
|
|
122
|
+
|
|
123
|
+
def main():
|
|
124
|
+
s1 = BaseScheduler()
|
|
125
|
+
s2 = BaseScheduler()
|
|
126
|
+
|
|
127
|
+
synchronizer.add_scheduler(s1, "seconds", 1, callback)
|
|
128
|
+
synchronizer.add_scheduler(s2, "seconds", 2, callback)
|
|
129
|
+
|
|
130
|
+
synchronizer.start_blocking()
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
main()
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Concurrent schedulers
|
|
137
|
+
|
|
138
|
+
To run multiple schedulers concurrently, you can use the `asyncio` library. This allows you to run multiple schedulers in an asynchronous manner, enabling better performance and responsiveness.
|
|
139
|
+
|
|
140
|
+
```Python
|
|
141
|
+
import asyncio
|
|
142
|
+
from simplecron.base import BaseScheduler, Job
|
|
143
|
+
from simplecron.runners import Schedulers
|
|
144
|
+
|
|
145
|
+
synchronizer = Schedulers()
|
|
146
|
+
|
|
147
|
+
def callback(job: Job, *args, **kwargs):
|
|
148
|
+
print("Hello, World!", job)
|
|
149
|
+
|
|
150
|
+
async def main():
|
|
151
|
+
s1 = BaseScheduler()
|
|
152
|
+
s2 = BaseScheduler()
|
|
153
|
+
|
|
154
|
+
synchronizer.add_scheduler(s1, "seconds", 1, callback)
|
|
155
|
+
synchronizer.add_scheduler(s2, "seconds", 2, callback)
|
|
156
|
+
|
|
157
|
+
await synchronizer.async_blocking()
|
|
158
|
+
|
|
159
|
+
if __name__ == "__main__":
|
|
160
|
+
asyncio.run(main())
|
|
161
|
+
``` -->
|
|
162
|
+
|
|
163
|
+
## Event Listeners
|
|
164
|
+
|
|
165
|
+
You can attach event listeners to a scheduler to listen for specific events. There are three main listeners:
|
|
166
|
+
|
|
167
|
+
* `before` - Triggered before a job is executed.
|
|
168
|
+
* `after` - Triggered after a job is executed.
|
|
169
|
+
* `before_all` - Triggered before all jobs are executed.
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
from simplecron.base import default_scheduler
|
|
173
|
+
from simplecron.utils import EventListenerEnum
|
|
174
|
+
|
|
175
|
+
default_scheduler.event_listener(EventListenerEnum.BEFORE_ALL, lambda scheduler: print("Before all jobs"))
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The same can be achieved using the shortcut method `before_all_events`, `after_events`, and `before_events`:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from simplecron.base import default_scheduler
|
|
182
|
+
|
|
183
|
+
default_scheduler.before_all_events(lambda scheduler: print("Before all jobs"))
|
|
184
|
+
default_scheduler.before_events(lambda job: print("Before job:", job))
|
|
185
|
+
default_scheduler.after_events(lambda job: print("After job:", job))
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Jobs
|
|
189
|
+
|
|
190
|
+
### Cancelling
|
|
191
|
+
|
|
192
|
+
To cancel a job, it simply needs to return an instance of `Cancel`.
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
def callback(job: Job, *args, **kwargs):
|
|
196
|
+
print("Hello, World!", job)
|
|
197
|
+
return Cancel(job, reason="Some reason") # This will cancel the job after it runs once
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Types of jobs
|
|
201
|
+
|
|
202
|
+
**Every second**
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
default_scheduler.every(1).second.do(callback)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Every X second**
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
default_scheduler.every(15).seconds.do(callback)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Every minute**
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
default_scheduler.every(1).minute.do(callback)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Every X minutes**
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
default_scheduler.every(15).minutes.do(callback)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Every hour**
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
default_scheduler.every(1).hour.do(callback)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Every hours**
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
default_scheduler.every(1).hours.do(callback)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Every day**
|
|
239
|
+
|
|
240
|
+
When no specific time is provided, the job will run automatically at the start of the day (00:00). If you need to run the job at a specific time, you must use the `at` method to specify the time in 24-hour format (HH:MM).
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
default_scheduler.every(1).day.do(callback)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
default_scheduler.every(1).day.at(datetime.time(12, 00)).do(callback)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Every days**
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
default_scheduler.every(1).days.do(callback)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Every week**
|
|
257
|
+
|
|
258
|
+
If no specific day and time is povided, the job will run automatically at the start of the week (Monday at 00:00). If you need to run the job at a specific day, you must use one of the properties `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday` or `sunday`.
|
|
259
|
+
|
|
260
|
+
You can also use the `at` method to specify the time in 24-hour format (HH:MM).
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
default_scheduler.every(1).week.do(callback)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
default_scheduler.every(1).week.at(datetime.time(12, 00)).do(callback)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Every X day**
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
default_scheduler.every(1).monday.do(callback)
|
|
274
|
+
default_scheduler.every(1).tuesday.do(callback)
|
|
275
|
+
default_scheduler.every(1).wednesday.do(callback)
|
|
276
|
+
default_scheduler.every(1).thursday.do(callback)
|
|
277
|
+
default_scheduler.every(1).friday.do(callback)
|
|
278
|
+
default_scheduler.every(1).saturday.do(callback)
|
|
279
|
+
default_scheduler.every(1).sunday.do(callback)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Tags
|
|
283
|
+
|
|
284
|
+
Tags allow you to categorize and filter jobs based on specific labels. This can be useful for organizing jobs, applying actions to groups of jobs, or selectively running certain jobs based on their tags.
|
|
285
|
+
|
|
286
|
+
```Python
|
|
287
|
+
base.every(15, tag="my_tag").seconds.do(executor)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
You can also attach event listeners to specific jobs matching a certain set of tags or criteria:
|
|
291
|
+
|
|
292
|
+
```Python
|
|
293
|
+
import time
|
|
294
|
+
|
|
295
|
+
from simplecron.base import Job, default_scheduler, logger
|
|
296
|
+
from simplecron.utils import EventListenerEnum
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def executor(job: Job):
|
|
300
|
+
logger.info("Executor called")
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def event_before(job: Job):
|
|
304
|
+
print("Before job:", job._tags)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
default_scheduler.create_every(10, tag="my_tag").seconds.do(executor)
|
|
308
|
+
|
|
309
|
+
default_scheduler.with_event_listener(
|
|
310
|
+
EventListenerEnum.BEFORE,
|
|
311
|
+
event_before,
|
|
312
|
+
for_tags=["my_tag"]
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
while True:
|
|
316
|
+
default_scheduler.run_pending()
|
|
317
|
+
time.sleep(1)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Providers
|
|
321
|
+
|
|
322
|
+
Providers are external services or modules that can be integrated with the scheduler to extend its functionality. They allow you to connect your scheduled jobs with various platforms, APIs, or other systems seamlessly.
|
|
323
|
+
|
|
324
|
+
### Redis Database provider
|
|
325
|
+
|
|
326
|
+
The example below will save the details of the scheduler and the jobs that were runned in a Redis backend:
|
|
327
|
+
|
|
328
|
+
```Python
|
|
329
|
+
import time
|
|
330
|
+
|
|
331
|
+
from simplecron import base
|
|
332
|
+
from simplecron.base import Job, logger
|
|
333
|
+
from simplecron.providers import RedisDatabase
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def executor(job: Job):
|
|
337
|
+
logger.warning("Executor called")
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
base.default_scheduler.providers.attach(RedisDatabase())
|
|
341
|
+
base.every(15).seconds.do(executor)
|
|
342
|
+
base.every(30).seconds.do(executor)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
while True:
|
|
346
|
+
base.run_pending()
|
|
347
|
+
time.sleep(1)
|
|
348
|
+
```
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Simple Cron
|
|
2
|
+
|
|
3
|
+
Simplecron is a simple and lightweight Python library for scheduling tasks using cron-like syntax. It allows you to define jobs that run at specific intervals or times, making it easy to automate repetitive tasks in your applications.
|
|
4
|
+
|
|
5
|
+
This project was inspired by [**schedule.**](https://github.com/dbader/schedule) and improved to add:
|
|
6
|
+
|
|
7
|
+
* Asynchronous functionnalities
|
|
8
|
+
* Redis, SQLite, Postgres provider support
|
|
9
|
+
|
|
10
|
+
## Creating a schedule
|
|
11
|
+
|
|
12
|
+
### Default scheduler
|
|
13
|
+
|
|
14
|
+
Simplecron uses a default scheduler that is created when the library is imported. You can create jobs using the `every` function, which creates a new job instance and attaches it to the default scheduler.
|
|
15
|
+
|
|
16
|
+
```Python
|
|
17
|
+
from simplecron import base
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def callback(job: base.Job, *args, **kwargs):
|
|
21
|
+
print("Hello, World!", job)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
base.every(1).second.do(callback)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
while True:
|
|
28
|
+
base.run_pending()
|
|
29
|
+
time.sleep(1)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The same code can be achieved using the `start_blocking` function, which simplifies the blocking loop:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from simplecron import base
|
|
36
|
+
|
|
37
|
+
def callback(job: base.Job, *args, **kwargs):
|
|
38
|
+
print("Hello, World!", job)
|
|
39
|
+
|
|
40
|
+
base.every(1).second.do(callback)
|
|
41
|
+
base.start_blocking()
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
By calling `every`, a new job is created. `second` attaches the unit of time to the job and finally `do` attaches the callback function.
|
|
45
|
+
|
|
46
|
+
> [!NOTE]
|
|
47
|
+
> `start_blocking` is a blocking function, in other words, it will block the main thread and will not allow other code to run while it is executing.
|
|
48
|
+
|
|
49
|
+
### Custom scheduler
|
|
50
|
+
|
|
51
|
+
You can also create your own scheduler by instantiating the `BaseScheduler` class. This can allow you to have multiple schedulers running concurrently, each with its own set of jobs.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from simplecron.base import BaseScheduler
|
|
55
|
+
|
|
56
|
+
s1 = BaseScheduler()
|
|
57
|
+
s2 = BaseScheduler()
|
|
58
|
+
|
|
59
|
+
# Adds a job to the first scheduler that runs every second
|
|
60
|
+
s1.every(1).second.do(lambda job: print("Scheduler 1:", job))
|
|
61
|
+
|
|
62
|
+
# Adds a job to the second scheduler that runs every 2 seconds
|
|
63
|
+
s2.every(2).seconds.do(lambda job: print("Scheduler 2:", job))
|
|
64
|
+
|
|
65
|
+
def main():
|
|
66
|
+
while True:
|
|
67
|
+
s1.run_pending_jobs()
|
|
68
|
+
s2.run_pending_jobs()
|
|
69
|
+
time.sleep(1)
|
|
70
|
+
|
|
71
|
+
if __name__ == "__main__":
|
|
72
|
+
main()
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
<!--
|
|
76
|
+
The same code can be achieved using the `Schedulers` class with the `start_blocking` method, which allows you to run multiple schedulers consecutively in a blocking manner.
|
|
77
|
+
|
|
78
|
+
```Python
|
|
79
|
+
import asyncio
|
|
80
|
+
from simplecron.base import BaseScheduler, Job
|
|
81
|
+
from simplecron.runners import Schedulers
|
|
82
|
+
|
|
83
|
+
synchronizer = Schedulers()
|
|
84
|
+
|
|
85
|
+
def callback(job: Job, *args, **kwargs):
|
|
86
|
+
print("Hello, World!", job)
|
|
87
|
+
|
|
88
|
+
def main():
|
|
89
|
+
s1 = BaseScheduler()
|
|
90
|
+
s2 = BaseScheduler()
|
|
91
|
+
|
|
92
|
+
synchronizer.add_scheduler(s1, "seconds", 1, callback)
|
|
93
|
+
synchronizer.add_scheduler(s2, "seconds", 2, callback)
|
|
94
|
+
|
|
95
|
+
synchronizer.start_blocking()
|
|
96
|
+
|
|
97
|
+
if __name__ == "__main__":
|
|
98
|
+
main()
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Concurrent schedulers
|
|
102
|
+
|
|
103
|
+
To run multiple schedulers concurrently, you can use the `asyncio` library. This allows you to run multiple schedulers in an asynchronous manner, enabling better performance and responsiveness.
|
|
104
|
+
|
|
105
|
+
```Python
|
|
106
|
+
import asyncio
|
|
107
|
+
from simplecron.base import BaseScheduler, Job
|
|
108
|
+
from simplecron.runners import Schedulers
|
|
109
|
+
|
|
110
|
+
synchronizer = Schedulers()
|
|
111
|
+
|
|
112
|
+
def callback(job: Job, *args, **kwargs):
|
|
113
|
+
print("Hello, World!", job)
|
|
114
|
+
|
|
115
|
+
async def main():
|
|
116
|
+
s1 = BaseScheduler()
|
|
117
|
+
s2 = BaseScheduler()
|
|
118
|
+
|
|
119
|
+
synchronizer.add_scheduler(s1, "seconds", 1, callback)
|
|
120
|
+
synchronizer.add_scheduler(s2, "seconds", 2, callback)
|
|
121
|
+
|
|
122
|
+
await synchronizer.async_blocking()
|
|
123
|
+
|
|
124
|
+
if __name__ == "__main__":
|
|
125
|
+
asyncio.run(main())
|
|
126
|
+
``` -->
|
|
127
|
+
|
|
128
|
+
## Event Listeners
|
|
129
|
+
|
|
130
|
+
You can attach event listeners to a scheduler to listen for specific events. There are three main listeners:
|
|
131
|
+
|
|
132
|
+
* `before` - Triggered before a job is executed.
|
|
133
|
+
* `after` - Triggered after a job is executed.
|
|
134
|
+
* `before_all` - Triggered before all jobs are executed.
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from simplecron.base import default_scheduler
|
|
138
|
+
from simplecron.utils import EventListenerEnum
|
|
139
|
+
|
|
140
|
+
default_scheduler.event_listener(EventListenerEnum.BEFORE_ALL, lambda scheduler: print("Before all jobs"))
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The same can be achieved using the shortcut method `before_all_events`, `after_events`, and `before_events`:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from simplecron.base import default_scheduler
|
|
147
|
+
|
|
148
|
+
default_scheduler.before_all_events(lambda scheduler: print("Before all jobs"))
|
|
149
|
+
default_scheduler.before_events(lambda job: print("Before job:", job))
|
|
150
|
+
default_scheduler.after_events(lambda job: print("After job:", job))
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Jobs
|
|
154
|
+
|
|
155
|
+
### Cancelling
|
|
156
|
+
|
|
157
|
+
To cancel a job, it simply needs to return an instance of `Cancel`.
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
def callback(job: Job, *args, **kwargs):
|
|
161
|
+
print("Hello, World!", job)
|
|
162
|
+
return Cancel(job, reason="Some reason") # This will cancel the job after it runs once
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Types of jobs
|
|
166
|
+
|
|
167
|
+
**Every second**
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
default_scheduler.every(1).second.do(callback)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Every X second**
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
default_scheduler.every(15).seconds.do(callback)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Every minute**
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
default_scheduler.every(1).minute.do(callback)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Every X minutes**
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
default_scheduler.every(15).minutes.do(callback)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Every hour**
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
default_scheduler.every(1).hour.do(callback)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Every hours**
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
default_scheduler.every(1).hours.do(callback)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Every day**
|
|
204
|
+
|
|
205
|
+
When no specific time is provided, the job will run automatically at the start of the day (00:00). If you need to run the job at a specific time, you must use the `at` method to specify the time in 24-hour format (HH:MM).
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
default_scheduler.every(1).day.do(callback)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
default_scheduler.every(1).day.at(datetime.time(12, 00)).do(callback)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Every days**
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
default_scheduler.every(1).days.do(callback)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Every week**
|
|
222
|
+
|
|
223
|
+
If no specific day and time is povided, the job will run automatically at the start of the week (Monday at 00:00). If you need to run the job at a specific day, you must use one of the properties `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday` or `sunday`.
|
|
224
|
+
|
|
225
|
+
You can also use the `at` method to specify the time in 24-hour format (HH:MM).
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
default_scheduler.every(1).week.do(callback)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
default_scheduler.every(1).week.at(datetime.time(12, 00)).do(callback)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Every X day**
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
default_scheduler.every(1).monday.do(callback)
|
|
239
|
+
default_scheduler.every(1).tuesday.do(callback)
|
|
240
|
+
default_scheduler.every(1).wednesday.do(callback)
|
|
241
|
+
default_scheduler.every(1).thursday.do(callback)
|
|
242
|
+
default_scheduler.every(1).friday.do(callback)
|
|
243
|
+
default_scheduler.every(1).saturday.do(callback)
|
|
244
|
+
default_scheduler.every(1).sunday.do(callback)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Tags
|
|
248
|
+
|
|
249
|
+
Tags allow you to categorize and filter jobs based on specific labels. This can be useful for organizing jobs, applying actions to groups of jobs, or selectively running certain jobs based on their tags.
|
|
250
|
+
|
|
251
|
+
```Python
|
|
252
|
+
base.every(15, tag="my_tag").seconds.do(executor)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
You can also attach event listeners to specific jobs matching a certain set of tags or criteria:
|
|
256
|
+
|
|
257
|
+
```Python
|
|
258
|
+
import time
|
|
259
|
+
|
|
260
|
+
from simplecron.base import Job, default_scheduler, logger
|
|
261
|
+
from simplecron.utils import EventListenerEnum
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def executor(job: Job):
|
|
265
|
+
logger.info("Executor called")
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def event_before(job: Job):
|
|
269
|
+
print("Before job:", job._tags)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
default_scheduler.create_every(10, tag="my_tag").seconds.do(executor)
|
|
273
|
+
|
|
274
|
+
default_scheduler.with_event_listener(
|
|
275
|
+
EventListenerEnum.BEFORE,
|
|
276
|
+
event_before,
|
|
277
|
+
for_tags=["my_tag"]
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
while True:
|
|
281
|
+
default_scheduler.run_pending()
|
|
282
|
+
time.sleep(1)
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Providers
|
|
286
|
+
|
|
287
|
+
Providers are external services or modules that can be integrated with the scheduler to extend its functionality. They allow you to connect your scheduled jobs with various platforms, APIs, or other systems seamlessly.
|
|
288
|
+
|
|
289
|
+
### Redis Database provider
|
|
290
|
+
|
|
291
|
+
The example below will save the details of the scheduler and the jobs that were runned in a Redis backend:
|
|
292
|
+
|
|
293
|
+
```Python
|
|
294
|
+
import time
|
|
295
|
+
|
|
296
|
+
from simplecron import base
|
|
297
|
+
from simplecron.base import Job, logger
|
|
298
|
+
from simplecron.providers import RedisDatabase
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def executor(job: Job):
|
|
302
|
+
logger.warning("Executor called")
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
base.default_scheduler.providers.attach(RedisDatabase())
|
|
306
|
+
base.every(15).seconds.do(executor)
|
|
307
|
+
base.every(30).seconds.do(executor)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
while True:
|
|
311
|
+
base.run_pending()
|
|
312
|
+
time.sleep(1)
|
|
313
|
+
```
|