feat: Add monitoring alerts skeleton and enhance worker with notifications

This commit is contained in:
masoodafar-web
2025-11-30 20:18:10 +03:30
parent 55fa71e09b
commit 199e7e99d1
23 changed files with 5038 additions and 1168 deletions

View File

@@ -0,0 +1,225 @@
# 🔄 Migration Guide: ParentId → NetworkParentId
## 📋 Overview
در سیستم قدیمی، کاربران با استفاده از `User.ParentId` به هم متصل می‌شدند (Parent-Child relationship).
سیستم جدید **Network-Club-Commission** از یک **Binary Tree** استفاده می‌کند که نیاز به:
- `User.NetworkParentId` (شناسه پدر در شبکه باینری)
- `User.LegPosition` (Left یا Right)
برای اجرای صحیح Worker و محاسبات، **باید** تمام کاربران قدیمی Migrate شوند.
---
## ⚠️ Critical Issues
### مشکل 1: Binary Tree Constraint
- هر Parent فقط می‌تواند **2 فرزند** داشته باشد (Left & Right)
- اگر کاربری در سیستم قدیمی بیشتر از 2 فرزند دارد، Migration فقط **2 فرزند اول** را می‌گیرد
### مشکل 2: Orphaned Nodes
- اگر `ParentId` اشاره به یک کاربر نامعتبر (حذف شده) باشد، آن User **Orphaned** است
- Orphaned nodes در Binary Tree نادیده گرفته می‌شوند
---
## 🚀 Migration Methods
### روش 1: Automatic (Seeder - توصیه می‌شود)
Migration به صورت خودکار در `Program.cs` در حالت **Development** اجرا می‌شود:
```csharp
// در Program.cs
var migrationSeeder = new NetworkParentIdMigrationSeeder(dbContext, logger);
await migrationSeeder.SeedAsync();
```
**مزایا:**
- ✅ Idempotent (می‌توان چندین بار اجرا کرد، فقط یکبار تاثیر می‌گذارد)
- ✅ Validation اتوماتیک
- ✅ Logging کامل
**کجا اجرا می‌شود؟**
- فقط در **Development** environment
- هر بار که پروژه Run شود
---
### روش 2: Manual (Command)
اگر نیاز به اجرای دستی دارید:
```csharp
// درخواست از طریق MediatR
var result = await _mediator.Send(new MigrateNetworkParentIdCommand());
if (result.Success)
{
Console.WriteLine($"Migrated: {result.MigratedCount}");
Console.WriteLine($"Skipped: {result.SkippedCount}");
}
else
{
Console.WriteLine($"Error: {result.Message}");
}
```
---
### روش 3: SQL Script
برای Production یا اجرای مستقیم روی Database:
```bash
# فایل: CMSMicroservice.Infrastructure/Migrations/Scripts/20250601_MigrateParentIdToNetworkParentId.sql
```
**نکته مهم:**
قبل از اجرا، **حتماً** بررسی کنید که آیا کاربری بیش از 2 فرزند دارد:
```sql
SELECT
ParentId,
COUNT(*) as ChildCount,
STRING_AGG(CAST(Id AS VARCHAR), ', ') as ChildIds
FROM Users
WHERE ParentId IS NOT NULL
GROUP BY ParentId
HAVING COUNT(*) > 2;
```
---
## 📊 Validation After Migration
### 1. بررسی تعداد کاربران Migrate شده
```csharp
var stats = await _context.Users
.GroupBy(u => 1)
.Select(g => new
{
TotalUsers = g.Count(),
UsersWithNetworkParent = g.Count(u => u.NetworkParentId != null),
LeftChildren = g.Count(u => u.LegPosition == NetworkLeg.Left),
RightChildren = g.Count(u => u.LegPosition == NetworkLeg.Right)
})
.FirstOrDefaultAsync();
```
### 2. بررسی Orphaned Nodes
```sql
SELECT Id, NetworkParentId
FROM Users
WHERE NetworkParentId IS NOT NULL
AND NetworkParentId NOT IN (SELECT Id FROM Users);
```
### 3. بررسی Binary Tree Violation
```sql
SELECT NetworkParentId, COUNT(*) as ChildCount
FROM Users
WHERE NetworkParentId IS NOT NULL
GROUP BY NetworkParentId
HAVING COUNT(*) > 2;
```
---
## ⚙️ Algorithm Details
### مراحل Migration:
1. **Find Users**: یافتن کاربران با `ParentId != NULL` و `NetworkParentId == NULL`
2. **Group by Parent**: گروه‌بندی بر اساس ParentId
3. **Check Constraint**: اگر Parent بیش از 2 فرزند دارد، فقط 2 تا اول را بگیر
4. **Assign Values**:
```csharp
child.NetworkParentId = parentId;
child.LegPosition = (i == 0) ? NetworkLeg.Left : NetworkLeg.Right;
```
5. **Save & Validate**: ذخیره و اعتبارسنجی Binary Tree
---
## 🐛 Troubleshooting
### مشکل: Parent has more than 2 children
**راه حل:**
تصمیم دستی بگیرید که کدام 2 فرزند را نگه دارید:
```sql
-- بررسی کنید که کدام Parent مشکل دارد
SELECT ParentId, COUNT(*) as ChildCount
FROM Users
WHERE ParentId = 123
GROUP BY ParentId;
-- لیست فرزندان را ببینید
SELECT Id, FullName, CreatedAt
FROM Users
WHERE ParentId = 123
ORDER BY CreatedAt;
-- دستی NetworkParentId را برای 2 فرزند انتخابی Set کنید
UPDATE Users
SET NetworkParentId = 123, LegPosition = 0 -- Left
WHERE Id = 456;
UPDATE Users
SET NetworkParentId = 123, LegPosition = 1 -- Right
WHERE Id = 789;
```
---
### مشکل: Orphaned Nodes (Parent doesn't exist)
**راه حل:**
ParentId را NULL کنید یا به یک Parent معتبر متصل کنید:
```sql
-- گزینه 1: NULL کردن (Root شدن)
UPDATE Users
SET ParentId = NULL, NetworkParentId = NULL
WHERE ParentId = 999; -- 999 وجود ندارد
-- گزینه 2: اتصال به Parent دیگر
UPDATE Users
SET ParentId = 1, NetworkParentId = 1
WHERE ParentId = 999;
```
---
## ✅ Checklist Before Production
- [ ] Migration در Development اجرا شده؟
- [ ] Validation Errors بررسی شد؟
- [ ] Orphaned Nodes رفع شدند؟
- [ ] Binary Tree Violations رفع شدند؟
- [ ] Backup از Database گرفته شده؟
- [ ] Migration Script برای Production آماده است؟
- [ ] Testing کامل انجام شده؟
---
## 🔗 Related Files
- **Seeder**: `CMSMicroservice.Infrastructure/Data/Seeding/NetworkParentIdMigrationSeeder.cs`
- **Command**: `CMSMicroservice.Application/UserCQ/Commands/MigrateNetworkParentId/`
- **SQL Script**: `CMSMicroservice.Infrastructure/Migrations/Scripts/20250601_MigrateParentIdToNetworkParentId.sql`
- **Entity**: `CMSMicroservice.Domain/Entities/User.cs` (خطوط 16, 45, 49)
---
## 📞 Support
اگر مشکل خاصی با Migration پیدا کردید:
1. Log های Seeder را بررسی کنید
2. ValidationErrors را چک کنید
3. SQL Script را به صورت دستی اجرا کنید