v4.3: file-based media storage + manual VACUUM maintenance

This commit is contained in:
Ashim Kumar
2026-06-12 13:24:00 +06:00
parent 965470853e
commit cc57204aff
10 changed files with 789 additions and 164 deletions

46
db.py
View File

@@ -1,4 +1,4 @@
# db.py - Database Configuration and Operations (v4.2)
# db.py - Database Configuration and Operations (v4.3)
import os
import sqlite3
@@ -32,13 +32,19 @@ def get_db_connection():
def init_db():
"""Initialize database tables. Auto-creates parent directory."""
"""Initialize database tables. Auto-creates parent directory + media storage."""
# ফোল্ডার না থাকলে নিজে থেকেই তৈরি করবে (Coolify volume mount-এর জন্য জরুরি)
db_dir = os.path.dirname(os.path.abspath(DATABASE))
if db_dir and not os.path.exists(db_dir):
os.makedirs(db_dir, exist_ok=True)
print(f"📂 Created data directory: {db_dir}")
# v4.3: media-storage ফোল্ডার তৈরি
from config import MEDIA_STORAGE_DIR
if not os.path.exists(MEDIA_STORAGE_DIR):
os.makedirs(MEDIA_STORAGE_DIR, exist_ok=True)
print(f"📂 Created media storage directory: {MEDIA_STORAGE_DIR}")
with get_db_connection() as conn:
cursor = conn.cursor()
@@ -115,7 +121,7 @@ def init_db():
)
''')
# v4.2 publishing migrations
# v4.2 publishing migrations + v4.3 file-based media path columns
migrations = [
('projects', 'is_published', 'INTEGER DEFAULT 0'),
('projects', 'published_at', 'TIMESTAMP'),
@@ -125,6 +131,10 @@ def init_db():
('projects', 'author', 'TEXT DEFAULT ""'),
('projects', 'category', 'TEXT DEFAULT ""'),
('projects', 'view_count', 'INTEGER DEFAULT 0'),
# --- v4.3: file-based media path columns ---
('projects', 'thumbnail_path', 'TEXT'),
('markdown_blocks', 'audio_path', 'TEXT'),
('block_images', 'image_path', 'TEXT'),
]
for table, column, definition in migrations:
@@ -135,14 +145,42 @@ def init_db():
pass
conn.commit()
print(f"✅ Database initialized at {DATABASE} (v4.2)")
print(f"✅ Database initialized at {DATABASE} (v4.3)")
def vacuum_db():
"""ম্যানুয়াল VACUUM (এখন আর অটোমেটিক চলে না)।"""
with get_db_connection() as conn:
conn.execute('VACUUM')
def get_db_stats():
"""
ডেটাবেসের সাইজ এবং কত% ফাঁকা (reusable free) স্পেস আছে তা রিটার্ন করে।
SQLite-এর freelist_count আর page_count দিয়ে হিসাব করা হয়।
"""
file_size = os.path.getsize(DATABASE) if os.path.exists(DATABASE) else 0
with get_db_connection() as conn:
cur = conn.cursor()
page_count = cur.execute('PRAGMA page_count').fetchone()[0]
freelist_count = cur.execute('PRAGMA freelist_count').fetchone()[0]
page_size = cur.execute('PRAGMA page_size').fetchone()[0]
free_bytes = freelist_count * page_size
free_percent = round((freelist_count / page_count) * 100, 1) if page_count > 0 else 0.0
return {
'file_size_bytes': file_size,
'file_size_mb': round(file_size / (1024 * 1024), 2),
'page_count': page_count,
'freelist_count': freelist_count,
'page_size': page_size,
'free_bytes': free_bytes,
'free_mb': round(free_bytes / (1024 * 1024), 2),
'free_percent': free_percent,
}
def init_app(app):
app.teardown_appcontext(close_db)
init_db()