Skip to content

Commit 62bb6bb

Browse files
committed
Feature: Add periodic cleanup for old database triggers, timezone-aware datetime
1 parent 1f6d32d commit 62bb6bb

137 files changed

Lines changed: 21561 additions & 13 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

state_manager/.dockerignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*.pyo
5+
*.pyd
6+
*.so
7+
8+
# C extensions
9+
*.egg
10+
*.egg-info
11+
.eggs
12+
13+
# Virtual environments
14+
.venv/
15+
16+
# Git, CI and editor config
17+
.git/
18+
.github/
19+
.vscode/
20+
21+
# Logs and temp files
22+
*.log
23+
24+
# Other
25+
.env
26+
Dockerfile
27+
tests/
28+
pytest.ini
29+
.pytest_cache/
30+
.coverage
31+
.coverage.*
32+
coverage.xml

state_manager/.gitignore

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
23+
# Virtual Environment
24+
venv/
25+
env/
26+
ENV/
27+
.env
28+
.venv/
29+
30+
# IDE
31+
.vscode/
32+
*.swp
33+
*.swo
34+
.idea/
35+
*.iws
36+
*.iml
37+
*.ipr
38+
39+
40+
# Local development
41+
.env.local
42+
.env.development.local
43+
.env.test.local
44+
.env.production.local
45+
46+
# Database
47+
*.db
48+
*.sqlite3
49+
50+
# OS generated files
51+
.DS_Store
52+
.DS_Store?
53+
._*
54+
.Spotlight-V100
55+
.Trashes
56+
ehthumbs.db
57+
Thumbs.db
58+
59+
#logs
60+
*.log
61+
logs/*.*
62+
!logs/.gitkeep
63+
64+
# local files
65+
files/
66+
!files/.gitkeep

state_manager/.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.12

state_manager/Dockerfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
FROM python:3.12-slim-bookworm
2+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
3+
4+
WORKDIR /api-server
5+
6+
COPY pyproject.toml uv.lock ./
7+
8+
RUN uv sync --locked
9+
10+
COPY . .
11+
12+
EXPOSE 8000
13+
14+
CMD ["uv", "run", "run.py", "--mode", "production", "--workers", "4"]

state_manager/README.md

Whitespace-only changes.

state_manager/__init__.py

Whitespace-only changes.

state_manager/app/__init__.py

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Config module for State Manager

state_manager/app/config/cors.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
CORS configuration for the State Manager API
3+
"""
4+
import os
5+
from typing import List
6+
7+
def get_cors_origins() -> List[str]:
8+
"""
9+
Get CORS origins from environment variables or use defaults
10+
"""
11+
# Get origins from environment variable
12+
cors_origins = os.getenv("CORS_ORIGINS", "")
13+
14+
if cors_origins:
15+
# Split by comma and strip whitespace
16+
return [origin.strip() for origin in cors_origins.split(",") if origin.strip()]
17+
18+
# Default origins for development
19+
return [
20+
"http://localhost:3000", # Next.js frontend
21+
"http://localhost:3001", # Alternative frontend port
22+
"http://127.0.0.1:3000", # Alternative localhost
23+
"http://127.0.0.1:3001", # Alternative localhost port
24+
]
25+
26+
def get_cors_config():
27+
"""
28+
Get CORS configuration
29+
"""
30+
return {
31+
"allow_origins": get_cors_origins(),
32+
"allow_credentials": True,
33+
"allow_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
34+
"allow_headers": [
35+
"Accept",
36+
"Accept-Language",
37+
"Content-Language",
38+
"Content-Type",
39+
"X-API-Key",
40+
"Authorization",
41+
"X-Requested-With",
42+
"X-Exosphere-Request-ID",
43+
],
44+
"expose_headers": [
45+
"X-Exosphere-Request-ID",
46+
],
47+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import os
2+
from pydantic import BaseModel, Field
3+
from dotenv import load_dotenv
4+
5+
load_dotenv()
6+
7+
class Settings(BaseModel):
8+
"""Application settings loaded from environment variables."""
9+
10+
# MongoDB Configuration
11+
mongo_uri: str = Field(..., description="MongoDB connection URI")
12+
mongo_database_name: str = Field(default="exosphere-state-manager", description="MongoDB database name")
13+
state_manager_secret: str = Field(..., description="Secret key for API authentication")
14+
secrets_encryption_key: str = Field(..., description="Key for encrypting secrets")
15+
trigger_workers: int = Field(default=1, description="Number of workers to run the trigger cron")
16+
17+
# Cleanup / Retention Configs
18+
trigger_retention_days: int = Field(default=30, description="How many days to retain old triggers")
19+
cleanup_interval_minutes: int = Field(default=60, description="Interval (minutes) between cleanup runs")
20+
21+
@classmethod
22+
def from_env(cls) -> "Settings":
23+
return cls(
24+
mongo_uri=os.getenv("MONGO_URI"), # type: ignore
25+
mongo_database_name=os.getenv("MONGO_DATABASE_NAME", "exosphere-state-manager"), # type: ignore
26+
state_manager_secret=os.getenv("STATE_MANAGER_SECRET"), # type: ignore
27+
secrets_encryption_key=os.getenv("SECRETS_ENCRYPTION_KEY"), # type: ignore
28+
trigger_workers=int(os.getenv("TRIGGER_WORKERS", 1)), # type: ignore
29+
30+
# NEW CONFIGS
31+
trigger_retention_days=int(os.getenv("TRIGGER_RETENTION_DAYS", 30)), # type: ignore
32+
cleanup_interval_minutes=int(os.getenv("CLEANUP_INTERVAL_MINUTES", 60)) # type: ignore
33+
)
34+
35+
36+
# Global settings instance - will be updated when get_settings() is called
37+
_settings = None
38+
39+
40+
def get_settings() -> Settings:
41+
"""Get the global settings instance, reloading from environment if needed."""
42+
global _settings
43+
_settings = Settings.from_env()
44+
return _settings
45+
46+
47+
# Initialize settings
48+
settings = get_settings()

0 commit comments

Comments
 (0)