clearUserRelationCache($ursUserId); // 获取用户的直接推荐人 $referral = UrsUserReferral::where('urs_user_id', $ursUserId) ->where('status', UrsUserReferral::STATUS_VALID) ->first(); if (!$referral) { Log::info("URS用户 {$ursUserId} 没有推荐人,无需生成关系缓存"); return true; } $ursReferrerId = $referral->urs_referrer_id; // 获取农场用户ID $farmUserId = UrsUserMappingService::getFarmUserId($ursUserId); $farmReferrerId = UrsUserMappingService::getFarmUserId($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; } // 创建直接关系缓存 $directRelation = new UrsUserRelationCache(); $directRelation->user_id = $farmUserId; $directRelation->related_user_id = $farmReferrerId; $directRelation->urs_user_id = $ursUserId; $directRelation->urs_related_user_id = $ursReferrerId; $directRelation->level = UrsPromotionRelationLevel::DIRECT; $directRelation->path = (string)$farmReferrerId; $directRelation->urs_path = (string)$ursReferrerId; $directRelation->depth = 1; $directRelation->save(); // 基于URS推荐关系链直接生成所有间接关系(不依赖缓存) $this->generateIndirectRelationsFromUrsChain($ursUserId, $farmUserId, $ursReferrerId, 1, (string)$ursReferrerId, (string)$farmReferrerId); // 清除Redis缓存 Redis::del("urs_promotion:user:{$ursUserId}:all_referrers"); Redis::del("urs_promotion:farm_user:{$farmUserId}:all_referrers"); Log::info("URS用户 {$ursUserId} 关系缓存生成成功"); return true; } catch (\Exception $e) { Log::error("生成URS用户关系缓存失败", [ 'urs_user_id' => $ursUserId, 'error' => $e->getMessage() ]); return false; } } /** * 基于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); } } /** * 清除用户的关系缓存 * * @param int $ursUserId URS用户ID * @return bool */ public function clearUserRelationCache(int $ursUserId): bool { try { // 获取农场用户ID $farmUserId = UrsUserMappingService::getFarmUserId($ursUserId); // 删除数据库中的关系缓存 UrsUserRelationCache::where('urs_user_id', $ursUserId)->delete(); // 清除Redis缓存 Redis::del("urs_promotion:user:{$ursUserId}:all_referrers"); if ($farmUserId > 0) { Redis::del("urs_promotion:farm_user:{$farmUserId}:all_referrers"); } return true; } catch (\Exception $e) { Log::error("清除URS用户关系缓存失败", [ 'urs_user_id' => $ursUserId, 'error' => $e->getMessage() ]); return false; } } /** * 重建所有用户的关系缓存 * * @param int $batchSize 批处理大小 * @param callable|null $progressCallback 进度回调函数 * @return array 包含成功和失败的数量 */ public function rebuildAllRelationCache(int $batchSize = 100, ?callable $progressCallback = null): array { try { // 清空关系缓存表 UrsUserRelationCache::truncate(); // 清除所有Redis缓存 $keys = Redis::keys("urs_promotion:user:*:all_referrers"); if (!empty($keys)) { Redis::del($keys); } $keys = Redis::keys("urs_promotion:farm_user:*:all_referrers"); if (!empty($keys)) { Redis::del($keys); } // 获取所有URS用户ID $ursUserIds = UrsUserReferral::where('status', UrsUserReferral::STATUS_VALID) ->pluck('urs_user_id') ->toArray(); $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 { $failCount++; } } } Log::info("URS关系缓存重建完成", [ 'success' => $successCount, 'fail' => $failCount, 'total' => count($ursUserIds) ]); return [ 'success' => $successCount, 'fail' => $failCount, 'total' => count($ursUserIds) ]; } catch (\Exception $e) { Log::error("重建所有URS关系缓存失败: " . $e->getMessage()); return [ 'success' => 0, 'fail' => 0, 'total' => 0, 'error' => $e->getMessage() ]; } } /** * 检查关系缓存的完整性 * * @return array 包含检查结果 */ public function checkRelationCacheIntegrity(): array { try { $totalUsers = UrsUserReferral::where('status', UrsUserReferral::STATUS_VALID)->count(); $usersWithCache = UrsUserRelationCache::distinct('urs_user_id')->count('urs_user_id'); $missingUsers = $totalUsers - $usersWithCache; // 检查循环推荐关系 $circularRelations = DB::select(" SELECT r1.urs_user_id, r1.urs_referrer_id FROM kku_urs_promotion_user_referrals r1 JOIN kku_urs_promotion_user_referrals r2 ON r1.urs_referrer_id = r2.urs_user_id WHERE r2.urs_referrer_id = r1.urs_user_id AND r1.status = 1 AND r2.status = 1 "); // 检查孤立的缓存 $orphanedCaches = DB::select(" SELECT c.urs_user_id FROM kku_urs_promotion_user_relation_cache c 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 "); return [ 'total_users' => $totalUsers, 'users_with_cache' => $usersWithCache, 'missing_users' => $missingUsers, 'circular_relations' => count($circularRelations), 'orphaned_caches' => count($orphanedCaches) ]; } catch (\Exception $e) { Log::error("检查URS关系缓存完整性失败: " . $e->getMessage()); return [ 'error' => $e->getMessage() ]; } } /** * 修复关系缓存问题 * * @param callable|null $progressCallback 进度回调函数 * @return array 包含修复结果 */ public function fixRelationCacheIssues(?callable $progressCallback = null): array { try { // 检查完整性 $integrity = $this->checkRelationCacheIntegrity(); $fixed = [ 'missing_users' => 0, 'orphaned_caches' => 0 ]; // 修复缺失的用户缓存 if ($integrity['missing_users'] > 0) { $usersWithCache = UrsUserRelationCache::distinct('urs_user_id')->pluck('urs_user_id')->toArray(); $allUsers = UrsUserReferral::where('status', UrsUserReferral::STATUS_VALID) ->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']++; } } } // 清理孤立的缓存 if ($integrity['orphaned_caches'] > 0) { $orphanedCaches = DB::select(" SELECT c.urs_user_id FROM kku_urs_promotion_user_relation_cache c 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']++; } } } return [ 'integrity' => $integrity, 'fixed' => $fixed ]; } catch (\Exception $e) { Log::error("修复URS关系缓存问题失败: " . $e->getMessage()); return [ 'error' => $e->getMessage() ]; } } /** * 为特定用户更新农场用户ID相关的缓存 * * @param int $ursUserId URS用户ID * @param int $farmUserId 农场用户ID * @return bool */ public function updateFarmUserIdInCache(int $ursUserId, int $farmUserId): bool { try { // 更新该用户作为被推荐人的缓存记录 UrsUserRelationCache::where('urs_user_id', $ursUserId) ->update(['user_id' => $farmUserId]); // 更新该用户作为推荐人的缓存记录(将占位的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, 'updated_placeholder_count' => $updatedCount ]); return true; } catch (\Exception $e) { Log::error("更新URS用户关系缓存中的农场用户ID失败", [ 'urs_user_id' => $ursUserId, 'farm_user_id' => $farmUserId, 'error' => $e->getMessage() ]); 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() ]); } } }