Improved scheduling using APScheduler

This commit is contained in:
Jörn-Michael Miehe 2022-08-31 01:29:44 +00:00
parent df7b031024
commit bdb4933887
4 changed files with 128 additions and 21 deletions

View file

@ -1,38 +1,51 @@
import logging import logging
import threading
from io import BytesIO from io import BytesIO
from threading import Lock
from typing import Any from typing import Any
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from webdav3.client import Client, Resource from webdav3.client import Client, Resource
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class DavFile: class DavFile:
__instances = None
def __init__(self, client: Client, path: Any) -> None: def __init__(self, client: Client, path: Any) -> None:
self.__resource: Resource = client.resource(path) self.__resource: Resource = client.resource(path)
self.__buffer = BytesIO() self.__buffer = BytesIO()
self.__lock = threading.Lock() self.__lock = Lock()
# register
if DavFile.__instances is None:
DavFile.__instances = []
DavFile.__instances.append(self)
def update(self) -> None: def update(self) -> None:
_logger.debug(f"updating {self.__resource}") _logger.info(f"updating {self.__resource}")
with self.__lock: with self.__lock:
self.__buffer.seek(0) self.__buffer.seek(0)
self.__buffer.truncate(0) self.__buffer.truncate(0)
self.__resource.write_to(self.__buffer) self.__resource.write_to(self.__buffer)
def refresh(self, refresh_interval: int = 5) -> threading.Event: @classmethod
stop_handle = threading.Event() def refresh(cls, refresh_interval: int = 5) -> AsyncIOScheduler:
scheduler = AsyncIOScheduler()
def refresh_loop() -> None: def tick() -> None:
while not stop_handle.wait(refresh_interval): for davfile in DavFile.__instances:
self.update() davfile.update()
thread = threading.Thread(target=refresh_loop) scheduler.add_job(tick)
thread.daemon = True scheduler.add_job(
thread.start() tick, "interval",
seconds=refresh_interval,
)
scheduler.start()
return stop_handle return scheduler
@property @property
def bytes(self) -> bytes: def bytes(self) -> bytes:

View file

@ -3,7 +3,8 @@ import logging
from fastapi import APIRouter from fastapi import APIRouter
from markdown import Markdown from markdown import Markdown
from .. import CLIENT, SETTINGS from .. import CLIENT
from ..config import SETTINGS
from ..dav_file import DavFile from ..dav_file import DavFile
router = APIRouter(prefix="/text", tags=["text"]) router = APIRouter(prefix="/text", tags=["text"])
@ -11,18 +12,21 @@ router = APIRouter(prefix="/text", tags=["text"])
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
_md = Markdown() _md = Markdown()
_message = DavFile(client=CLIENT, path="message.txt") _message = ""
_ticker = DavFile(client=CLIENT, path="ticker.txt") _ticker = ""
_title = DavFile(client=CLIENT, path="title.txt") _title = ""
@router.on_event("startup") @router.on_event("startup")
async def on_startup(): async def on_startup():
_logger.debug("text router startup") global _message, _ticker, _title
_message.refresh() _message = DavFile(client=CLIENT, path="message.txt")
_ticker.refresh() _ticker = DavFile(client=CLIENT, path="ticker.txt")
_title.refresh() _title = DavFile(client=CLIENT, path="title.txt")
DavFile.refresh(60)
_logger.debug("text router started")
@router.get("/message") @router.get("/message")

91
api/poetry.lock generated
View file

@ -15,6 +15,32 @@ doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"]
trio = ["trio (>=0.16)"] trio = ["trio (>=0.16)"]
[[package]]
name = "apscheduler"
version = "3.9.1"
description = "In-process task scheduler with Cron-like capabilities"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
[package.dependencies]
pytz = "*"
six = ">=1.4.0"
tzlocal = ">=2.0,<3.0.0 || >=4.0.0"
[package.extras]
asyncio = ["trollius"]
doc = ["sphinx", "sphinx-rtd-theme"]
gevent = ["gevent"]
mongodb = ["pymongo (>=3.0)"]
redis = ["redis (>=3.0)"]
rethinkdb = ["rethinkdb (>=2.4.0)"]
sqlalchemy = ["sqlalchemy (>=0.8)"]
testing = ["mock", "pytest", "pytest-asyncio", "pytest-asyncio (<0.6)", "pytest-cov", "pytest-tornado5"]
tornado = ["tornado (>=4.3)"]
twisted = ["twisted"]
zookeeper = ["kazoo"]
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2022.6.15" version = "2022.6.15"
@ -169,6 +195,25 @@ python-versions = ">=3.5"
[package.extras] [package.extras]
cli = ["click (>=5.0)"] cli = ["click (>=5.0)"]
[[package]]
name = "pytz"
version = "2022.2.1"
description = "World timezone definitions, modern and historical"
category = "main"
optional = false
python-versions = "*"
[[package]]
name = "pytz-deprecation-shim"
version = "0.1.0.post0"
description = "Shims to make deprecation of pytz easier"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
[package.dependencies]
tzdata = {version = "*", markers = "python_version >= \"3.6\""}
[[package]] [[package]]
name = "requests" name = "requests"
version = "2.28.1" version = "2.28.1"
@ -226,6 +271,30 @@ category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
[[package]]
name = "tzdata"
version = "2022.2"
description = "Provider of IANA time zone data"
category = "main"
optional = false
python-versions = ">=2"
[[package]]
name = "tzlocal"
version = "4.2"
description = "tzinfo object for the local timezone"
category = "main"
optional = false
python-versions = ">=3.6"
[package.dependencies]
pytz-deprecation-shim = "*"
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
[package.extras]
devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"]
test = ["pytest (>=4.3)", "pytest-mock (>=3.3)"]
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "1.26.12" version = "1.26.12"
@ -282,13 +351,17 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.9" python-versions = "^3.9"
content-hash = "a8edb56f5824246d8a490c280bf11318d1efa11d6109b4982b8adf15b391d587" content-hash = "136b9208bffca16de395a3444ca9d172d7e6d7e40866eea987174fa7b69822c7"
[metadata.files] [metadata.files]
anyio = [ anyio = [
{file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"}, {file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"},
{file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"}, {file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"},
] ]
apscheduler = [
{file = "APScheduler-3.9.1-py2.py3-none-any.whl", hash = "sha256:ddc25a0ddd899de44d7f451f4375fb971887e65af51e41e5dcf681f59b8b2c9a"},
{file = "APScheduler-3.9.1.tar.gz", hash = "sha256:65e6574b6395498d371d045f2a8a7e4f7d50c6ad21ef7313d15b1c7cf20df1e3"},
]
certifi = [ certifi = [
{file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"},
{file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"},
@ -442,6 +515,14 @@ python-dotenv = [
{file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"}, {file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"},
{file = "python_dotenv-0.20.0-py3-none-any.whl", hash = "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"}, {file = "python_dotenv-0.20.0-py3-none-any.whl", hash = "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"},
] ]
pytz = [
{file = "pytz-2022.2.1-py2.py3-none-any.whl", hash = "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197"},
{file = "pytz-2022.2.1.tar.gz", hash = "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5"},
]
pytz-deprecation-shim = [
{file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"},
{file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"},
]
requests = [ requests = [
{file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
{file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
@ -462,6 +543,14 @@ typing-extensions = [
{file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"},
{file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"},
] ]
tzdata = [
{file = "tzdata-2022.2-py2.py3-none-any.whl", hash = "sha256:c3119520447d68ef3eb8187a55a4f44fa455f30eb1b4238fa5691ba094f2b05b"},
{file = "tzdata-2022.2.tar.gz", hash = "sha256:21f4f0d7241572efa7f7a4fdabb052e61b55dc48274e6842697ccdf5253e5451"},
]
tzlocal = [
{file = "tzlocal-4.2-py3-none-any.whl", hash = "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745"},
{file = "tzlocal-4.2.tar.gz", hash = "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"},
]
urllib3 = [ urllib3 = [
{file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"},
{file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},

View file

@ -11,6 +11,7 @@ python = "^3.9"
uvicorn = "^0.18.3" uvicorn = "^0.18.3"
webdavclient3 = "3.14.5" webdavclient3 = "3.14.5"
Markdown = "^3.4.1" Markdown = "^3.4.1"
APScheduler = "^3.9.1"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
# pytest = "^5.2" # pytest = "^5.2"