پرش به مطلب اصلی

اکشن‌های سیستم

این مستند شامل تمام اکشن‌هایی است که در پس‌زمینه داشبورد کاربر اتفاق می‌افتند و کاربر مستقیماً متوجه آن‌ها نمی‌شود، اما برای عملکرد صحیح سیستم ضروری هستند.


فلسفه System Actions

چرا نیاز به اکشن‌های پس‌زمینه داریم؟

  1. بهبود تجربه کاربر: بسیاری از عملیات زمان‌بر هستند و نباید کاربر منتظر بماند
  2. جداسازی نگرانی‌ها: منطق بیزنسی پیچیده باید از رابط کاربری جدا باشد
  3. قابلیت اطمینان: اگر عملیات ناموفق شود، می‌توان retry کرد بدون اینکه کاربر دوباره اقدام کند
  4. مقیاس‌پذیری: عملیات سنگین را می‌توان در سرورهای جداگانه اجرا کرد

دسته‌بندی اکشن‌ها

۱. اکشن‌های احراز هویت و امنیت

۱.۱ بررسی اعتبار توکن

زمان اجرا: هر درخواست به سرور

عملکرد:

  1. توکن JWT را از header استخراج می‌کند
  2. امضای توکن را بررسی می‌کند
  3. تاریخ انقضا را چک می‌کند
  4. اگر منقضی شده، سعی می‌کند با refresh token، توکن جدید بگیرد

API:

Middleware: AuthenticationMiddleware

داده‌های لاگ:

  • User ID
  • Token expiry time
  • Refresh status

۱.۲ ثبت لاگ فعالیت کاربر

زمان اجرا: هر عملیات مهم کاربر (لاگین، آپلود، ویرایش، حذف)

عملکرد:

  • اطلاعات فعالیت کاربر را در جدول user_activity_logs ثبت می‌کند
  • شامل: نوع عملیات، زمان، IP، User Agent، ...

هدف:

  • امکان بررسی فعالیت‌های مشکوک
  • آمار استفاده از سیستم
  • Audit trail برای compliance

مثال لاگ:

{
"user_id": 12345,
"action": "video_uploaded",
"timestamp": "2024-11-16T10:30:00Z",
"ip_address": "1.2.3.4",
"user_agent": "Mozilla/5.0...",
"metadata": {
"video_id": 67890,
"file_size": 500000000
}
}

۱.۳ تشخیص فعالیت مشکوک

زمان اجرا: Real-time، همزمان با فعالیت کاربر

عملکرد: سیستم الگوهای مشکوک را تشخیص می‌دهد:

  • تعداد زیاد درخواست در مدت کوتاه (Brute force یا Spam)
  • تلاش برای دسترسی به resource های دیگران
  • تغییرات غیرعادی در الگوی رفتاری

اقدام:

  1. اگر مشکوک بود، یک flag در دیتابیس ثبت می‌شود
  2. تیم امنیتی notification دریافت می‌کنند
  3. در صورت لزوم، کاربر موقتاً مسدود می‌شود

API:

Service: SecurityMonitoringService
Method: detectSuspiciousActivity()

۲. اکشن‌های آپلود و پردازش

۲.۱ محاسبه هش MD5

زمان اجرا: بلافاصله پس از شروع آپلود فایل

عملکرد:

  1. به‌صورت chunk به chunk، هش MD5 فایل را محاسبه می‌کند
  2. این هش برای تشخیص ویدئوی تکراری و Content ID استفاده می‌شود

الگوریتم:

hash = MD5_INIT()
for each chunk in file:
hash = MD5_UPDATE(hash, chunk)
final_hash = MD5_FINAL(hash)

API:

Service: FileHashService
Method: calculateMD5()

زمان تقریبی:

  • فایل ۱ گیگابایتی: ~۳۰ ثانیه

۲.۲ بررسی ویدئوی تکراری

زمان اجرا: پس از محاسبه هش MD5

عملکرد:

  1. هش MD5 را در دیتابیس جستجو می‌کند
  2. چک می‌کند که آیا این ویدئو قبلاً توسط همین کاربر آپلود شده یا خیر
  3. اگر تکراری بود، آپلود را متوقف می‌کند

Query:

SELECT id, title FROM videos
WHERE user_id = ? AND md5_hash = ?

API:

Service: DuplicateDetectionService
Method: checkDuplicate(userId, md5Hash)

۲.۳ بررسی محدودیت روزانه

زمان اجرا: قبل از شروع آپلود

عملکرد:

  1. تعداد و حجم آپلودهای امروز کاربر را از دیتابیس می‌خواند
  2. با حد مجاز مقایسه می‌کند
  3. اگر رسیده باشد، آپلود را reject می‌کند

Query:

SELECT COUNT(*) as upload_count, SUM(file_size) as total_size
FROM videos
WHERE user_id = ? AND DATE(created_at) = CURDATE()

منطق تصمیم‌گیری:

if (uploadCount >= maxUploads || totalSize + newFileSize > maxSize) {
reject("Daily limit exceeded")
}

۲.۴ ارسال به صف کانورت

زمان اجرا: پس از اتمام موفقیت‌آمیز آپلود فایل

عملکرد:

  1. اطلاعات ویدئو را در یک پیام قرار می‌دهد
  2. پیام را به صف (Queue) کانورت ارسال می‌کند
  3. Worker های تیم کانورت این پیام‌ها را می‌خوانند و پردازش می‌کنند

صف استفاده شده: RabbitMQ یا Kafka

پیام نمونه:

{
"video_id": 67890,
"user_id": 12345,
"file_path": "/uploads/2024/11/16/video_xyz.mp4",
"file_size": 500000000,
"md5_hash": "abc123...",
"priority": "normal",
"callback_url": "https://aparat.com/api/convert/callback"
}

API:

Service: ConvertQueueService
Method: enqueueVideo(videoData)

۲.۵ دریافت نتیجه پردازش از تیم کانورت

زمان اجرا: وقتی تیم کانورت پردازش را تمام کرد و callback را صدا زد

عملکرد:

  1. تیم کانورت یک callback به backend ما می‌زند
  2. اطلاعات ویدئوهای تبدیل‌شده (۳۶۰p, ۴۸۰p, ۷۲۰p, ۱۰۸۰p) را دریافت می‌کنیم
  3. این اطلاعات را در دیتابیس ذخیره می‌کنیم
  4. وضعیت ویدئو را از "در حال پردازش" به "آماده" تغییر می‌دهیم
  5. به کاربر notification می‌فرستیم

Callback Payload:

{
"video_id": 67890,
"status": "completed",
"qualities": [
{"quality": "360p", "url": "https://cdn.aparat.com/.../360p.mp4", "size": 50000000},
{"quality": "480p", "url": "https://cdn.aparat.com/.../480p.mp4", "size": 100000000},
{"quality": "720p", "url": "https://cdn.aparat.com/.../720p.mp4", "size": 250000000},
{"quality": "1080p", "url": "https://cdn.aparat.com/.../1080p.mp4", "size": 500000000}
],
"thumbnail": "https://cdn.aparat.com/.../thumb.jpg",
"duration": 600
}

API:

Endpoint: POST /api/convert/callback

۲.۶ ثبت Content ID

زمان اجرا: وقتی کاربر گزینه "فعال‌سازی حق نشر" را انتخاب کرده باشد

عملکرد:

  1. هش MD5 ویدئو را در جدول content_id ثبت می‌کند
  2. مالکیت این هش را برای کاربر ثبت می‌کند
  3. ویدئوهای مشابه دیگر کاربران را جستجو می‌کند
  4. اگر یافت شد، آن‌ها را حذف می‌کند (یا به صاحب Content ID اطلاع می‌دهد)

Query:

-- ثبت Content ID
INSERT INTO content_id (user_id, video_id, md5_hash, created_at)
VALUES (?, ?, ?, NOW())

-- جستجوی ویدئوهای مشابه
SELECT id FROM videos
WHERE md5_hash = ? AND user_id != ?

API:

Service: ContentIDService
Method: registerContentID(userId, videoId, md5Hash)
Method: findDuplicates(md5Hash, excludeUserId)

۳. اکشن‌های مدیریت لیست پخش

۳.۱ افزودن ویدئو به لیست‌های پخش

زمان اجرا: پس از ثبت نهایی ویدئو

عملکرد:

  1. لیست‌های پخش انتخاب‌شده توسط کاربر را می‌خواند
  2. برای هر لیست، یک رکورد در جدول playlist_videos ایجاد می‌کند
  3. تعداد ویدئوهای لیست را update می‌کند

محدودیت:

  • حداکثر ۵ لیست پخش

Query:

-- افزودن به لیست
INSERT INTO playlist_videos (playlist_id, video_id, position, created_at)
VALUES (?, ?, ?, NOW())

-- آپدیت تعداد
UPDATE playlists
SET video_count = video_count + 1
WHERE id = ?

۳.۲ ایجاد لیست پخش جدید

زمان اجرا: وقتی کاربر در حین آپلود، لیست پخش جدید می‌سازد

عملکرد:

  1. بررسی می‌کند تعداد لیست‌های کاربر کمتر از ۱۰۰۰ باشد
  2. اگر بیشتر بود، بدون نمایش خطا عملیات را لغو می‌کند (silent fail)
  3. در غیر این صورت، لیست جدید را ایجاد می‌کند

Query:

-- بررسی تعداد
SELECT COUNT(*) FROM playlists WHERE user_id = ?

-- ایجاد لیست جدید
INSERT INTO playlists (user_id, title, video_count, created_at)
VALUES (?, ?, 0, NOW())

۴. اکشن‌های آمار و Analytics

۴.۱ محاسبه آمار Real-time

زمان اجرا: هر ۳۰ دقیقه (Cron Job)

عملکرد:

  1. برای هر ویدئو، آمار را از جداول مختلف جمع‌آوری می‌کند:
    • تعداد بازدید از جدول video_views
    • تعداد لایک از جدول video_likes
    • تعداد کامنت از جدول comments
  2. این آمار را aggregate می‌کند
  3. در جدول video_stats_cache ذخیره می‌کند

Query:

INSERT INTO video_stats_cache (video_id, views, likes, comments, calculated_at)
SELECT
video_id,
COUNT(DISTINCT view_id) as views,
(SELECT COUNT(*) FROM video_likes WHERE video_id = v.video_id) as likes,
(SELECT COUNT(*) FROM comments WHERE video_id = v.video_id) as comments,
NOW()
FROM video_views v
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 MINUTE)
GROUP BY video_id

هدف: سرعت بالای نمایش آمار به کاربر (بدون نیاز به query های پیچیده)


۴.۲ محاسبه آمار درآمد

زمان اجرا: هر ۱ ساعت (Cron Job)

عملکرد:

  1. درآمد تبلیغاتی هر ویدئو را از سیستم Ad Server دریافت می‌کند
  2. RPM (Revenue Per Mille) هر ویدئو را محاسبه می‌کند
  3. درآمد کل کاربر را جمع می‌زند
  4. در جدول revenue_stats ذخیره می‌کند

فرمول RPM:

RPM = (Total Revenue / Total Views) * 1000

۴.۳ ثبت لاگ بازدید

زمان اجرا: هر بار که کاربری ویدئو را تماشا می‌کند

عملکرد:

  1. اطلاعات بازدید را ثبت می‌کند:
    • User ID (یا Anonymous)
    • Video ID
    • IP Address
    • User Agent
    • Referrer (از کجا آمده)
    • Watch Time (چقدر از ویدئو را دیده)
  2. این داده‌ها برای محاسبه آمار استفاده می‌شوند

نکته: از Big Data tools مثل Kafka + Spark برای پردازش حجم بالای view logs استفاده می‌شود.


۵. اکشن‌های Notification

۵.۱ ارسال نوتیفیکیشن پس از اتمام پردازش

زمان اجرا: پس از دریافت callback از تیم کانورت (وقتی ویدئو آماده شد)

عملکرد:

  1. یک نوتیفیکیشن ایجاد می‌کند
  2. به جدول notifications اضافه می‌کند
  3. از طریق WebSocket یا Push Notification به کاربر ارسال می‌کند

محتوای notification:

{
"type": "video_ready",
"title": "ویدئوی شما آماده شد!",
"message": "ویدئوی «عنوان ویدئو» پردازش شد و آماده نمایش است.",
"link": "/dashboard/videos/67890",
"timestamp": "2024-11-16T10:30:00Z"
}

کانال‌های ارسال:

  • In-app notification
  • Push notification (موبایل)
  • ایمیل (اختیاری)

۵.۲ ارسال هشدارها (Alerts)

زمان اجرا: وقتی شرایط هشدار برقرار شود

عملکرد:

  1. سیستم شرایط هشدارهای تعریف‌شده را چک می‌کند
  2. اگر شرط برقرار باشد، هشدار را ارسال می‌کند

مثال: کاربر تنظیم کرده: "وقتی بازدید ویدئوی من از ۱۰,۰۰۰ گذشت، به من اطلاع بده"

if (video.views >= 10000 && !alert_sent) {
sendNotification(user, "ویدئوی شما به ۱۰,۰۰۰ بازدید رسید!")
markAlertAsSent(alert_id)
}

۶. اکشن‌های بهینه‌سازی و Caching

۶.۱ کش کردن داده‌های پرتکرار

زمان اجرا: همیشه

عملکرد: داده‌هایی که زیاد تغییر نمی‌کنند را در Redis cache می‌کند:

  • آمار کلی کانال (TTL: 5 min)
  • لیست ویدئوها (TTL: 10 min)
  • اطلاعات پروفایل (TTL: 30 min)

Key Pattern:

user:{user_id}:stats
user:{user_id}:videos
video:{video_id}:stats

۶.۲ Invalidate کردن کش

زمان اجرا: وقتی داده تغییر می‌کند

عملکرد: کلیدهای مربوطه را از Redis حذف می‌کند تا دفعه بعد، داده fresh از دیتابیس خوانده شود.

مثال:

// وقتی ویدئو جدید آپلود شد
redis.del(`user:${userId}:videos`)
redis.del(`user:${userId}:stats`)

۷. اکشن‌های نظافت (Cleanup)

۷.۱ حذف فایل‌های موقت

زمان اجرا: هر روز ساعت ۳ بامداد (Cron Job)

عملکرد:

  1. فایل‌های آپلود نیمه‌کاره که بیش از ۲۴ ساعت گذشته را پیدا می‌کند
  2. این فایل‌ها را حذف می‌کند تا فضای دیسک آزاد شود

۷.۲ حذف نوتیفیکیشن‌های قدیمی

زمان اجرا: هر هفته (Cron Job)

عملکرد: نوتیفیکیشن‌های بیش از ۳ ماه قبل را حذف می‌کند (یا archive می‌کند).


۸. اکشن‌های Monitoring و Health Check

۸.۱ بررسی سلامت سیستم

زمان اجرا: هر ۱ دقیقه

عملکرد:

  1. Ping به سرویس‌های مختلف می‌زند:
    • Database
    • Redis
    • Queue (RabbitMQ)
    • CDN
  2. اگر مشکلی بود، alert به تیم DevOps می‌فرستد

۸.۲ جمع‌آوری Metrics

زمان اجرا: Real-time

عملکرد: متریک‌های مختلف سیستم را جمع‌آوری و به Prometheus/Grafana می‌فرستد:

  • تعداد درخواست‌ها
  • زمان پاسخ
  • نرخ خطا
  • استفاده از CPU/Memory
  • تعداد آپلودهای موفق/ناموفق

جدول خلاصه System Actions

نام اکشنفرکانس اجراسرویس مسئولاولویت
بررسی توکنهر requestAuth Serviceبحرانی
لاگ فعالیتهر عملیات مهمLogging Serviceمتوسط
محاسبه MD5حین آپلودFile Serviceبالا
تشخیص تکراریبعد از MD5Duplicate Serviceبالا
ارسال به صف کانورتبعد از آپلودQueue Serviceبحرانی
دریافت نتیجه کانورتCallbackWebhook Handlerبحرانی
ثبت Content IDاختیاریContent ID Serviceمتوسط
محاسبه آمارهر ۳۰ دقیقهAnalytics Serviceمتوسط
محاسبه درآمدهر ۱ ساعتRevenue Serviceبالا
ارسال نوتیفیکیشنEvent-basedNotification Serviceمتوسط
کش کردنReal-timeCache Serviceبالا
CleanupروزانهMaintenance Serviceپایین
Health Checkهر ۱ دقیقهMonitoring Serviceبحرانی

نمودار تعاملات (Sequence Diagram)

فرآیند آپلود ویدئو

کاربر -> Frontend: انتخاب فایل
Frontend -> Backend: شروع آپلود
Backend -> FileService: محاسبه MD5
FileService -> Backend: MD5 Hash
Backend -> DuplicateService: چک تکراری
DuplicateService -> Database: Query
Database -> DuplicateService: نتیجه
DuplicateService -> Backend: OK
Backend -> Storage: ذخیره فایل
Storage -> Backend: File Path
Backend -> QueueService: ارسال به صف کانورت
QueueService -> ConvertWorker: پیام
Backend -> Frontend: آپلود موفق
Frontend -> کاربر: پیام موفقیت

... (پردازش در پس‌زمینه) ...

ConvertWorker -> ConvertService: شروع پردازش
ConvertService -> ConvertWorker: نتیجه
ConvertWorker -> Backend: Callback
Backend -> Database: ذخیره اطلاعات
Backend -> NotificationService: ارسال نوتیفیکیشن
NotificationService -> کاربر: ویدئو آماده شد!

پیوست‌ها

API های مربوط به System Actions

  • /api/convert/callback - دریافت نتیجه از تیم کانورت
  • /api/health - Health check
  • /api/metrics - دریافت متریک‌ها

سرویس‌های خارجی

  • RabbitMQ: صف پیام‌ها
  • Redis: Cache
  • Kafka: Stream processing برای view logs
  • Prometheus: Monitoring
  • Grafana: Visualization

آخرین به‌روزرسانی: ۱۴۰۳/۰۸/۲۶ نویسنده: تیم فنی آپارات