Files
meubility-workbench/app/config.py
2026-07-01 23:29:51 +02:00

75 lines
3.2 KiB
Python

from __future__ import annotations
from pathlib import Path
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Runtime settings.
SQLite is the default because this prototype should run immediately.
The schema is deliberately plain enough to migrate to PostGIS later.
"""
database_url: str = "sqlite:///./data/workbench.sqlite"
data_dir: Path = Path("./data")
# 0 means import all stop_times. Use a positive value only for constrained
# demos where full timetable routing is not needed.
gtfs_stop_times_import_limit: int = 0
# "sidecar_stop_times" keeps the large timetable call table in a per-dataset
# SQLite file and stores compact GTFS tables in the main app database.
# Set to "main" for the old all-in-one SQLite layout.
gtfs_timetable_storage: str = "sidecar_stop_times"
gtfs_keep_activation_stage: bool = False
# "sidecar_features" keeps extracted OSM transport features in a per-dataset
# SQLite file. The main DB materializes only OSM rows that need stable
# foreign keys for matches or route-layer output.
osm_feature_storage: str = "sidecar_features"
osm_sidecar_create_visual_only_stops: bool = False
# Large OSM PBF extracts should be reduced to transport objects before the
# Python extractor scans them. XML fixtures stay unfiltered by default.
osm_pbf_prefilter_enabled: bool = True
osm_pbf_prefilter_formats: str = "osm_pbf"
osm_pbf_prefilter_script: Path = Path("scripts/osmium_transport_filter.sh")
osm_diff_max_sequence_gap: int = 14
osm_diff_apply_batch_size: int = 7
osm_diff_state_timeout_seconds: float = 30.0
sqlite_timeout_seconds: float = 120.0
sqlite_busy_timeout_ms: int = 120000
database_write_lock_timeout_seconds: float = 1.0
database_write_lock_cli_timeout_seconds: float = 3600.0
queue_worker_autostart: bool = True
queue_worker_count: int = 1
queue_worker_poll_interval_seconds: float = 2.0
queue_job_lease_seconds: int = 7200
route_matching_batch_size: int = 100
route_layer_osm_route_batch_size: int = 1000
route_layer_osm_stop_batch_size: int = 5000
# SQLite defaults to sidecar storage. PostgreSQL/PostGIS defaults to main
# table storage so indexes, joins, and spatial operators can work over the
# full imported datasets.
postgres_use_sidecars: bool = False
# Keep supervised workers alive across API server restarts. Stale workers are
# detected by PID files at the next startup; stale job leases are requeued.
queue_worker_stop_on_shutdown: bool = False
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
@property
def normalized_database_url(self) -> str:
if self.database_url.startswith("postgresql://"):
return "postgresql+psycopg://" + self.database_url.removeprefix("postgresql://")
return self.database_url
@property
def is_sqlite_database(self) -> bool:
return self.normalized_database_url.startswith("sqlite")
@property
def is_postgresql_database(self) -> bool:
return self.normalized_database_url.startswith("postgresql")
settings = Settings()
settings.data_dir.mkdir(parents=True, exist_ok=True)