Postgres support (DB_* env), LoginEvent audit table, Choice.value 300, deploy.sh pg_dump backup
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -314,37 +314,60 @@ WSGI_APPLICATION = 'config.wsgi.application'
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
# timeout بالاتر از پیشفرض: وقتی دو کانکشنِ همزمان (مثلِ تستِ
|
||||
# concurrency واقعیِ campaigns) به قفلِ نوشتنِ SQLite برخورد
|
||||
# میکنن، این باعث میشه کانکشنِ منتظر تا ۲۰ ثانیه صبر کنه بهجای
|
||||
# اینکه فوراً OperationalError('database table is locked') بده.
|
||||
'OPTIONS': {
|
||||
'timeout': 20,
|
||||
# هر atomic() قفلِ نوشتن را از اول میگیرد (BEGIN IMMEDIATE).
|
||||
# SQLite از SELECT ... FOR UPDATE پشتیبانی نمیکند و جنگو
|
||||
# select_for_update را رویش بیصدا نادیده میگیرد؛ پس محافظهای
|
||||
# «قفلِ ردیف» در پرداخت، تخفیف، قلب و سهمیهی دستیار بدونِ این
|
||||
# عملاً قفلی نداشتند. با IMMEDIATE کلِ تراکنش سریالی میشود (قفلِ
|
||||
# کلِ دیتابیس، نه ردیف) — روی SQLite درشتتر ولی درست. هزینه:
|
||||
# تراکنشها پشتِ هم صف میکشند؛ فراخوانیهای شبکهای (AI، زرینپال)
|
||||
# عمداً بیرون از atomic() هستند. بعد از Postgres این را بردارید.
|
||||
'transaction_mode': 'IMMEDIATE',
|
||||
},
|
||||
# کانکشنِ DB بهازای هر request باز/بسته نشه؛ تا این تعداد ثانیه
|
||||
# persistent بمونه. با SQLite بیاثرِ عملی ولی بیضرره؛ بعد از
|
||||
# مهاجرت به Postgres جلوی هزینهی TCP+auth در هر request رو میگیره.
|
||||
'CONN_MAX_AGE': int(os.environ.get('DB_CONN_MAX_AGE', '60')),
|
||||
# تستها روی فایل، مثلِ پروداکشن. دیتابیسِ پیشفرضِ تست در حافظه با
|
||||
# shared-cache است که قفلش جدولبهجدول و بیانتظار است («table is
|
||||
# locked») — رفتاری که روی فایلِ واقعی پیش نمیآید؛ تستِ همزمانیِ
|
||||
# campaigns با BEGIN IMMEDIATE فقط همینجا میافتاد.
|
||||
'TEST': {'NAME': str(BASE_DIR / '.test-db.sqlite3')},
|
||||
# Postgres وقتی DB_NAME ست باشد؛ وگرنه SQLite (وضعِ فعلیِ سرور تا روزِ انتقال).
|
||||
# ستبودنِ DB_NAME با ناقصبودنِ بقیه (کاربر/رمز) عمداً خطا میدهد، نه اتصالِ بیرمز.
|
||||
DB_NAME = os.environ.get('DB_NAME', '')
|
||||
|
||||
if DB_NAME:
|
||||
_missing = [k for k in ('DB_USER', 'DB_PASSWORD') if not os.environ.get(k)]
|
||||
if _missing:
|
||||
raise RuntimeError('DB_NAME ست شده ولی %s خالی است.' % ', '.join(_missing))
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': DB_NAME,
|
||||
'USER': os.environ['DB_USER'],
|
||||
'PASSWORD': os.environ['DB_PASSWORD'],
|
||||
'HOST': os.environ.get('DB_HOST', '127.0.0.1'),
|
||||
'PORT': os.environ.get('DB_PORT', '5432'),
|
||||
'CONN_MAX_AGE': int(os.environ.get('DB_CONN_MAX_AGE', '60')),
|
||||
# قفلِ ردیف روی Postgres واقعی است (select_for_update)؛ transaction_mode
|
||||
# فقط برای SQLite بود. با تستهای همزمانی روی Postgres سنجیده میشود.
|
||||
}
|
||||
}
|
||||
}
|
||||
else:
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
# timeout بالاتر از پیشفرض: وقتی دو کانکشنِ همزمان (مثلِ تستِ
|
||||
# concurrency واقعیِ campaigns) به قفلِ نوشتنِ SQLite برخورد
|
||||
# میکنن، این باعث میشه کانکشنِ منتظر تا ۲۰ ثانیه صبر کنه بهجای
|
||||
# اینکه فوراً OperationalError('database table is locked') بده.
|
||||
'OPTIONS': {
|
||||
'timeout': 20,
|
||||
# هر atomic() قفلِ نوشتن را از اول میگیرد (BEGIN IMMEDIATE).
|
||||
# SQLite از SELECT ... FOR UPDATE پشتیبانی نمیکند و جنگو
|
||||
# select_for_update را رویش بیصدا نادیده میگیرد؛ پس محافظهای
|
||||
# «قفلِ ردیف» در پرداخت، تخفیف، قلب و سهمیهی دستیار بدونِ این
|
||||
# عملاً قفلی نداشتند. با IMMEDIATE کلِ تراکنش سریالی میشود (قفلِ
|
||||
# کلِ دیتابیس، نه ردیف) — روی SQLite درشتتر ولی درست. هزینه:
|
||||
# تراکنشها پشتِ هم صف میکشند؛ فراخوانیهای شبکهای (AI، زرینپال)
|
||||
# عمداً بیرون از atomic() هستند. بعد از Postgres این را بردارید.
|
||||
'transaction_mode': 'IMMEDIATE',
|
||||
},
|
||||
# کانکشنِ DB بهازای هر request باز/بسته نشه؛ تا این تعداد ثانیه
|
||||
# persistent بمونه. با SQLite بیاثرِ عملی ولی بیضرره؛ بعد از
|
||||
# مهاجرت به Postgres جلوی هزینهی TCP+auth در هر request رو میگیره.
|
||||
'CONN_MAX_AGE': int(os.environ.get('DB_CONN_MAX_AGE', '60')),
|
||||
# تستها روی فایل، مثلِ پروداکشن. دیتابیسِ پیشفرضِ تست در حافظه با
|
||||
# shared-cache است که قفلش جدولبهجدول و بیانتظار است («table is
|
||||
# locked») — رفتاری که روی فایلِ واقعی پیش نمیآید؛ تستِ همزمانیِ
|
||||
# campaigns با BEGIN IMMEDIATE فقط همینجا میافتاد.
|
||||
'TEST': {'NAME': str(BASE_DIR / '.test-db.sqlite3')},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# In production a shared cache is required for rate limiting to work across
|
||||
# workers/instances; falls back to LocMemCache only when DEBUG=True.
|
||||
|
||||
Reference in New Issue
Block a user