|
|
@@ -46,9 +46,42 @@ class UrsRelationCacheLogic
|
|
|
$farmUserId = UrsUserMappingService::getFarmUserId($ursUserId);
|
|
|
$farmReferrerId = UrsUserMappingService::getFarmUserId($ursReferrerId);
|
|
|
|
|
|
- // 如果农场用户ID为0,跳过缓存生成
|
|
|
- if ($farmUserId <= 0 || $farmReferrerId <= 0) {
|
|
|
- Log::info("URS用户 {$ursUserId} 或推荐人 {$ursReferrerId} 未进入农场,跳过缓存生成");
|
|
|
+ // 如果当前用户未进入农场,无法生成缓存
|
|
|
+ if ($farmUserId <= 0) {
|
|
|
+ Log::info("URS用户 {$ursUserId} 未进入农场,跳过缓存生成");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果推荐人未进入农场,创建占位缓存记录,避免断代问题
|
|
|
+ if ($farmReferrerId <= 0) {
|
|
|
+ Log::info("URS用户 {$ursUserId} 的推荐人 {$ursReferrerId} 未进入农场,创建占位缓存记录");
|
|
|
+
|
|
|
+ // 检查是否已存在该深度的缓存记录,避免重复插入
|
|
|
+ $existingCache = UrsUserRelationCache::where('urs_user_id', $ursUserId)
|
|
|
+ ->where('urs_related_user_id', $ursReferrerId)
|
|
|
+ ->where('depth', 1)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (!$existingCache) {
|
|
|
+ // 创建占位的直接关系缓存(农场用户ID为0)
|
|
|
+ $directRelation = new UrsUserRelationCache();
|
|
|
+ $directRelation->user_id = $farmUserId;
|
|
|
+ $directRelation->related_user_id = 0; // 推荐人未进入农场,设为0
|
|
|
+ $directRelation->urs_user_id = $ursUserId;
|
|
|
+ $directRelation->urs_related_user_id = $ursReferrerId;
|
|
|
+ $directRelation->level = UrsPromotionRelationLevel::DIRECT;
|
|
|
+ $directRelation->path = '0'; // 占位路径
|
|
|
+ $directRelation->urs_path = (string)$ursReferrerId;
|
|
|
+ $directRelation->depth = 1;
|
|
|
+ $directRelation->save();
|
|
|
+ } else {
|
|
|
+ Log::debug("URS用户 {$ursUserId} 的占位缓存记录已存在,跳过创建");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 尝试获取推荐人的上级关系(基于URS关系)
|
|
|
+ $this->generateIndirectRelationsFromUrsChain($ursUserId, $farmUserId, $ursReferrerId, 1, (string)$ursReferrerId, '0');
|
|
|
+
|
|
|
+ Log::info("URS用户 {$ursUserId} 占位缓存记录创建完成");
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
@@ -64,31 +97,8 @@ class UrsRelationCacheLogic
|
|
|
$directRelation->depth = 1;
|
|
|
$directRelation->save();
|
|
|
|
|
|
- // 获取推荐人的所有上级(限制在20代以内)
|
|
|
- $upperRelations = UrsUserRelationCache::where('urs_user_id', $ursReferrerId)
|
|
|
- ->where('depth', '<', UrsPromotionRelationLevel::getMaxLevel())
|
|
|
- ->get();
|
|
|
-
|
|
|
- // 创建间接关系缓存(最多20代)
|
|
|
- foreach ($upperRelations as $upperRelation) {
|
|
|
- $newDepth = $upperRelation->depth + 1;
|
|
|
-
|
|
|
- // 限制最大深度为20代
|
|
|
- if ($newDepth > UrsPromotionRelationLevel::getMaxLevel()) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- $indirectRelation = new UrsUserRelationCache();
|
|
|
- $indirectRelation->user_id = $farmUserId;
|
|
|
- $indirectRelation->related_user_id = $upperRelation->related_user_id;
|
|
|
- $indirectRelation->urs_user_id = $ursUserId;
|
|
|
- $indirectRelation->urs_related_user_id = $upperRelation->urs_related_user_id;
|
|
|
- $indirectRelation->level = UrsPromotionRelationLevel::getLevelByDepth($newDepth);
|
|
|
- $indirectRelation->path = $farmReferrerId . ',' . $upperRelation->path;
|
|
|
- $indirectRelation->urs_path = $ursReferrerId . ',' . $upperRelation->urs_path;
|
|
|
- $indirectRelation->depth = $newDepth;
|
|
|
- $indirectRelation->save();
|
|
|
- }
|
|
|
+ // 基于URS推荐关系链直接生成所有间接关系(不依赖缓存)
|
|
|
+ $this->generateIndirectRelationsFromUrsChain($ursUserId, $farmUserId, $ursReferrerId, 1, (string)$ursReferrerId, (string)$farmReferrerId);
|
|
|
|
|
|
// 清除Redis缓存
|
|
|
Redis::del("urs_promotion:user:{$ursUserId}:all_referrers");
|
|
|
@@ -105,6 +115,108 @@ class UrsRelationCacheLogic
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 基于URS关系链生成间接关系缓存
|
|
|
+ *
|
|
|
+ * 当推荐人未进入农场时,通过URS推荐关系链向上查找已进入农场的上级
|
|
|
+ *
|
|
|
+ * @param int $ursUserId 当前用户的URS用户ID
|
|
|
+ * @param int $farmUserId 当前用户的农场用户ID
|
|
|
+ * @param int $currentUrsReferrerId 当前层级的URS推荐人ID
|
|
|
+ * @param int $currentDepth 当前深度
|
|
|
+ * @param string $currentUrsPath 当前URS路径链
|
|
|
+ * @param string $currentFarmPath 当前农场路径链
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ private function generateIndirectRelationsFromUrsChain(int $ursUserId, int $farmUserId, int $currentUrsReferrerId, int $currentDepth, string $currentUrsPath = '', string $currentFarmPath = ''): void
|
|
|
+ {
|
|
|
+ // 限制最大深度为20代
|
|
|
+ if ($currentDepth >= UrsPromotionRelationLevel::getMaxLevel()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前推荐人的推荐人
|
|
|
+ $upperReferral = UrsUserReferral::where('urs_user_id', $currentUrsReferrerId)
|
|
|
+ ->where('status', UrsUserReferral::STATUS_VALID)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (!$upperReferral) {
|
|
|
+ // 没有更上级的推荐人,结束递归
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $upperUrsReferrerId = $upperReferral->urs_referrer_id;
|
|
|
+ $upperFarmReferrerId = UrsUserMappingService::getFarmUserId($upperUrsReferrerId);
|
|
|
+ $newDepth = $currentDepth + 1;
|
|
|
+
|
|
|
+ // 构建新的路径链
|
|
|
+ $newUrsPath = empty($currentUrsPath) ? (string)$upperUrsReferrerId : $currentUrsPath . ',' . $upperUrsReferrerId;
|
|
|
+ $currentFarmReferrerId = UrsUserMappingService::getFarmUserId($currentUrsReferrerId);
|
|
|
+ $currentFarmPart = $currentFarmReferrerId > 0 ? (string)$currentFarmReferrerId : '0';
|
|
|
+ $upperFarmPart = $upperFarmReferrerId > 0 ? (string)$upperFarmReferrerId : '0';
|
|
|
+ $newFarmPath = empty($currentFarmPath) ? $upperFarmPart : $currentFarmPath . ',' . $upperFarmPart;
|
|
|
+
|
|
|
+ if ($upperFarmReferrerId > 0) {
|
|
|
+ // 检查是否已存在该深度的关系缓存
|
|
|
+ $existingCache = UrsUserRelationCache::where('urs_user_id', $ursUserId)
|
|
|
+ ->where('urs_related_user_id', $upperUrsReferrerId)
|
|
|
+ ->where('depth', $newDepth)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (!$existingCache) {
|
|
|
+ // 上级推荐人已进入农场,创建有效的关系缓存
|
|
|
+ $indirectRelation = new UrsUserRelationCache();
|
|
|
+ $indirectRelation->user_id = $farmUserId;
|
|
|
+ $indirectRelation->related_user_id = $upperFarmReferrerId;
|
|
|
+ $indirectRelation->urs_user_id = $ursUserId;
|
|
|
+ $indirectRelation->urs_related_user_id = $upperUrsReferrerId;
|
|
|
+ $indirectRelation->level = UrsPromotionRelationLevel::getLevelByDepth($newDepth);
|
|
|
+ $indirectRelation->path = $newFarmPath;
|
|
|
+ $indirectRelation->urs_path = $newUrsPath;
|
|
|
+ $indirectRelation->depth = $newDepth;
|
|
|
+ $indirectRelation->save();
|
|
|
+ }
|
|
|
+
|
|
|
+ Log::debug("为URS用户 {$ursUserId} 创建间接关系缓存", [
|
|
|
+ 'upper_urs_referrer_id' => $upperUrsReferrerId,
|
|
|
+ 'upper_farm_referrer_id' => $upperFarmReferrerId,
|
|
|
+ 'depth' => $newDepth
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 继续向上递归查找,基于URS推荐关系链
|
|
|
+ $this->generateIndirectRelationsFromUrsChain($ursUserId, $farmUserId, $upperUrsReferrerId, $newDepth, $newUrsPath, $newFarmPath);
|
|
|
+ } else {
|
|
|
+ // 检查是否已存在该深度的占位缓存
|
|
|
+ $existingCache = UrsUserRelationCache::where('urs_user_id', $ursUserId)
|
|
|
+ ->where('urs_related_user_id', $upperUrsReferrerId)
|
|
|
+ ->where('depth', $newDepth)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (!$existingCache) {
|
|
|
+ // 上级推荐人也未进入农场,创建占位缓存并继续向上查找
|
|
|
+ $indirectRelation = new UrsUserRelationCache();
|
|
|
+ $indirectRelation->user_id = $farmUserId;
|
|
|
+ $indirectRelation->related_user_id = 0; // 占位
|
|
|
+ $indirectRelation->urs_user_id = $ursUserId;
|
|
|
+ $indirectRelation->urs_related_user_id = $upperUrsReferrerId;
|
|
|
+ $indirectRelation->level = UrsPromotionRelationLevel::getLevelByDepth($newDepth);
|
|
|
+ $indirectRelation->path = $newFarmPath;
|
|
|
+ $indirectRelation->urs_path = $newUrsPath;
|
|
|
+ $indirectRelation->depth = $newDepth;
|
|
|
+ $indirectRelation->save();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 继续向上递归查找
|
|
|
+ $this->generateIndirectRelationsFromUrsChain($ursUserId, $farmUserId, $upperUrsReferrerId, $newDepth, $newUrsPath, $newFarmPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 清除用户的关系缓存
|
|
|
*
|
|
|
@@ -140,9 +252,10 @@ class UrsRelationCacheLogic
|
|
|
* 重建所有用户的关系缓存
|
|
|
*
|
|
|
* @param int $batchSize 批处理大小
|
|
|
+ * @param callable|null $progressCallback 进度回调函数
|
|
|
* @return array 包含成功和失败的数量
|
|
|
*/
|
|
|
- public function rebuildAllRelationCache(int $batchSize = 100): array
|
|
|
+ public function rebuildAllRelationCache(int $batchSize = 100, ?callable $progressCallback = null): array
|
|
|
{
|
|
|
try {
|
|
|
// 清空关系缓存表
|
|
|
@@ -165,12 +278,21 @@ class UrsRelationCacheLogic
|
|
|
|
|
|
$successCount = 0;
|
|
|
$failCount = 0;
|
|
|
+ $totalUsers = count($ursUserIds);
|
|
|
+ $processedCount = 0;
|
|
|
|
|
|
// 分批处理
|
|
|
$chunks = array_chunk($ursUserIds, $batchSize);
|
|
|
|
|
|
foreach ($chunks as $chunk) {
|
|
|
foreach ($chunk as $ursUserId) {
|
|
|
+ $processedCount++;
|
|
|
+
|
|
|
+ // 调用进度回调函数
|
|
|
+ if ($progressCallback) {
|
|
|
+ $progressCallback($ursUserId, $processedCount, $totalUsers, $successCount, $failCount);
|
|
|
+ }
|
|
|
+
|
|
|
if ($this->generateUserRelationCache($ursUserId)) {
|
|
|
$successCount++;
|
|
|
} else {
|
|
|
@@ -248,9 +370,10 @@ class UrsRelationCacheLogic
|
|
|
/**
|
|
|
* 修复关系缓存问题
|
|
|
*
|
|
|
+ * @param callable|null $progressCallback 进度回调函数
|
|
|
* @return array 包含修复结果
|
|
|
*/
|
|
|
- public function fixRelationCacheIssues(): array
|
|
|
+ public function fixRelationCacheIssues(?callable $progressCallback = null): array
|
|
|
{
|
|
|
try {
|
|
|
// 检查完整性
|
|
|
@@ -268,8 +391,17 @@ class UrsRelationCacheLogic
|
|
|
->pluck('urs_user_id')
|
|
|
->toArray();
|
|
|
$missingUsers = array_diff($allUsers, $usersWithCache);
|
|
|
+ $totalMissing = count($missingUsers);
|
|
|
+ $processedMissing = 0;
|
|
|
|
|
|
foreach ($missingUsers as $ursUserId) {
|
|
|
+ $processedMissing++;
|
|
|
+
|
|
|
+ // 调用进度回调函数
|
|
|
+ if ($progressCallback) {
|
|
|
+ $progressCallback('missing', $ursUserId, $processedMissing, $totalMissing, $fixed['missing_users']);
|
|
|
+ }
|
|
|
+
|
|
|
if ($this->generateUserRelationCache($ursUserId)) {
|
|
|
$fixed['missing_users']++;
|
|
|
}
|
|
|
@@ -284,8 +416,17 @@ class UrsRelationCacheLogic
|
|
|
LEFT JOIN kku_urs_promotion_user_referrals r ON c.urs_user_id = r.urs_user_id AND r.status = 1
|
|
|
WHERE r.urs_user_id IS NULL
|
|
|
");
|
|
|
+ $totalOrphaned = count($orphanedCaches);
|
|
|
+ $processedOrphaned = 0;
|
|
|
|
|
|
foreach ($orphanedCaches as $cache) {
|
|
|
+ $processedOrphaned++;
|
|
|
+
|
|
|
+ // 调用进度回调函数
|
|
|
+ if ($progressCallback) {
|
|
|
+ $progressCallback('orphaned', $cache->urs_user_id, $processedOrphaned, $totalOrphaned, $fixed['orphaned_caches']);
|
|
|
+ }
|
|
|
+
|
|
|
if ($this->clearUserRelationCache($cache->urs_user_id)) {
|
|
|
$fixed['orphaned_caches']++;
|
|
|
}
|
|
|
@@ -318,16 +459,31 @@ class UrsRelationCacheLogic
|
|
|
UrsUserRelationCache::where('urs_user_id', $ursUserId)
|
|
|
->update(['user_id' => $farmUserId]);
|
|
|
|
|
|
- // 更新该用户作为推荐人的缓存记录
|
|
|
- UrsUserRelationCache::where('urs_related_user_id', $ursUserId)
|
|
|
+ // 更新该用户作为推荐人的缓存记录(将占位的0更新为实际农场用户ID)
|
|
|
+ $updatedCount = UrsUserRelationCache::where('urs_related_user_id', $ursUserId)
|
|
|
+ ->where('related_user_id', 0) // 只更新占位记录
|
|
|
->update(['related_user_id' => $farmUserId]);
|
|
|
|
|
|
+ if ($updatedCount > 0) {
|
|
|
+ Log::info("更新了 {$updatedCount} 条占位缓存记录", [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'farm_user_id' => $farmUserId
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 更新路径中的占位符
|
|
|
+ $this->updatePlaceholderPaths($ursUserId, $farmUserId);
|
|
|
+ }
|
|
|
+
|
|
|
// 重新生成该用户的关系缓存(确保路径正确)
|
|
|
$this->generateUserRelationCache($ursUserId);
|
|
|
|
|
|
+ // 为该用户的所有下级重新生成缓存(修复断代问题)
|
|
|
+ $this->regenerateDownstreamCaches($ursUserId);
|
|
|
+
|
|
|
Log::info("URS用户关系缓存中的农场用户ID更新成功", [
|
|
|
'urs_user_id' => $ursUserId,
|
|
|
- 'farm_user_id' => $farmUserId
|
|
|
+ 'farm_user_id' => $farmUserId,
|
|
|
+ 'updated_placeholder_count' => $updatedCount
|
|
|
]);
|
|
|
|
|
|
return true;
|
|
|
@@ -340,4 +496,95 @@ class UrsRelationCacheLogic
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新路径中的占位符
|
|
|
+ *
|
|
|
+ * @param int $ursUserId URS用户ID
|
|
|
+ * @param int $farmUserId 农场用户ID
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ private function updatePlaceholderPaths(int $ursUserId, int $farmUserId): void
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 获取所有包含该用户的路径记录
|
|
|
+ $records = UrsUserRelationCache::where('urs_path', 'LIKE', "%{$ursUserId}%")->get();
|
|
|
+
|
|
|
+ foreach ($records as $record) {
|
|
|
+ $pathParts = explode(',', $record->path);
|
|
|
+ $ursPathParts = explode(',', $record->urs_path);
|
|
|
+
|
|
|
+ // 找到URS路径中对应的位置,更新农场用户路径
|
|
|
+ $ursIndex = array_search((string)$ursUserId, $ursPathParts);
|
|
|
+ if ($ursIndex !== false && isset($pathParts[$ursIndex]) && $pathParts[$ursIndex] === '0') {
|
|
|
+ $pathParts[$ursIndex] = (string)$farmUserId;
|
|
|
+ $record->path = implode(',', $pathParts);
|
|
|
+ $record->save();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Log::debug("更新路径占位符完成", [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'farm_user_id' => $farmUserId,
|
|
|
+ 'updated_records' => $records->count()
|
|
|
+ ]);
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::warning("更新路径占位符失败", [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'farm_user_id' => $farmUserId,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 为用户的所有下级重新生成缓存
|
|
|
+ *
|
|
|
+ * 当用户进入农场后,需要为其所有下级重新生成缓存以修复断代问题
|
|
|
+ *
|
|
|
+ * @param int $ursUserId URS用户ID
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ private function regenerateDownstreamCaches(int $ursUserId): void
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 获取该用户的所有直接下级
|
|
|
+ $directSubordinates = UrsUserReferral::where('urs_referrer_id', $ursUserId)
|
|
|
+ ->where('status', UrsUserReferral::STATUS_VALID)
|
|
|
+ ->pluck('urs_user_id')
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ if (empty($directSubordinates)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Log::info("开始为用户的下级重新生成缓存", [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'subordinate_count' => count($directSubordinates)
|
|
|
+ ]);
|
|
|
+
|
|
|
+ foreach ($directSubordinates as $subordinateUrsUserId) {
|
|
|
+ // 检查下级是否已进入农场
|
|
|
+ $subordinateFarmUserId = UrsUserMappingService::getFarmUserId($subordinateUrsUserId);
|
|
|
+ if ($subordinateFarmUserId > 0) {
|
|
|
+ // 重新生成下级的关系缓存
|
|
|
+ $this->generateUserRelationCache($subordinateUrsUserId);
|
|
|
+
|
|
|
+ // 递归处理下级的下级
|
|
|
+ $this->regenerateDownstreamCaches($subordinateUrsUserId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Log::info("用户下级缓存重新生成完成", [
|
|
|
+ 'urs_user_id' => $ursUserId
|
|
|
+ ]);
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error("重新生成下级缓存失败", [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|