Added cron jobs as hosted services
All checks were successful
Test before pr merge / test-lint (pull_request) Successful in 6s
Build on push / prepare (push) Successful in 11s
Build on push / core (push) Successful in 18s
Build on push / query (push) Successful in 19s
Build on push / dependency (push) Successful in 14s
Build on push / database (push) Successful in 15s
Build on push / application (push) Successful in 18s
Build on push / mail (push) Successful in 19s
Build on push / translation (push) Successful in 29s
Build on push / auth (push) Successful in 18s
Build on push / api (push) Successful in 18s

This commit is contained in:
2025-10-04 05:38:21 +02:00
parent e0f6e1c241
commit 685c20e3bf
11 changed files with 77 additions and 24 deletions

View File

@@ -1,3 +1,4 @@
import asyncio
import time import time
from cpl.application.abc import ApplicationABC from cpl.application.abc import ApplicationABC
@@ -36,7 +37,7 @@ class Application(ApplicationABC):
def _wait(time_ms: int): def _wait(time_ms: int):
time.sleep(time_ms) time.sleep(time_ms)
def main(self): async def main(self):
self._logger.debug(f"Host: {Environment.get_host_name()}") self._logger.debug(f"Host: {Environment.get_host_name()}")
self._logger.debug(f"Environment: {Environment.get_environment()}") self._logger.debug(f"Environment: {Environment.get_environment()}")
Console.write_line(List(range(0, 10)).select(lambda x: f"x={x}").to_list()) Console.write_line(List(range(0, 10)).select(lambda x: f"x={x}").to_list())
@@ -76,7 +77,7 @@ class Application(ApplicationABC):
# self.test_send_mail() # self.test_send_mail()
x = 0 x = 0
while x < 5: while x < 500:
Console.write_line("Running...") Console.write_line("Running...")
x += 1 x += 1
time.sleep(5) await asyncio.sleep(5)

View File

@@ -1,7 +1,9 @@
import asyncio import asyncio
import time from datetime import datetime
from cpl.core.console import Console from cpl.core.console import Console
from cpl.core.time.cron import Cron
from cpl.dependency.hosted.cronjob import CronjobABC
from cpl.dependency.hosted.hosted_service import HostedService from cpl.dependency.hosted.hosted_service import HostedService
@@ -17,4 +19,12 @@ class Hosted(HostedService):
async def stop(self): async def stop(self):
Console.write_line("Hosted Service Stopped") Console.write_line("Hosted Service Stopped")
self._stopped = True self._stopped = True
class MyCronJob(CronjobABC):
def __init__(self):
CronjobABC.__init__(self, Cron("*/1 * * * *")) # Every minute
async def loop(self):
Console.write_line(f"[{datetime.now()}] Hello from Cronjob!")

View File

@@ -1,11 +1,10 @@
from cpl import mail
from cpl.application.abc import StartupABC from cpl.application.abc import StartupABC
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.pipes import IPAddressPipe from cpl.core.pipes import IPAddressPipe
from cpl.dependency import ServiceCollection from cpl.dependency import ServiceCollection
from cpl.mail.mail_module import MailModule from cpl.mail.mail_module import MailModule
from hosted_service import Hosted from hosted_service import Hosted, MyCronJob
from scoped_service import ScopedService from scoped_service import ScopedService
from test_service import TestService from test_service import TestService
@@ -26,3 +25,4 @@ class Startup(StartupABC):
services.add_singleton(TestService) services.add_singleton(TestService)
services.add_scoped(ScopedService) services.add_scoped(ScopedService)
services.add_hosted_service(Hosted) services.add_hosted_service(Hosted)
services.add_hosted_service(MyCronJob)

View File

@@ -57,14 +57,9 @@ class Host:
async def runner(): async def runner():
try: try:
if asyncio.iscoroutinefunction(func): if asyncio.iscoroutinefunction(func):
app_task = asyncio.create_task(func(*args, **kwargs)) await func(*args, **kwargs)
else: else:
app_task = cls.get_loop().run_in_executor(None, func, *args, **kwargs) func(*args, **kwargs)
await asyncio.wait(
[app_task, *cls._tasks.values()],
return_when=asyncio.FIRST_COMPLETED,
)
except (KeyboardInterrupt, asyncio.CancelledError): except (KeyboardInterrupt, asyncio.CancelledError):
pass pass
finally: finally:

View File

@@ -1,2 +1,2 @@
from .time_format_settings import TimeFormatSettings from .time_format_settings import TimeFormatSettings
from .time_format_settings_names_enum import TimeFormatSettingsNamesEnum from .cron import Cron

View File

@@ -0,0 +1,13 @@
from datetime import datetime
import croniter
class Cron:
def __init__(self, cron_expression: str, start_time: datetime = None):
self._cron_expression = cron_expression
self._start_time = start_time or datetime.now()
self._iter = croniter.croniter(cron_expression, self._start_time)
def next(self) -> datetime:
return self._iter.get_next(datetime)

View File

@@ -13,7 +13,7 @@ class TimeFormatSettings(ConfigurationModelABC):
date_time_format: str = None, date_time_format: str = None,
date_time_log_format: str = None, date_time_log_format: str = None,
): ):
ConfigurationModelABC.__init__(self) ConfigurationModelABC.__init__(self, readonly=False)
self._date_format: Optional[str] = date_format self._date_format: Optional[str] = date_format
self._time_format: Optional[str] = time_format self._time_format: Optional[str] = time_format
self._date_time_format: Optional[str] = date_time_format self._date_time_format: Optional[str] = date_time_format

View File

@@ -1,8 +0,0 @@
from enum import Enum
class TimeFormatSettingsNamesEnum(Enum):
date_format = "DateFormat"
time_format = "TimeFormat"
date_time_format = "DateTimeFormat"
date_time_log_format = "DateTimeLogFormat"

View File

@@ -3,3 +3,4 @@ colorama==0.4.6
tabulate==0.9.0 tabulate==0.9.0
termcolor==3.1.0 termcolor==3.1.0
pynput==1.8.1 pynput==1.8.1
croniter==6.0.0

View File

@@ -1,2 +1,3 @@
from .hosted_service import HostedService from .hosted_service import HostedService
from .startup_task import StartupTask from .startup_task import StartupTask
from .cronjob import CronjobABC

View File

@@ -0,0 +1,40 @@
import asyncio
from abc import ABC, abstractmethod
from datetime import datetime
from cpl.core.time.cron import Cron
from cpl.dependency.hosted import HostedService
class CronjobABC(HostedService, ABC):
def __init__(self, cron: Cron):
self._cron = cron
self._task: asyncio.Task | None = None
self._running = False
async def start(self):
self._running = True
self._task = asyncio.create_task(self._run_loop())
async def stop(self):
self._running = False
if self._task:
self._task.cancel()
try:
await self._task
except asyncio.CancelledError:
pass
async def _run_loop(self):
while self._running:
next_run = self._cron.next()
now = datetime.now()
delay = (next_run - now).total_seconds()
if delay > 0:
await asyncio.sleep(delay)
if not self._running:
break
await self.loop()
@abstractmethod
async def loop(self): ...