قاعدة البيانات: الترحيل من SQLite إلى PostgreSQL

قاعدة بيانات SQLite رائعة في التطوير، لكنها لا تتعامل جيدًا مع المستخدمين المتزامنين. لذا انتقل إلى PostgreSQL في بيئة الإنتاج.

لماذا الترحيل؟

الميزة SQLite PostgreSQL
الكتابة المتزامنة تُقفل أثناء الكتابة تتعامل مع كتابات متزامنة كثيرة
قابلية التوسع ملف واحد تجمّعات ونسخ متماثل
سلامة البيانات أساسية امتثال كامل لمتطلبات ACID
خيارات الاستضافة قائمة على الملفات Supabase، AWS RDS، Fly.io
الأنسب إلى التطوير، ومستخدم واحد الإنتاج، وعدة مستخدمين

الخطوة 1: تثبيت محوّل PostgreSQL

pip install psycopg2-binary

أضف ما يلي إلى requirements.txt:

psycopg2-binary

إذا كنت تستخدم Docker، فأعد بناء الصورة بعد إضافة التبعية:

cd aiproject/backend
docker compose build

الخطوة 2: تحديث إعدادات قاعدة البيانات

يدعم الكود بالفعل متغير البيئة DATABASE_URL. عدّل backend/app/__init__.py ليستخدمه:

import os

def create_app():
    app = Flask(__name__)

    database_url = os.getenv("DATABASE_URL", "sqlite:///chat.db")
    # بعض المزوّدين يستخدمون postgres:// لكن SQLAlchemy يحتاج إلى postgresql://
    if database_url and database_url.startswith("postgres://"):
        database_url = database_url.replace("postgres://", "postgresql://", 1)

    app.config["SQLALCHEMY_DATABASE_URI"] = database_url
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    ...

حين لا يكون DATABASE_URL مضبوطًا (أي في التطوير المحلي)، يعود الكود إلى SQLite. ولن تحتاج إلى تغيير أي شيء محليًا.

الخطوة 3: إعداد Supabase PostgreSQL

توفّر Supabase خطة مجانية سخية (قاعدة بيانات بسعة 500MB، دون إسبات).

  1. انتقل إلى https://supabase.com وأنشئ حسابًا (تسجيل الدخول عبر GitHub يعمل)
  2. انقر New project
  3. أدخل:
  4. Name: aiproject (أو أي اسم تختاره)
  5. Database Password: أنشئ كلمة مرور قوية (واحفظها في مكان آمن)
  6. Region: اختر المنطقة الأقرب إليك
  7. Pricing Plan: Free (لا تقلق، التكلفة 0 دولار)
  8. انتظر دقيقتين تقريبًا حتى تجهز قاعدة البيانات
  9. انتقل إلى Project Settings → Database → Connection string
  10. انسخ سلسلة الاتصال URI. تبدو هكذا: postgresql://postgres:YOUR_PASSWORD@db.xxxxxxxxxxxxxx.supabase.co:6543/postgres استبدل YOUR_PASSWORD بكلمة المرور التي أنشأتها في الخطوة 3.

الخطوة 4: إضافة DATABASE_URL إلى Hugging Face Spaces

  1. انتقل إلى مساحتك: https://huggingface.co/spaces/YOUR_USERNAME/aiproject-backend
  2. انقر Settings → Repository Secrets
  3. أضف سرًّا جديدًا:
  4. Name: DATABASE_URL
  5. Value: سلسلة اتصال Supabase من الخطوة 3
  6. ستُعاد المساحة تشغيلها تلقائيًا مع السر الجديد

الخطوة 5: التحقق

curl https://YOUR_USERNAME-aiproject-backend.hf.space/api/messages
# → [] (فارغة — قاعدة بيانات PostgreSQL جديدة)

أصبحت واجهتك الخلفية الآن تستخدم Supabase PostgreSQL في بيئة الإنتاج.

الخطوة 6: ترحيل البيانات الحالية (اختياري)

إذا كانت لديك رسائل دردشة في قاعدة بيانات SQLite المحلية وتريد الاحتفاظ بها:

# scripts/migrate_to_postgres.py
import sqlite3
import psycopg2
import os

# اتصل بـ SQLite
sqlite_conn = sqlite3.connect("instance/chat.db")
sqlite_cursor = sqlite_conn.cursor()

# اتصل بـ PostgreSQL (اضبط DATABASE_URL على سلسلة اتصال Supabase الخاصة بك)
pg_conn = psycopg2.connect(os.getenv("DATABASE_URL"))
pg_cursor = pg_conn.cursor()

# أنشئ الجدول
pg_cursor.execute("""
    CREATE TABLE IF NOT EXISTS message (
        id SERIAL PRIMARY KEY,
        content VARCHAR(1000) NOT NULL,
        sender VARCHAR(20) NOT NULL,
        timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
""")

# انسخ البيانات
sqlite_cursor.execute("SELECT content, sender, timestamp FROM message")
rows = sqlite_cursor.fetchall()

for row in rows:
    pg_cursor.execute(
        "INSERT INTO message (content, sender, timestamp) VALUES (%s, %s, %s)",
        row
    )

pg_conn.commit()
print(f"Migrated {len(rows)} messages")

sqlite_conn.close()
pg_conn.close()

شغّله:

cd aiproject/backend
source venv/bin/activate
DATABASE_URL="postgresql://..." python scripts/migrate_to_postgres.py

العودة إلى SQLite محليًا

لا تزال بيئة التطوير المحلية لديك تستخدم SQLite (لأن متغير البيئة DATABASE_URL غير مضبوط). ولن تحتاج إلى تغيير أي شيء.