75 lines
3.2 KiB
Python
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)
|