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

96
migrate_to_files.py Normal file
View File

@@ -0,0 +1,96 @@
# migrate_to_files.py - One-time: base64 in DB → files on disk (v4.2 → v4.3)
import sqlite3
import base64
from config import DATABASE
from db import init_db
from media_storage import save_audio, save_image, save_thumbnail
def migrate():
# নিশ্চিত করি নতুন কলামগুলো (audio_path, image_path, thumbnail_path) তৈরি আছে
print("🔧 Ensuring schema is up to date...")
init_db()
conn = sqlite3.connect(DATABASE)
conn.row_factory = sqlite3.Row
cur = conn.cursor()
# --- Audio ---
cur.execute('''
SELECT mb.id as block_id, mb.audio_data, mb.audio_format, c.project_id
FROM markdown_blocks mb JOIN chapters c ON mb.chapter_id = c.id
WHERE mb.audio_data IS NOT NULL AND mb.audio_data != ''
AND (mb.audio_path IS NULL OR mb.audio_path = '')
''')
rows = cur.fetchall()
print(f"🔊 Migrating {len(rows)} audio blocks...")
done = 0
for r in rows:
try:
rel = save_audio(r['project_id'], r['block_id'], r['audio_data'], r['audio_format'] or 'mp3')
if rel:
cur.execute("UPDATE markdown_blocks SET audio_path=?, audio_data='' WHERE id=?",
(rel, r['block_id']))
done += 1
except Exception as e:
print(f" ⚠️ Audio block {r['block_id']} failed: {e}")
conn.commit()
print(f"{done} audio files written")
# --- Images ---
cur.execute('''
SELECT bi.id as image_id, bi.image_data, bi.image_format, c.project_id
FROM block_images bi
JOIN markdown_blocks mb ON bi.block_id = mb.id
JOIN chapters c ON mb.chapter_id = c.id
WHERE bi.image_data IS NOT NULL AND bi.image_data != ''
AND (bi.image_path IS NULL OR bi.image_path = '')
''')
rows = cur.fetchall()
print(f"🖼️ Migrating {len(rows)} images...")
done = 0
for r in rows:
try:
rel = save_image(r['project_id'], r['image_id'], r['image_data'], r['image_format'] or 'png')
if rel:
cur.execute("UPDATE block_images SET image_path=?, image_data='' WHERE id=?",
(rel, r['image_id']))
done += 1
except Exception as e:
print(f" ⚠️ Image {r['image_id']} failed: {e}")
conn.commit()
print(f"{done} image files written")
# --- Thumbnails ---
cur.execute('''
SELECT id, thumbnail_data, thumbnail_format FROM projects
WHERE thumbnail_data IS NOT NULL AND thumbnail_data != ''
AND (thumbnail_path IS NULL OR thumbnail_path = '')
''')
rows = cur.fetchall()
print(f"📕 Migrating {len(rows)} thumbnails...")
done = 0
for r in rows:
try:
raw = base64.b64decode(r['thumbnail_data'])
rel = save_thumbnail(r['id'], raw, r['thumbnail_format'] or 'png')
if rel:
cur.execute("UPDATE projects SET thumbnail_path=?, thumbnail_data=NULL WHERE id=?",
(rel, r['id']))
done += 1
except Exception as e:
print(f" ⚠️ Thumbnail {r['id']} failed: {e}")
conn.commit()
print(f"{done} thumbnails written")
print("🧹 Running VACUUM (this may take a while on a large DB)...")
conn.execute('VACUUM')
conn.commit()
conn.close()
print("✅ Migration complete! Database should now be much smaller.")
if __name__ == '__main__':
migrate()