orionis 0.472.0__py3-none-any.whl → 0.474.0__py3-none-any.whl
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.
- orionis/console/core/reactor.py +1 -1
- orionis/console/tasks/schedule.py +91 -302
- orionis/container/container.py +249 -35
- orionis/metadata/framework.py +1 -1
- {orionis-0.472.0.dist-info → orionis-0.474.0.dist-info}/METADATA +1 -1
- {orionis-0.472.0.dist-info → orionis-0.474.0.dist-info}/RECORD +14 -10
- tests/container/core/test_advanced_async.py +234 -0
- tests/container/core/test_async_optimizations.py +268 -0
- tests/container/mocks/mock_advanced_async.py +332 -0
- tests/container/mocks/mock_async_optimizations.py +407 -0
- {orionis-0.472.0.dist-info → orionis-0.474.0.dist-info}/WHEEL +0 -0
- {orionis-0.472.0.dist-info → orionis-0.474.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.472.0.dist-info → orionis-0.474.0.dist-info}/top_level.txt +0 -0
- {orionis-0.472.0.dist-info → orionis-0.474.0.dist-info}/zip-safe +0 -0
orionis/console/core/reactor.py
CHANGED
|
@@ -520,7 +520,7 @@ class Reactor(IReactor):
|
|
|
520
520
|
command_instance._args = {}
|
|
521
521
|
|
|
522
522
|
# Call the handle method of the command instance
|
|
523
|
-
output =
|
|
523
|
+
output = self.__app.call(command_instance, 'handle')
|
|
524
524
|
|
|
525
525
|
# Log the command execution completion with DONE state
|
|
526
526
|
elapsed_time = round(time.perf_counter() - start_time, 2)
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
from typing import Any, List, Optional
|
|
2
|
-
from apscheduler.schedulers.background import BackgroundScheduler as APSBackgroundScheduler
|
|
3
|
-
from apscheduler.schedulers.blocking import BlockingScheduler as APSBlockingScheduler
|
|
4
2
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler as APSAsyncIOScheduler
|
|
5
3
|
from apscheduler.triggers.cron import CronTrigger
|
|
6
4
|
from apscheduler.triggers.date import DateTrigger
|
|
@@ -9,7 +7,6 @@ from orionis.console.contracts.reactor import IReactor
|
|
|
9
7
|
from datetime import datetime
|
|
10
8
|
import pytz
|
|
11
9
|
import asyncio
|
|
12
|
-
from typing import Union
|
|
13
10
|
from orionis.console.exceptions import CLIOrionisRuntimeError
|
|
14
11
|
from orionis.app import Orionis
|
|
15
12
|
|
|
@@ -23,7 +20,7 @@ class Scheduler():
|
|
|
23
20
|
Initialize a new instance of the Scheduler class.
|
|
24
21
|
|
|
25
22
|
This constructor sets up the internal state required for scheduling commands,
|
|
26
|
-
including references to the application instance,
|
|
23
|
+
including references to the application instance, AsyncIOScheduler, the
|
|
27
24
|
command reactor, and job tracking structures. It also initializes properties
|
|
28
25
|
for managing the current scheduling context.
|
|
29
26
|
|
|
@@ -42,11 +39,10 @@ class Scheduler():
|
|
|
42
39
|
# Store the application instance for configuration access.
|
|
43
40
|
self.__app = Orionis()
|
|
44
41
|
|
|
45
|
-
# Initialize
|
|
46
|
-
self.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
self.__initScheduler()
|
|
42
|
+
# Initialize AsyncIOScheduler instance with timezone configuration.
|
|
43
|
+
self.__scheduler: APSAsyncIOScheduler = APSAsyncIOScheduler(
|
|
44
|
+
timezone=pytz.timezone(self.__app.config('app.timezone', 'UTC'))
|
|
45
|
+
)
|
|
50
46
|
|
|
51
47
|
# Store the reactor instance for command management.
|
|
52
48
|
self.__reactor = reactor
|
|
@@ -61,41 +57,6 @@ class Scheduler():
|
|
|
61
57
|
self.__command: str = None # The command signature to be scheduled.
|
|
62
58
|
self.__args: List[str] = None # Arguments for the command.
|
|
63
59
|
self.__purpose: str = None # Purpose or description of the scheduled job.
|
|
64
|
-
self.__type: str = None # Scheduler type (background, blocking, asyncio).
|
|
65
|
-
|
|
66
|
-
def __initScheduler(
|
|
67
|
-
self
|
|
68
|
-
) -> None:
|
|
69
|
-
"""
|
|
70
|
-
Initialize the internal APScheduler instances for background, blocking, and asyncio scheduling.
|
|
71
|
-
|
|
72
|
-
This method creates and configures three types of schedulers:
|
|
73
|
-
- BackgroundScheduler: Runs jobs in the background using threads.
|
|
74
|
-
- BlockingScheduler: Runs jobs in the foreground and blocks the main thread.
|
|
75
|
-
- AsyncIOScheduler: Integrates with asyncio event loops for asynchronous job execution.
|
|
76
|
-
|
|
77
|
-
The timezone for all schedulers is set based on the application's configuration.
|
|
78
|
-
|
|
79
|
-
Returns
|
|
80
|
-
-------
|
|
81
|
-
None
|
|
82
|
-
This method does not return any value. It initializes internal scheduler attributes.
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
# Initialize the BackgroundScheduler with the application's timezone
|
|
86
|
-
self.__background_scheduler = APSBackgroundScheduler(
|
|
87
|
-
timezone=pytz.timezone(self.__app.config('app.timezone', 'UTC'))
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
# Initialize the BlockingScheduler with the application's timezone
|
|
91
|
-
self.__blocking_scheduler = APSBlockingScheduler(
|
|
92
|
-
timezone=pytz.timezone(self.__app.config('app.timezone', 'UTC'))
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
# Initialize the AsyncIOScheduler with the application's timezone
|
|
96
|
-
self.__asyncio_scheduler = APSAsyncIOScheduler(
|
|
97
|
-
timezone=pytz.timezone(self.__app.config('app.timezone', 'UTC'))
|
|
98
|
-
)
|
|
99
60
|
|
|
100
61
|
def __getCommands(
|
|
101
62
|
self
|
|
@@ -130,70 +91,6 @@ class Scheduler():
|
|
|
130
91
|
# Return the commands dictionary
|
|
131
92
|
return commands
|
|
132
93
|
|
|
133
|
-
def background(
|
|
134
|
-
self
|
|
135
|
-
) -> 'Scheduler':
|
|
136
|
-
"""
|
|
137
|
-
Set the scheduler type to 'background' for job scheduling.
|
|
138
|
-
|
|
139
|
-
This method configures the scheduler to use the BackgroundScheduler, which runs jobs in the background using threads.
|
|
140
|
-
It updates the internal type property to indicate that subsequent scheduled jobs should be handled by the background scheduler.
|
|
141
|
-
|
|
142
|
-
Returns
|
|
143
|
-
-------
|
|
144
|
-
Scheduler
|
|
145
|
-
Returns the current instance of the Scheduler to allow method chaining.
|
|
146
|
-
"""
|
|
147
|
-
|
|
148
|
-
# Set the scheduler type to 'background'
|
|
149
|
-
self.__type = 'background'
|
|
150
|
-
|
|
151
|
-
# Return self to support method chaining
|
|
152
|
-
return self
|
|
153
|
-
|
|
154
|
-
def blocking(
|
|
155
|
-
self
|
|
156
|
-
) -> 'Scheduler':
|
|
157
|
-
"""
|
|
158
|
-
Set the scheduler type to 'blocking' for job scheduling.
|
|
159
|
-
|
|
160
|
-
This method configures the scheduler to use the BlockingScheduler, which runs jobs in the foreground and blocks the main thread.
|
|
161
|
-
It updates the internal type property so that subsequent scheduled jobs will be handled by the blocking scheduler.
|
|
162
|
-
|
|
163
|
-
Returns
|
|
164
|
-
-------
|
|
165
|
-
Scheduler
|
|
166
|
-
Returns the current instance of the Scheduler to allow method chaining.
|
|
167
|
-
"""
|
|
168
|
-
|
|
169
|
-
# Set the scheduler type to 'blocking'
|
|
170
|
-
self.__type = 'blocking'
|
|
171
|
-
|
|
172
|
-
# Return self to support method chaining
|
|
173
|
-
return self
|
|
174
|
-
|
|
175
|
-
def asyncio(
|
|
176
|
-
self
|
|
177
|
-
) -> 'Scheduler':
|
|
178
|
-
"""
|
|
179
|
-
Set the scheduler type to 'asyncio' for job scheduling.
|
|
180
|
-
|
|
181
|
-
This method configures the scheduler to use the AsyncIOScheduler, which integrates with
|
|
182
|
-
asyncio event loops for asynchronous job execution. It updates the internal type property
|
|
183
|
-
so that subsequent scheduled jobs will be handled by the asyncio scheduler.
|
|
184
|
-
|
|
185
|
-
Returns
|
|
186
|
-
-------
|
|
187
|
-
Scheduler
|
|
188
|
-
Returns the current instance of the Scheduler to allow method chaining.
|
|
189
|
-
"""
|
|
190
|
-
|
|
191
|
-
# Set the scheduler type to 'asyncio'
|
|
192
|
-
self.__type = 'asyncio'
|
|
193
|
-
|
|
194
|
-
# Return self to support method chaining
|
|
195
|
-
return self
|
|
196
|
-
|
|
197
94
|
def __isAvailable(
|
|
198
95
|
self,
|
|
199
96
|
signature: str
|
|
@@ -254,47 +151,16 @@ class Scheduler():
|
|
|
254
151
|
# Return the description if the command exists, otherwise return None
|
|
255
152
|
return command_entry['description'] if command_entry else None
|
|
256
153
|
|
|
257
|
-
def __getScheduler(
|
|
258
|
-
self
|
|
259
|
-
) -> Optional[Union[APSBackgroundScheduler, APSBlockingScheduler, APSAsyncIOScheduler]]:
|
|
260
|
-
"""
|
|
261
|
-
Retrieve the appropriate APScheduler instance based on the current scheduler type.
|
|
262
|
-
|
|
263
|
-
This method selects and returns the internal scheduler instance corresponding to the
|
|
264
|
-
type specified by the user (background, blocking, or asyncio). The scheduler type is
|
|
265
|
-
determined by the value of the internal `__type` attribute, which is set using the
|
|
266
|
-
`background()`, `blocking()`, or `asyncio()` methods.
|
|
267
|
-
|
|
268
|
-
Returns
|
|
269
|
-
-------
|
|
270
|
-
Optional[Union[APSBackgroundScheduler, APSBlockingScheduler, APSAsyncIOScheduler]]
|
|
271
|
-
The scheduler instance matching the current type, or None if the type is not set
|
|
272
|
-
or does not match any known scheduler.
|
|
273
|
-
"""
|
|
274
|
-
|
|
275
|
-
# Return the BackgroundScheduler if the type is set to 'background'
|
|
276
|
-
if self.__type == 'background':
|
|
277
|
-
return self.__background_scheduler
|
|
278
|
-
|
|
279
|
-
# Return the BlockingScheduler if the type is set to 'blocking'
|
|
280
|
-
elif self.__type == 'blocking':
|
|
281
|
-
return self.__blocking_scheduler
|
|
282
|
-
|
|
283
|
-
# Return the AsyncIOScheduler if the type is set to 'asyncio'
|
|
284
|
-
elif self.__type == 'asyncio':
|
|
285
|
-
return self.__asyncio_scheduler
|
|
286
|
-
|
|
287
154
|
def __reset(
|
|
288
155
|
self
|
|
289
156
|
) -> None:
|
|
290
157
|
"""
|
|
291
158
|
Reset the internal state of the Scheduler instance.
|
|
292
159
|
|
|
293
|
-
This method clears the current command, arguments, purpose
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
settings.
|
|
160
|
+
This method clears the current command, arguments, and purpose attributes,
|
|
161
|
+
effectively resetting the scheduler's configuration to its initial state.
|
|
162
|
+
This can be useful for preparing the scheduler for a new command or job
|
|
163
|
+
scheduling without retaining any previous settings.
|
|
298
164
|
|
|
299
165
|
Returns
|
|
300
166
|
-------
|
|
@@ -305,7 +171,6 @@ class Scheduler():
|
|
|
305
171
|
self.__command = None
|
|
306
172
|
self.__args = None
|
|
307
173
|
self.__purpose = None
|
|
308
|
-
self.__type = None
|
|
309
174
|
|
|
310
175
|
def command(
|
|
311
176
|
self,
|
|
@@ -410,8 +275,8 @@ class Scheduler():
|
|
|
410
275
|
Schedule a command to run once at a specific date and time.
|
|
411
276
|
|
|
412
277
|
This method schedules the currently registered command to execute exactly once at the
|
|
413
|
-
specified datetime
|
|
414
|
-
|
|
278
|
+
specified datetime using the AsyncIOScheduler. The job is registered internally and
|
|
279
|
+
added to the scheduler instance.
|
|
415
280
|
|
|
416
281
|
Parameters
|
|
417
282
|
----------
|
|
@@ -426,8 +291,7 @@ class Scheduler():
|
|
|
426
291
|
Raises
|
|
427
292
|
------
|
|
428
293
|
CLIOrionisRuntimeError
|
|
429
|
-
If the provided date is not a `datetime` instance
|
|
430
|
-
or if there is an error while scheduling the job.
|
|
294
|
+
If the provided date is not a `datetime` instance or if there is an error while scheduling the job.
|
|
431
295
|
"""
|
|
432
296
|
|
|
433
297
|
try:
|
|
@@ -438,30 +302,18 @@ class Scheduler():
|
|
|
438
302
|
"The date must be an instance of datetime."
|
|
439
303
|
)
|
|
440
304
|
|
|
441
|
-
# If no scheduler type is set, default to background scheduler.
|
|
442
|
-
if self.__type is None:
|
|
443
|
-
self.background()
|
|
444
|
-
|
|
445
305
|
# Register the job details internally.
|
|
446
306
|
self.__jobs[self.__command] = {
|
|
447
307
|
'signature': self.__command,
|
|
448
308
|
'args': self.__args,
|
|
449
309
|
'purpose': self.__purpose,
|
|
450
|
-
'type': self.__type,
|
|
451
310
|
'trigger': 'once_at',
|
|
452
311
|
'start_at': date.strftime('%Y-%m-%d %H:%M:%S'),
|
|
453
312
|
'end_at': date.strftime('%Y-%m-%d %H:%M:%S')
|
|
454
313
|
}
|
|
455
314
|
|
|
456
|
-
# Retrieve the appropriate scheduler instance.
|
|
457
|
-
scheduler = self.__getScheduler()
|
|
458
|
-
|
|
459
|
-
# Raise an error if the scheduler is not defined.
|
|
460
|
-
if scheduler is None:
|
|
461
|
-
raise CLIOrionisRuntimeError("No scheduler type has been defined.")
|
|
462
|
-
|
|
463
315
|
# Add the job to the scheduler.
|
|
464
|
-
|
|
316
|
+
self.__scheduler.add_job(
|
|
465
317
|
func= lambda command=self.__command, args=list(self.__args): self.__reactor.call(
|
|
466
318
|
command,
|
|
467
319
|
args
|
|
@@ -489,124 +341,135 @@ class Scheduler():
|
|
|
489
341
|
# Wrap and raise any other exceptions as CLIOrionisRuntimeError.
|
|
490
342
|
raise CLIOrionisRuntimeError(f"Error scheduling the job: {str(e)}")
|
|
491
343
|
|
|
492
|
-
def start(self) -> None:
|
|
344
|
+
async def start(self) -> None:
|
|
493
345
|
"""
|
|
494
|
-
Start
|
|
495
|
-
|
|
496
|
-
This method initiates the three scheduler types managed by this Scheduler instance:
|
|
497
|
-
- AsyncIOScheduler: Integrates with asyncio event loops for asynchronous job execution.
|
|
498
|
-
- BackgroundScheduler: Runs jobs in the background using threads.
|
|
499
|
-
- BlockingScheduler: Runs jobs in the foreground and blocks the main thread.
|
|
346
|
+
Start the AsyncIO scheduler instance and keep it running.
|
|
500
347
|
|
|
501
|
-
|
|
348
|
+
This method initiates the AsyncIOScheduler which integrates with asyncio event loops
|
|
349
|
+
for asynchronous job execution. It ensures the scheduler starts properly within
|
|
350
|
+
an asyncio context and maintains the event loop active to process scheduled jobs.
|
|
502
351
|
|
|
503
352
|
Returns
|
|
504
353
|
-------
|
|
505
354
|
None
|
|
506
|
-
This method does not return any value. It starts
|
|
355
|
+
This method does not return any value. It starts the AsyncIO scheduler and keeps it running.
|
|
507
356
|
"""
|
|
508
357
|
|
|
509
358
|
# Start the AsyncIOScheduler to handle asynchronous jobs.
|
|
510
|
-
# Only start if there's an event loop running or we can create one
|
|
511
359
|
try:
|
|
360
|
+
|
|
361
|
+
# Ensure we're in an asyncio context
|
|
512
362
|
asyncio.get_running_loop()
|
|
513
|
-
self.__asyncio_scheduler.start()
|
|
514
|
-
except RuntimeError:
|
|
515
|
-
# No event loop is running, AsyncIOScheduler won't be started
|
|
516
|
-
# This is normal for non-asyncio environments
|
|
517
|
-
pass
|
|
518
363
|
|
|
519
|
-
|
|
520
|
-
|
|
364
|
+
# Start the scheduler
|
|
365
|
+
if not self.__scheduler.running:
|
|
366
|
+
self.__scheduler.start()
|
|
367
|
+
|
|
368
|
+
# Keep the event loop alive to process scheduled jobs
|
|
369
|
+
try:
|
|
370
|
+
|
|
371
|
+
# Wait for the scheduler to start and keep it running
|
|
372
|
+
while True:
|
|
373
|
+
await asyncio.sleep(1)
|
|
374
|
+
|
|
375
|
+
except KeyboardInterrupt:
|
|
376
|
+
|
|
377
|
+
# Handle graceful shutdown on keyboard interrupt
|
|
378
|
+
await self.shutdown()
|
|
379
|
+
|
|
380
|
+
except Exception as e:
|
|
521
381
|
|
|
522
|
-
|
|
523
|
-
|
|
382
|
+
# Handle exceptions that may occur during scheduler startup
|
|
383
|
+
raise CLIOrionisRuntimeError(f"Failed to start the scheduler: {str(e)}")
|
|
524
384
|
|
|
525
|
-
def shutdown(self, wait=True) -> None:
|
|
385
|
+
async def shutdown(self, wait=True) -> None:
|
|
526
386
|
"""
|
|
527
|
-
Shut down
|
|
387
|
+
Shut down the AsyncIO scheduler instance asynchronously.
|
|
528
388
|
|
|
529
|
-
This method gracefully stops the
|
|
530
|
-
|
|
531
|
-
- BackgroundScheduler: Runs jobs in the background using threads.
|
|
532
|
-
- BlockingScheduler: Runs jobs in the foreground and blocks the main thread.
|
|
389
|
+
This method gracefully stops the AsyncIOScheduler that handles asynchronous job execution.
|
|
390
|
+
Using async ensures proper cleanup in asyncio environments.
|
|
533
391
|
|
|
534
392
|
Parameters
|
|
535
393
|
----------
|
|
536
394
|
wait : bool, optional
|
|
537
|
-
If True, the method will wait until all currently executing jobs are completed before shutting down the
|
|
538
|
-
If False, the
|
|
395
|
+
If True, the method will wait until all currently executing jobs are completed before shutting down the scheduler.
|
|
396
|
+
If False, the scheduler will be shut down immediately without waiting for running jobs to finish. Default is True.
|
|
539
397
|
|
|
540
398
|
Returns
|
|
541
399
|
-------
|
|
542
400
|
None
|
|
543
|
-
This method does not return any value. It shuts down
|
|
401
|
+
This method does not return any value. It shuts down the AsyncIO scheduler.
|
|
544
402
|
"""
|
|
545
403
|
|
|
546
404
|
# Validate that the wait parameter is a boolean.
|
|
547
405
|
if not isinstance(wait, bool):
|
|
548
406
|
raise ValueError("The 'wait' parameter must be a boolean value.")
|
|
549
407
|
|
|
550
|
-
# Shut down the AsyncIOScheduler, waiting for jobs if specified.
|
|
551
408
|
try:
|
|
552
|
-
|
|
553
|
-
|
|
409
|
+
|
|
410
|
+
# Shut down the AsyncIOScheduler, waiting for jobs if specified.
|
|
411
|
+
if self.__scheduler.running:
|
|
412
|
+
|
|
413
|
+
# For AsyncIOScheduler, shutdown can be called normally
|
|
414
|
+
# but we await any pending operations
|
|
415
|
+
self.__scheduler.shutdown(wait=wait)
|
|
416
|
+
|
|
417
|
+
# Give a small delay to ensure proper cleanup
|
|
418
|
+
if wait:
|
|
419
|
+
await asyncio.sleep(0.1)
|
|
420
|
+
|
|
554
421
|
except Exception:
|
|
422
|
+
|
|
555
423
|
# AsyncIOScheduler may not be running or may have issues in shutdown
|
|
556
424
|
pass
|
|
557
425
|
|
|
558
|
-
|
|
559
|
-
if self.__background_scheduler.running:
|
|
560
|
-
self.__background_scheduler.shutdown(wait=wait)
|
|
561
|
-
|
|
562
|
-
# Shut down the BlockingScheduler, waiting for jobs if specified.
|
|
563
|
-
if self.__blocking_scheduler.running:
|
|
564
|
-
self.__blocking_scheduler.shutdown(wait=wait)
|
|
565
|
-
|
|
566
|
-
def remove(self, signature:str) -> None:
|
|
426
|
+
async def remove(self, signature: str) -> bool:
|
|
567
427
|
"""
|
|
568
|
-
Remove a scheduled job from
|
|
428
|
+
Remove a scheduled job from the AsyncIO scheduler asynchronously.
|
|
569
429
|
|
|
570
|
-
This method
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
the removal request without raising an error.
|
|
430
|
+
This method removes a job with the specified signature from both the internal
|
|
431
|
+
jobs dictionary and the AsyncIOScheduler instance. Using async ensures proper
|
|
432
|
+
cleanup in asyncio environments.
|
|
574
433
|
|
|
575
434
|
Parameters
|
|
576
435
|
----------
|
|
577
436
|
signature : str
|
|
578
|
-
The
|
|
437
|
+
The signature of the command/job to remove from the scheduler.
|
|
579
438
|
|
|
580
439
|
Returns
|
|
581
440
|
-------
|
|
582
|
-
|
|
583
|
-
|
|
441
|
+
bool
|
|
442
|
+
Returns True if the job was successfully removed, False if the job was not found.
|
|
443
|
+
|
|
444
|
+
Raises
|
|
445
|
+
------
|
|
446
|
+
ValueError
|
|
447
|
+
If the signature is not a non-empty string.
|
|
584
448
|
"""
|
|
585
449
|
|
|
586
|
-
# Validate that the
|
|
450
|
+
# Validate that the signature is a non-empty string
|
|
587
451
|
if not isinstance(signature, str) or not signature.strip():
|
|
588
|
-
raise ValueError("
|
|
452
|
+
raise ValueError("Signature must be a non-empty string.")
|
|
589
453
|
|
|
590
|
-
# Remove the job from the AsyncIOScheduler, if it exists.
|
|
591
454
|
try:
|
|
592
|
-
self.__asyncio_scheduler.remove_job(signature)
|
|
593
|
-
except Exception:
|
|
594
|
-
# Job may not exist in this scheduler, continue with others
|
|
595
|
-
pass
|
|
596
455
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
456
|
+
# Remove from the scheduler
|
|
457
|
+
self.__scheduler.remove_job(signature)
|
|
458
|
+
|
|
459
|
+
# Remove from internal jobs dictionary
|
|
460
|
+
if signature in self.__jobs:
|
|
461
|
+
del self.__jobs[signature]
|
|
462
|
+
|
|
463
|
+
# Give a small delay to ensure proper cleanup
|
|
464
|
+
await asyncio.sleep(0.01)
|
|
465
|
+
|
|
466
|
+
# Return True to indicate successful removal
|
|
467
|
+
return True
|
|
603
468
|
|
|
604
|
-
# Remove the job from the BlockingScheduler, if it exists.
|
|
605
|
-
try:
|
|
606
|
-
self.__blocking_scheduler.remove_job(signature)
|
|
607
469
|
except Exception:
|
|
608
|
-
|
|
609
|
-
|
|
470
|
+
|
|
471
|
+
# Job not found or other error
|
|
472
|
+
return False
|
|
610
473
|
|
|
611
474
|
def jobs(self) -> dict:
|
|
612
475
|
"""
|
|
@@ -626,78 +489,4 @@ class Scheduler():
|
|
|
626
489
|
"""
|
|
627
490
|
|
|
628
491
|
# Return the internal dictionary holding all scheduled jobs and their details.
|
|
629
|
-
return self.__jobs
|
|
630
|
-
|
|
631
|
-
def start_asyncio_scheduler(self) -> bool:
|
|
632
|
-
"""
|
|
633
|
-
Start the AsyncIOScheduler specifically.
|
|
634
|
-
|
|
635
|
-
This method attempts to start only the AsyncIOScheduler. It's useful when you need
|
|
636
|
-
to start the asyncio scheduler separately or when working in an asyncio environment.
|
|
637
|
-
|
|
638
|
-
Returns
|
|
639
|
-
-------
|
|
640
|
-
bool
|
|
641
|
-
True if the AsyncIOScheduler was started successfully, False otherwise.
|
|
642
|
-
"""
|
|
643
|
-
|
|
644
|
-
try:
|
|
645
|
-
# Check if we're in an asyncio environment
|
|
646
|
-
asyncio.get_running_loop()
|
|
647
|
-
if not self.__asyncio_scheduler.running:
|
|
648
|
-
self.__asyncio_scheduler.start()
|
|
649
|
-
return True
|
|
650
|
-
except RuntimeError:
|
|
651
|
-
# No event loop is running
|
|
652
|
-
return False
|
|
653
|
-
except Exception:
|
|
654
|
-
# Other errors
|
|
655
|
-
return False
|
|
656
|
-
|
|
657
|
-
async def start_asyncio_scheduler_async(self) -> bool:
|
|
658
|
-
"""
|
|
659
|
-
Start the AsyncIOScheduler in an async context.
|
|
660
|
-
|
|
661
|
-
This method is designed to be called from async functions and ensures
|
|
662
|
-
the AsyncIOScheduler is properly started within an asyncio event loop.
|
|
663
|
-
|
|
664
|
-
Returns
|
|
665
|
-
-------
|
|
666
|
-
bool
|
|
667
|
-
True if the AsyncIOScheduler was started successfully, False otherwise.
|
|
668
|
-
"""
|
|
669
|
-
|
|
670
|
-
try:
|
|
671
|
-
if not self.__asyncio_scheduler.running:
|
|
672
|
-
self.__asyncio_scheduler.start()
|
|
673
|
-
return True
|
|
674
|
-
except Exception:
|
|
675
|
-
return False
|
|
676
|
-
|
|
677
|
-
def is_asyncio_scheduler_running(self) -> bool:
|
|
678
|
-
"""
|
|
679
|
-
Check if the AsyncIOScheduler is currently running.
|
|
680
|
-
|
|
681
|
-
Returns
|
|
682
|
-
-------
|
|
683
|
-
bool
|
|
684
|
-
True if the AsyncIOScheduler is running, False otherwise.
|
|
685
|
-
"""
|
|
686
|
-
|
|
687
|
-
return self.__asyncio_scheduler.running if self.__asyncio_scheduler else False
|
|
688
|
-
|
|
689
|
-
def get_scheduler_status(self) -> dict:
|
|
690
|
-
"""
|
|
691
|
-
Get the status of all schedulers.
|
|
692
|
-
|
|
693
|
-
Returns
|
|
694
|
-
-------
|
|
695
|
-
dict
|
|
696
|
-
A dictionary with the running status of each scheduler type.
|
|
697
|
-
"""
|
|
698
|
-
|
|
699
|
-
return {
|
|
700
|
-
'asyncio': self.__asyncio_scheduler.running if self.__asyncio_scheduler else False,
|
|
701
|
-
'background': self.__background_scheduler.running if self.__background_scheduler else False,
|
|
702
|
-
'blocking': self.__blocking_scheduler.running if self.__blocking_scheduler else False
|
|
703
|
-
}
|
|
492
|
+
return self.__jobs
|