|
|
@@ -0,0 +1,334 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\UrsPromotion\Logics;
|
|
|
+
|
|
|
+use App\Module\UrsPromotion\Enums\UrsPromotionRelationLevel;
|
|
|
+use App\Module\UrsPromotion\Models\UrsUserReferral;
|
|
|
+use App\Module\UrsPromotion\Models\UrsUserRelationCache;
|
|
|
+use App\Module\UrsPromotion\Services\UrsUserMappingService;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
+use Illuminate\Support\Facades\Redis;
|
|
|
+
|
|
|
+/**
|
|
|
+ * URS关系缓存逻辑类
|
|
|
+ *
|
|
|
+ * 处理URS用户关系缓存的核心业务逻辑,包括生成关系缓存、清理关系缓存、
|
|
|
+ * 重建关系缓存等功能。该类仅供内部使用,不对外提供服务。
|
|
|
+ */
|
|
|
+class UrsRelationCacheLogic
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 生成用户的关系缓存
|
|
|
+ *
|
|
|
+ * @param int $ursUserId URS用户ID
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public function generateUserRelationCache(int $ursUserId): bool
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 清除用户的现有关系缓存
|
|
|
+ $this->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);
|
|
|
+
|
|
|
+ // 如果农场用户ID为0,跳过缓存生成
|
|
|
+ if ($farmUserId <= 0 || $farmReferrerId <= 0) {
|
|
|
+ Log::info("URS用户 {$ursUserId} 或推荐人 {$ursReferrerId} 未进入农场,跳过缓存生成");
|
|
|
+ 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();
|
|
|
+
|
|
|
+ // 获取推荐人的所有上级
|
|
|
+ $upperRelations = UrsUserRelationCache::where('urs_user_id', $ursReferrerId)->get();
|
|
|
+
|
|
|
+ // 创建间接关系缓存
|
|
|
+ foreach ($upperRelations as $upperRelation) {
|
|
|
+ $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::INDIRECT;
|
|
|
+ $indirectRelation->path = $farmReferrerId . ',' . $upperRelation->path;
|
|
|
+ $indirectRelation->urs_path = $ursReferrerId . ',' . $upperRelation->urs_path;
|
|
|
+ $indirectRelation->depth = $upperRelation->depth + 1;
|
|
|
+ $indirectRelation->save();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清除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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清除用户的关系缓存
|
|
|
+ *
|
|
|
+ * @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 批处理大小
|
|
|
+ * @return array 包含成功和失败的数量
|
|
|
+ */
|
|
|
+ public function rebuildAllRelationCache(int $batchSize = 100): 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;
|
|
|
+
|
|
|
+ // 分批处理
|
|
|
+ $chunks = array_chunk($ursUserIds, $batchSize);
|
|
|
+
|
|
|
+ foreach ($chunks as $chunk) {
|
|
|
+ foreach ($chunk as $ursUserId) {
|
|
|
+ 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()
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 修复关系缓存问题
|
|
|
+ *
|
|
|
+ * @return array 包含修复结果
|
|
|
+ */
|
|
|
+ public function fixRelationCacheIssues(): 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);
|
|
|
+
|
|
|
+ foreach ($missingUsers as $ursUserId) {
|
|
|
+ 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
|
|
|
+ ");
|
|
|
+
|
|
|
+ foreach ($orphanedCaches as $cache) {
|
|
|
+ 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]);
|
|
|
+
|
|
|
+ // 更新该用户作为推荐人的缓存记录
|
|
|
+ UrsUserRelationCache::where('urs_related_user_id', $ursUserId)
|
|
|
+ ->update(['related_user_id' => $farmUserId]);
|
|
|
+
|
|
|
+ // 重新生成该用户的关系缓存(确保路径正确)
|
|
|
+ $this->generateUserRelationCache($ursUserId);
|
|
|
+
|
|
|
+ Log::info("URS用户关系缓存中的农场用户ID更新成功", [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'farm_user_id' => $farmUserId
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error("更新URS用户关系缓存中的农场用户ID失败", [
|
|
|
+ 'urs_user_id' => $ursUserId,
|
|
|
+ 'farm_user_id' => $farmUserId,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
+ ]);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|