Optimize database and deployment: fix SQL injection, async auth, persist data
- Move SQLite DB to data/ directory and track in git for portability - Fix SQL injection in cleanup_old_emails (use parameterized query) - Replace sync requests with async httpx in auth.py - Enable WAL mode and foreign keys for SQLite - Add UNIQUE constraint and foreign key to account_tags table - Remove redundant indexes on primary key columns - Mount data/ volume in docker-compose for persistence - Remove unused requests dependency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
23
database.py
23
database.py
@@ -18,9 +18,11 @@ logger = logging.getLogger(__name__)
|
||||
class DatabaseManager:
|
||||
"""数据库管理器"""
|
||||
|
||||
def __init__(self, db_path: str = "outlook_manager.db"):
|
||||
def __init__(self, db_path: str = "data/outlook_manager.db"):
|
||||
self.db_path = db_path
|
||||
self._local = threading.local()
|
||||
# 确保数据目录存在
|
||||
Path(db_path).parent.mkdir(parents=True, exist_ok=True)
|
||||
self.init_database()
|
||||
|
||||
def get_connection(self) -> sqlite3.Connection:
|
||||
@@ -28,6 +30,9 @@ class DatabaseManager:
|
||||
if not hasattr(self._local, 'connection'):
|
||||
self._local.connection = sqlite3.connect(self.db_path)
|
||||
self._local.connection.row_factory = sqlite3.Row
|
||||
# 启用WAL模式,提升并发读性能
|
||||
self._local.connection.execute('PRAGMA journal_mode=WAL')
|
||||
self._local.connection.execute('PRAGMA foreign_keys=ON')
|
||||
return self._local.connection
|
||||
|
||||
def init_database(self):
|
||||
@@ -51,10 +56,11 @@ class DatabaseManager:
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS account_tags (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
email TEXT NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
tags TEXT NOT NULL, -- JSON格式存储标签数组
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (email) REFERENCES accounts(email) ON DELETE CASCADE
|
||||
)
|
||||
''')
|
||||
|
||||
@@ -114,9 +120,8 @@ class DatabaseManager:
|
||||
cursor.execute(f"ALTER TABLE claude_payment_status ADD COLUMN {col} TEXT {default}")
|
||||
logger.info(f"已为 claude_payment_status 添加 {col} 列")
|
||||
|
||||
# 创建索引
|
||||
cursor.execute('CREATE INDEX IF NOT EXISTS idx_accounts_email ON accounts(email)')
|
||||
cursor.execute('CREATE INDEX IF NOT EXISTS idx_account_tags_email ON account_tags(email)')
|
||||
# 创建索引(accounts.email 是 PRIMARY KEY,无需额外索引)
|
||||
# account_tags.email 已有 UNIQUE 约束,无需额外索引
|
||||
cursor.execute('CREATE INDEX IF NOT EXISTS idx_email_cache_email ON email_cache(email)')
|
||||
cursor.execute('CREATE INDEX IF NOT EXISTS idx_email_cache_message_id ON email_cache(message_id)')
|
||||
|
||||
@@ -309,9 +314,9 @@ class DatabaseManager:
|
||||
conn = self.get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
DELETE FROM email_cache
|
||||
WHERE created_at < datetime('now', '-{} days')
|
||||
'''.format(days))
|
||||
DELETE FROM email_cache
|
||||
WHERE created_at < datetime('now', ? || ' days')
|
||||
''', (f'-{days}',))
|
||||
deleted_count = cursor.rowcount
|
||||
conn.commit()
|
||||
return deleted_count
|
||||
|
||||
Reference in New Issue
Block a user