22Spire database connection
33"""
44from contextlib import contextmanager
5- from datetime import time
6- import os
5+ from typing import Optional
76
87import redis
98from sqlalchemy import create_engine
109from sqlalchemy .orm import sessionmaker , Session
11- from sqlalchemy .sql .expression import true
1210
1311from .utils .settings import (
12+ SPIRE_DB_URI ,
13+ SPIRE_DB_URI_READ_ONLY ,
14+ SPIRE_DB_POOL_RECYCLE_SECONDS ,
15+ SPIRE_DB_STATEMENT_TIMEOUT_MILLIS ,
1416 BUGOUT_SPIRE_THREAD_DB_POOL_SIZE ,
1517 BUGOUT_SPIRE_THREAD_DB_MAX_OVERFLOW ,
1618 BUGOUT_REDIS_URL ,
1921 BUGOUT_HUMBUG_REDIS_CONNECTIONS_PER_PROCESS ,
2022)
2123
22- connection_str = os .environ .get ("SPIRE_DB_URI" )
23- if connection_str is None :
24- raise ValueError ("SPIRE_DB_URI environment variable not set" )
2524
26- engine = create_engine (
27- connection_str ,
25+ def create_spire_engine (
26+ url : Optional [str ],
27+ pool_size : int ,
28+ max_overflow : int ,
29+ statement_timeout : int ,
30+ pool_recycle : int = SPIRE_DB_POOL_RECYCLE_SECONDS ,
31+ ):
32+ # Pooling: https://docs.sqlalchemy.org/en/14/core/pooling.html#sqlalchemy.pool.QueuePool
33+ # Statement timeout: https://stackoverflow.com/a/44936982
34+ return create_engine (
35+ url = url ,
36+ pool_size = pool_size ,
37+ pool_recycle = pool_recycle ,
38+ max_overflow = max_overflow ,
39+ connect_args = {"options" : f"-c statement_timeout={ statement_timeout } " },
40+ )
41+
42+
43+ engine = create_spire_engine (
44+ url = SPIRE_DB_URI ,
2845 pool_size = BUGOUT_SPIRE_THREAD_DB_POOL_SIZE ,
2946 max_overflow = BUGOUT_SPIRE_THREAD_DB_MAX_OVERFLOW ,
47+ statement_timeout = SPIRE_DB_STATEMENT_TIMEOUT_MILLIS ,
48+ pool_recycle = SPIRE_DB_POOL_RECYCLE_SECONDS ,
3049)
3150SessionLocal = sessionmaker (bind = engine )
3251
@@ -43,6 +62,31 @@ def yield_connection_from_env() -> Session:
4362 session .close ()
4463
4564
65+ # Read only database
66+ RO_engine = create_spire_engine (
67+ url = SPIRE_DB_URI_READ_ONLY ,
68+ pool_size = BUGOUT_SPIRE_THREAD_DB_POOL_SIZE ,
69+ max_overflow = BUGOUT_SPIRE_THREAD_DB_MAX_OVERFLOW ,
70+ statement_timeout = SPIRE_DB_STATEMENT_TIMEOUT_MILLIS ,
71+ pool_recycle = SPIRE_DB_POOL_RECYCLE_SECONDS ,
72+ )
73+ RO_SessionLocal = sessionmaker (bind = RO_engine )
74+
75+
76+ def yield_db_read_only_session () -> Session :
77+ """
78+ Yields read only database connection (created using environment variables).
79+ As per FastAPI docs:
80+ https://fastapi.tiangolo.com/tutorial/sql-databases/#create-a-dependency
81+ """
82+ session = RO_SessionLocal ()
83+ try :
84+ yield session
85+ finally :
86+ session .close ()
87+
88+
89+ # Redis
4690RedisPool = redis .ConnectionPool .from_url (
4791 f"redis://:{ BUGOUT_REDIS_PASSWORD } @{ BUGOUT_REDIS_URL } " ,
4892 max_connections = BUGOUT_HUMBUG_REDIS_CONNECTIONS_PER_PROCESS ,
0 commit comments