improve entezar bazdid
This commit is contained in:
1 parent
1fd27d0445
commit
2aee85593f
18 files changed
+10271
-7558
No files matched your search
@@ -0,0 +1,81 @@
|
||||
"""پاکسازی کلیدهای «آلوده» دفتر یکتاسازی یادآوری بازدید.
|
||||
|
||||
چرا لازم است؟ کلید یکتاسازیِ یادآوری بازدید، در نسخهٔ قدیمی ``visit:<id>:<شمارهٔ چرخه>``
|
||||
بود که شمارهٔ چرخه با تقسیم روز بر یک عدد ثابت محاسبه میشد. وقتی آن عدد صفر میشد،
|
||||
عددهای بیمعنا (مثل ``visit:1601:24663``) ساخته و برای همیشه در ``SMSDedup`` ثبت
|
||||
میشدند؛ نتیجهاش قفل دائمی یادآوری برای همان مشتری بود.
|
||||
|
||||
قاعدهٔ جدید کلید را با «موعد تقویمی» میسازد: ``visit:<id>:<YYYY-MM>``. کلیدهای قدیمی
|
||||
هرگز با کلید جدید برخورد نمیکنند، بنابراین بیضرر ولی بازدارندهاند.
|
||||
|
||||
این دستور **فقط** کلیدهای بیمعنا/قدیمیِ دفتر را حذف میکند و هیچ مشتری، اقدام یا
|
||||
پیامکی را تغییر نمیدهد.
|
||||
|
||||
python manage.py cleanup_visit_dedup --dry-run # فقط گزارش
|
||||
python manage.py cleanup_visit_dedup # حذف کلیدهای بیمعنا (cycle > حد)
|
||||
python manage.py cleanup_visit_dedup --all-legacy # حذف همهٔ کلیدهای قالب قدیمی
|
||||
"""
|
||||
import re
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import transaction
|
||||
|
||||
from ...models import SMSDedup
|
||||
|
||||
# سقف منطقی شمارهٔ چرخه؛ هر عدد بزرگتر از این، نتیجهٔ باگ تقسیم قدیمی است.
|
||||
MAX_SANE_CYCLE = 50
|
||||
LEGACY_PATTERN = re.compile(r"^visit:(\d+):(\d+)$")
|
||||
NEW_PATTERN = re.compile(r"^visit:(\d+):(\d{4}-\d{2})$")
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "حذف کلیدهای آلوده/قدیمی دفتر یکتاسازی یادآوری بازدید (بدون تغییر دادهٔ مشتری)."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("--dry-run", action="store_true",
|
||||
help="فقط گزارش؛ چیزی حذف نمیشود.")
|
||||
parser.add_argument("--all-legacy", action="store_true",
|
||||
help="همهٔ کلیدهای قالب قدیمی (visit:<id>:<عدد>) حذف شوند، "
|
||||
"نه فقط عددهای بیمعنا.")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
dry_run = options["dry_run"]
|
||||
all_legacy = options["all_legacy"]
|
||||
|
||||
absurd, sane_legacy, current = [], [], []
|
||||
for key in SMSDedup.objects.filter(key__startswith="visit:").values_list(
|
||||
"key", flat=True
|
||||
).iterator():
|
||||
if NEW_PATTERN.match(key):
|
||||
current.append(key)
|
||||
continue
|
||||
match = LEGACY_PATTERN.match(key)
|
||||
if match:
|
||||
cycle = int(match.group(2))
|
||||
(absurd if cycle > MAX_SANE_CYCLE else sane_legacy).append(key)
|
||||
else:
|
||||
absurd.append(key)
|
||||
|
||||
doomed = absurd + (sane_legacy if all_legacy else [])
|
||||
|
||||
self.stdout.write(self.style.MIGRATE_LABEL("گزارش کلیدهای یادآوری بازدید:"))
|
||||
self.stdout.write(f" کلیدهای قالب جدید (موعد تقویمی): {len(current):,}")
|
||||
self.stdout.write(f" کلیدهای بیمعنا (چرخه > {MAX_SANE_CYCLE} یا ناشناخته): {len(absurd):,}")
|
||||
self.stdout.write(f" کلیدهای قدیمیِ سالم (چرخه ≤ {MAX_SANE_CYCLE}): {len(sane_legacy):,}")
|
||||
if absurd:
|
||||
self.stdout.write(" نمونهٔ کلیدهای بیمعنا: " + ", ".join(absurd[:5]))
|
||||
self.stdout.write(f" قابل حذف در این اجرا: {len(doomed):,}")
|
||||
|
||||
if dry_run:
|
||||
self.stdout.write(self.style.WARNING(
|
||||
"\n[شبیهسازی] هیچ کلیدی حذف نشد."
|
||||
))
|
||||
return
|
||||
if not doomed:
|
||||
self.stdout.write(self.style.SUCCESS("\nانجام شد: چیزی برای حذف نبود."))
|
||||
return
|
||||
with transaction.atomic():
|
||||
deleted, _ = SMSDedup.objects.filter(key__in=doomed).delete()
|
||||
self.stdout.write(self.style.SUCCESS(
|
||||
f"\nانجام شد: {deleted:,} کلید حذف شد (فقط از دفتر یکتاسازی)."
|
||||
))
|
||||
Reference in new issue
Block a user