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
from cpl.application.abc import ApplicationABC
@@ -36,7 +37,7 @@ class Application(ApplicationABC):
def _wait(time_ms: int):
time.sleep(time_ms)
def main(self):
async def main(self):
self._logger.debug(f"Host: {Environment.get_host_name()}")
self._logger.debug(f"Environment: {Environment.get_environment()}")
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()
x = 0
while x < 5:
while x < 500:
Console.write_line("Running...")
x += 1
time.sleep(5)
await asyncio.sleep(5)

View File

@@ -1,7 +1,9 @@
import asyncio
import time
from datetime import datetime
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
@@ -18,3 +20,11 @@ class Hosted(HostedService):
async def stop(self):
Console.write_line("Hosted Service Stopped")
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.core.configuration import Configuration
from cpl.core.environment import Environment
from cpl.core.pipes import IPAddressPipe
from cpl.dependency import ServiceCollection
from cpl.mail.mail_module import MailModule
from hosted_service import Hosted
from hosted_service import Hosted, MyCronJob
from scoped_service import ScopedService
from test_service import TestService
@@ -26,3 +25,4 @@ class Startup(StartupABC):
services.add_singleton(TestService)
services.add_scoped(ScopedService)
services.add_hosted_service(Hosted)
services.add_hosted_service(MyCronJob)

View File

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

View File

@@ -1,2 +1,2 @@
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_log_format: str = None,
):
ConfigurationModelABC.__init__(self)
ConfigurationModelABC.__init__(self, readonly=False)
self._date_format: Optional[str] = date_format
self._time_format: Optional[str] = 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
termcolor==3.1.0
pynput==1.8.1
croniter==6.0.0

View File

@@ -1,2 +1,3 @@
from .hosted_service import HostedService
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): ...