create docker compose setup
This commit is contained in:
parent
f2fd4c8d7c
commit
16e840fb78
9 changed files with 228 additions and 46 deletions
|
|
@ -12,6 +12,8 @@ from aiocache.serializers import PickleSerializer
|
|||
from pyairtable import Api as AirtableApi
|
||||
from pyairtable.formulas import match
|
||||
|
||||
from random_access.settings import settings
|
||||
|
||||
logger = logging.getLogger("uvicorn.error")
|
||||
|
||||
# Global queue for write operations
|
||||
|
|
@ -52,7 +54,8 @@ def _generate_cache_key(*args, **kwargs) -> str:
|
|||
ttl=300, # 5 minutes
|
||||
cache=Cache.REDIS, # type: ignore
|
||||
serializer=PickleSerializer(),
|
||||
port=6379,
|
||||
endpoint=settings.redis_host,
|
||||
port=settings.redis_port,
|
||||
namespace="airtable_reads",
|
||||
key_builder=lambda f, *args, **kwargs: _generate_cache_key(f.__name__, *args, **kwargs)
|
||||
)
|
||||
|
|
@ -69,7 +72,8 @@ async def get_user_record(slack_user_id: str, users_table) -> dict:
|
|||
ttl=300, # 5 minutes
|
||||
cache=Cache.REDIS, # type: ignore
|
||||
serializer=PickleSerializer(),
|
||||
port=6379,
|
||||
endpoint=settings.redis_host,
|
||||
port=settings.redis_port,
|
||||
namespace="airtable_reads",
|
||||
key_builder=lambda f, *args, **kwargs: _generate_cache_key(f.__name__, *args, **kwargs)
|
||||
)
|
||||
|
|
@ -86,7 +90,8 @@ async def get_game_record(game_id: str, submissions_table) -> dict:
|
|||
ttl=180, # 3 minutes
|
||||
cache=Cache.REDIS, # type: ignore
|
||||
serializer=PickleSerializer(),
|
||||
port=6379,
|
||||
endpoint=settings.redis_host,
|
||||
port=settings.redis_port,
|
||||
namespace="airtable_reads",
|
||||
key_builder=lambda f, *args, **kwargs: _generate_cache_key(f.__name__, *args, **kwargs)
|
||||
)
|
||||
|
|
@ -100,7 +105,8 @@ async def get_all_items(items_table):
|
|||
ttl=60, # 1 minute
|
||||
cache=Cache.REDIS, # type: ignore
|
||||
serializer=PickleSerializer(),
|
||||
port=6379,
|
||||
endpoint=settings.redis_host,
|
||||
port=settings.redis_port,
|
||||
namespace="airtable_reads",
|
||||
key_builder=lambda f, *args, **kwargs: _generate_cache_key(f.__name__, *args, **kwargs)
|
||||
)
|
||||
|
|
@ -117,7 +123,8 @@ async def get_session_by_token_cached(token: str, sessions_table) -> Optional[di
|
|||
ttl=300, # 5 minutes
|
||||
cache=Cache.REDIS, # type: ignore
|
||||
serializer=PickleSerializer(),
|
||||
port=6379,
|
||||
endpoint=settings.redis_host,
|
||||
port=settings.redis_port,
|
||||
namespace="airtable_reads",
|
||||
key_builder=lambda f, *args, **kwargs: _generate_cache_key(f.__name__, *args, **kwargs)
|
||||
)
|
||||
|
|
@ -138,7 +145,8 @@ async def get_user_items(user_id: str, users_table) -> List[dict]:
|
|||
ttl=300, # 5 minutes
|
||||
cache=Cache.REDIS, # type: ignore
|
||||
serializer=PickleSerializer(),
|
||||
port=6379,
|
||||
endpoint=settings.redis_host,
|
||||
port=settings.redis_port,
|
||||
namespace="airtable_reads",
|
||||
key_builder=lambda f, *args, **kwargs: _generate_cache_key(f.__name__, *args, **kwargs)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ import logging
|
|||
from collections import namedtuple
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from fastapi import FastAPI, Request, Response, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from slowapi import Limiter, _rate_limit_exceeded_handler
|
||||
from slowapi import Limiter
|
||||
from slowapi.errors import RateLimitExceeded
|
||||
from slowapi.middleware import SlowAPIMiddleware
|
||||
from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler
|
||||
|
|
@ -27,9 +26,6 @@ Result = namedtuple("Result", "content, status")
|
|||
|
||||
logger = logging.getLogger("uvicorn.error")
|
||||
|
||||
if not load_dotenv():
|
||||
raise FileNotFoundError("Environment secrets not found!")
|
||||
|
||||
# Initialize rate limiter
|
||||
limiter = Limiter(key_func=get_client_ip)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,29 @@
|
|||
"""
|
||||
Settings configuration that works in both local development and Docker environments.
|
||||
|
||||
In local development:
|
||||
- Loads from .env file if it exists
|
||||
- Environment variables override .env file values
|
||||
|
||||
In Docker:
|
||||
- Reads directly from environment variables (no .env file needed)
|
||||
- Use docker-compose.yml or docker run -e to set environment variables
|
||||
"""
|
||||
|
||||
import os
|
||||
from os import environ
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8', extra='ignore')
|
||||
model_config = SettingsConfigDict(
|
||||
# Try to load .env file for local development, but don't fail if it doesn't exist
|
||||
env_file='.env' if os.path.exists('.env') else None,
|
||||
env_file_encoding='utf-8',
|
||||
extra='ignore',
|
||||
# Environment variables take precedence over .env file
|
||||
env_ignore_empty=True
|
||||
)
|
||||
airtable_pat: str
|
||||
airtable_base: str
|
||||
slack_signing_secret: str
|
||||
|
|
@ -20,10 +41,21 @@ class Settings(BaseSettings):
|
|||
# Session security
|
||||
session_ttl_hours: int = 24 # Session expires after 24 hours
|
||||
|
||||
# Redis/Valkey settings - prioritize explicit env vars, fall back to container detection
|
||||
redis_host: str = environ.get("REDIS_HOST") or (
|
||||
"valkey" if environ.get("DOCKER_CONTAINER") else "localhost"
|
||||
)
|
||||
redis_port: int = int(environ.get("REDIS_PORT", "6379"))
|
||||
|
||||
@property
|
||||
def is_production(self) -> bool:
|
||||
return self.environment == "production"
|
||||
|
||||
@property
|
||||
def is_container(self) -> bool:
|
||||
"""Detect if running in a container environment."""
|
||||
return bool(environ.get("DOCKER_CONTAINER") or environ.get("REDIS_HOST"))
|
||||
|
||||
@property
|
||||
def origins_list(self) -> list[str]:
|
||||
if self.allowed_origins == "*":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue