diff --git a/src/ddns_service/config.py b/src/ddns_service/config.py index c21301b..9899f65 100644 --- a/src/ddns_service/config.py +++ b/src/ddns_service/config.py @@ -141,6 +141,8 @@ def load_config(config_path): cfg["daemon"].setdefault("ssl", False) cfg["daemon"].setdefault("proxy_header", "") cfg["daemon"].setdefault("trusted_proxies", []) + cfg["daemon"].setdefault("thread_pool_size", 10) + cfg["daemon"].setdefault("request_timeout", 10) cfg.setdefault("database", {}) cfg["database"].setdefault("backend", "sqlite") diff --git a/src/ddns_service/server.py b/src/ddns_service/server.py index c1b10f0..a72f126 100644 --- a/src/ddns_service/server.py +++ b/src/ddns_service/server.py @@ -8,6 +8,7 @@ import json import logging import signal import ssl +from concurrent.futures import ThreadPoolExecutor from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from urllib.parse import parse_qs, urlparse @@ -64,7 +65,7 @@ def _is_trusted_proxy(client_ip, trusted_networks): class DDNSServer(ThreadingHTTPServer): - """HTTP server with Application instance.""" + """HTTP server with Application instance and thread pool.""" def __init__(self, app, address): """ @@ -79,8 +80,21 @@ class DDNSServer(ThreadingHTTPServer): self.trusted_networks = _parse_trusted_proxies( app.config["daemon"].get("trusted_proxies", []) ) + self.pool_size = app.config["daemon"]["thread_pool_size"] + self.request_timeout = app.config["daemon"]["request_timeout"] + self.executor = ThreadPoolExecutor(max_workers=self.pool_size) super().__init__(address, DDNSRequestHandler) + def process_request(self, request, client_address): + """Submit request to thread pool.""" + request.settimeout(self.request_timeout) + self.executor.submit(self.process_request_thread, request, client_address) + + def server_close(self): + """Shutdown thread pool and close server.""" + self.executor.shutdown(wait=True) + super().server_close() + class DDNSRequestHandler(BaseHTTPRequestHandler): """HTTP request handler for DDNS updates."""