diff --git a/app/Console/Commands/Cleanup.php b/app/Console/Commands/Cleanup.php index 93543c15..d2a2d39e 100644 --- a/app/Console/Commands/Cleanup.php +++ b/app/Console/Commands/Cleanup.php @@ -14,14 +14,14 @@ class Cleanup extends Command * * @var string */ - protected $signature = 'cleanup {--action=} {--begin_id=} {--end_id=} {--request_id=} {--delay=}'; + protected $signature = 'cleanup {--action=} {--begin_id=} {--id_str=} {--end_id=} {--request_id=} {--delay=}'; /** * The console command description. * * @var string */ - protected $description = 'Cleanup async job trigger, options: --begin_id, --end_id, --request_id, --delay, --action (seed_bonus, seeding_leeching_time, seeders_etc)'; + protected $description = 'Cleanup async job trigger, options: --begin_id, --end_id, --id_str, --request_id, --delay, --action (seed_bonus, seeding_leeching_time, seeders_etc)'; /** * Execute the console command. @@ -33,15 +33,16 @@ class Cleanup extends Command $action = $this->option('action'); $beginId = $this->option('begin_id'); $endId = $this->option('end_id'); + $idStr = $this->option('id_str'); $commentRequestId = $this->option('request_id'); $delay = $this->option('delay') ?: 0; - $this->info("beginId: $beginId, endId: $endId, commentRequestId: $commentRequestId, delay: $delay, action: $action"); + $this->info("beginId: $beginId, endId: $endId, idStr: $idStr, commentRequestId: $commentRequestId, delay: $delay, action: $action"); if ($action == 'seed_bonus') { - CalculateUserSeedBonus::dispatch($beginId, $endId, $commentRequestId)->delay($delay); + CalculateUserSeedBonus::dispatch($beginId, $endId, $idStr, $commentRequestId)->delay($delay); } elseif ($action == 'seeding_leeching_time') { - UpdateUserSeedingLeechingTime::dispatch($beginId, $endId, $commentRequestId)->delay($delay); + UpdateUserSeedingLeechingTime::dispatch($beginId, $endId, $idStr, $commentRequestId)->delay($delay); }elseif ($action == 'seeders_etc') { - UpdateTorrentSeedersEtc::dispatch($beginId, $endId, $commentRequestId)->delay($delay); + UpdateTorrentSeedersEtc::dispatch($beginId, $endId, $idStr, $commentRequestId)->delay($delay); } else { $msg = "[$commentRequestId], Invalid action: $action"; do_log($msg, 'error'); diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index d197a4d1..20df6081 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -98,9 +98,8 @@ class Test extends Command */ public function handle() { - $redis = NexusDB::redis(); - $r = CleanupRepository::recordBatch($redis, 99, 100); - dd($r); + CleanupRepository::recordBatch(NexusDB::redis(), "1", "5"); + CleanupRepository::runBatchJobCalculateUserSeedBonus("bbbbb"); } } diff --git a/app/Jobs/CalculateUserSeedBonus.php b/app/Jobs/CalculateUserSeedBonus.php index 4136c069..5ec3be37 100644 --- a/app/Jobs/CalculateUserSeedBonus.php +++ b/app/Jobs/CalculateUserSeedBonus.php @@ -4,7 +4,6 @@ namespace App\Jobs; use App\Models\Setting; use App\Models\User; -use App\Repositories\CleanupRepository; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldQueue; @@ -21,6 +20,8 @@ class CalculateUserSeedBonus implements ShouldQueue private int $endUid; + private string $uidArrStr; + private string $requestId; /** @@ -28,10 +29,11 @@ class CalculateUserSeedBonus implements ShouldQueue * * @return void */ - public function __construct(int $beginUid, int $endUid, string $requestId = '') + public function __construct(int $beginUid, int $endUid, string $uidArrStr, string $requestId = '') { $this->beginUid = $beginUid; $this->endUid = $endUid; + $this->uidArrStr = $uidArrStr; $this->requestId = $requestId; } @@ -47,7 +49,7 @@ class CalculateUserSeedBonus implements ShouldQueue public $tries = 1; - public $timeout = 3600; + public $timeout = 600; /** * Execute the job. @@ -56,7 +58,74 @@ class CalculateUserSeedBonus implements ShouldQueue */ public function handle() { - CleanupRepository::runBatchJob(CleanupRepository::USER_SEED_BONUS_BATCH_KEY, $this->requestId); + $beginTimestamp = time(); + $logPrefix = sprintf("[CLEANUP_CLI_CALCULATE_SEED_BONUS_HANDLE_JOB], commonRequestId: %s, beginUid: %s, endUid: %s", $this->requestId, $this->beginUid, $this->endUid); +// $sql = sprintf("select userid from peers where userid > %s and userid <= %s and seeder = 'yes' group by userid", $this->beginUid, $this->endUid); +// $results = NexusDB::select($sql); +// $count = count($results); +// do_log("$logPrefix, [GET_UID], sql: $sql, count: " . count($results)); +// if ($count == 0) { +// do_log("$logPrefix, no user..."); +// return; +// } + $haremAdditionFactor = Setting::get('bonus.harem_addition'); + $officialAdditionFactor = Setting::get('bonus.official_addition'); + $donortimes_bonus = Setting::get('bonus.donortimes'); + $autoclean_interval_one = Setting::get('main.autoclean_interval_one'); + $sql = sprintf("select %s from users where id in (%s)", implode(',', User::$commonFields), $this->uidArrStr); + $results = NexusDB::select($sql); + $logFile = getLogFile("seed-bonus-points"); + do_log("$logPrefix, [GET_UID_REAL], count: " . count($results) . ", logFile: $logFile"); + $fd = fopen($logFile, 'a'); + foreach ($results as $userInfo) + { + $uid = $userInfo['id']; + $isDonor = is_donor($userInfo); + $seedBonusResult = calculate_seed_bonus($uid); + $bonusLog = "[CLEANUP_CLI_CALCULATE_SEED_BONUS_HANDLE_USER], user: $uid, seedBonusResult: " . nexus_json_encode($seedBonusResult); + $all_bonus = $seedBonusResult['seed_bonus']; + $bonusLog .= ", all_bonus: $all_bonus"; + if ($isDonor) { + $all_bonus = $all_bonus * $donortimes_bonus; + $bonusLog .= ", isDonor, donortimes_bonus: $donortimes_bonus, all_bonus: $all_bonus"; + } + if ($officialAdditionFactor > 0) { + $officialAddition = $seedBonusResult['official_bonus'] * $officialAdditionFactor; + $all_bonus += $officialAddition; + $bonusLog .= ", officialAdditionFactor: $officialAdditionFactor, official_bonus: {$seedBonusResult['official_bonus']}, officialAddition: $officialAddition, all_bonus: $all_bonus"; + } + if ($haremAdditionFactor > 0) { + $haremBonus = calculate_harem_addition($uid); + $haremAddition = $haremBonus * $haremAdditionFactor; + $all_bonus += $haremAddition; + $bonusLog .= ", haremAdditionFactor: $haremAdditionFactor, haremBonus: $haremBonus, haremAddition: $haremAddition, all_bonus: $all_bonus"; + } + if ($seedBonusResult['medal_additional_factor'] > 0) { + $medalAddition = $seedBonusResult['medal_bonus'] * $seedBonusResult['medal_additional_factor']; + $all_bonus += $medalAddition; + $bonusLog .= ", medalAdditionFactor: {$seedBonusResult['medal_additional_factor']}, medalBonus: {$seedBonusResult['medal_bonus']}, medalAddition: $medalAddition, all_bonus: $all_bonus"; + } + $dividend = 3600 / $autoclean_interval_one; + $all_bonus = $all_bonus / $dividend; + $seed_points = $seedBonusResult['seed_points'] / $dividend; + $updatedAt = now()->toDateTimeString(); + $sql = "update users set seed_points = ifnull(seed_points, 0) + $seed_points, seed_points_per_hour = {$seedBonusResult['seed_points']}, seedbonus = seedbonus + $all_bonus, seed_points_updated_at = '$updatedAt' where id = $uid limit 1"; + do_log("$bonusLog, query: $sql"); + NexusDB::statement($sql); + if ($fd) { + $log = sprintf( + '%s|%s|%s|%s|%s|%s|%s|%s', + date('Y-m-d H:i:s'), $uid, + $userInfo['seed_points'], number_format($seed_points, 1, '.', ''), number_format($userInfo['seed_points'] + $seed_points, 1, '.', ''), + $userInfo['seedbonus'], number_format($all_bonus, 1, '.', ''), number_format($userInfo['seedbonus'] + $all_bonus, 1, '.', '') + ); + fwrite($fd, $log . PHP_EOL); + } else { + do_log("logFile: $logFile is not writeable!", 'error'); + } + } + $costTime = time() - $beginTimestamp; + do_log("$logPrefix, [DONE], cost time: $costTime seconds"); } /** diff --git a/app/Jobs/UpdateTorrentSeedersEtc.php b/app/Jobs/UpdateTorrentSeedersEtc.php index 2fa155a4..5c8243bc 100644 --- a/app/Jobs/UpdateTorrentSeedersEtc.php +++ b/app/Jobs/UpdateTorrentSeedersEtc.php @@ -23,15 +23,18 @@ class UpdateTorrentSeedersEtc implements ShouldQueue private string $requestId; + private string $idStr; + /** * Create a new job instance. * * @return void */ - public function __construct(int $beginTorrentId, int $endTorrentId, string $requestId = '') + public function __construct(int $beginTorrentId, int $endTorrentId, string $idStr, string $requestId = '') { $this->beginTorrentId = $beginTorrentId; $this->endTorrentId = $endTorrentId; + $this->idStr = $idStr; $this->requestId = $requestId; } diff --git a/app/Jobs/UpdateUserSeedingLeechingTime.php b/app/Jobs/UpdateUserSeedingLeechingTime.php index 9700d2ff..4ceab6b6 100644 --- a/app/Jobs/UpdateUserSeedingLeechingTime.php +++ b/app/Jobs/UpdateUserSeedingLeechingTime.php @@ -23,15 +23,18 @@ class UpdateUserSeedingLeechingTime implements ShouldQueue private string $requestId; + private string $idStr; + /** * Create a new job instance. * * @return void */ - public function __construct(int $beginUid, int $endUid, string $requestId = '') + public function __construct(int $beginUid, int $endUid, string $idStr, string $requestId = '') { $this->beginUid = $beginUid; $this->endUid = $endUid; + $this->idStr = $idStr; $this->requestId = $requestId; } diff --git a/app/Repositories/CleanupRepository.php b/app/Repositories/CleanupRepository.php index cf5081fb..3419f183 100644 --- a/app/Repositories/CleanupRepository.php +++ b/app/Repositories/CleanupRepository.php @@ -12,6 +12,12 @@ class CleanupRepository extends BaseRepository const USER_SEEDING_LEECHING_TIME_BATCH_KEY = "batch_key:user_seeding_leeching_time"; const TORRENT_SEEDERS_ETC_BATCH_KEY = "batch_key:torrent_seeders_etc"; + private static int $totalTask = 3; + + private static int $oneTaskSeconds = 0; + + private static int $scanSize = 1000; + public static function recordBatch(\Redis $redis, $uid, $torrentId) { $args = [ @@ -26,6 +32,11 @@ class CleanupRepository extends BaseRepository return $result; } + public static function runBatchJobCalculateUserSeedBonus(string $requestId) + { + self::runBatchJob(self::USER_SEED_BONUS_BATCH_KEY, $requestId); + } + public static function runBatchJob($batchKey, $requestId) { $redis = NexusDB::redis(); @@ -40,9 +51,9 @@ class CleanupRepository extends BaseRepository //update the batch key $redis->set($batchKey, $batchKey . ":" . self::getHashKeySuffix()); $count = match ($batchKey) { - self::USER_SEEDING_LEECHING_TIME_BATCH_KEY => self::updateUserLeechingSeedingTime($redis, $batch, $logPrefix), - self::TORRENT_SEEDERS_ETC_BATCH_KEY => self::updateTorrentSeedersEtc($redis, $batch, $logPrefix), - self::USER_SEED_BONUS_BATCH_KEY => self::calculateUserSeedBonus($redis, $batch, $logPrefix), + self::USER_SEEDING_LEECHING_TIME_BATCH_KEY => self::updateUserLeechingSeedingTime($redis, $batch, $requestId), + self::TORRENT_SEEDERS_ETC_BATCH_KEY => self::updateTorrentSeedersEtc($redis, $batch, $requestId), + self::USER_SEED_BONUS_BATCH_KEY => self::calculateUserSeedBonus($redis, $batch, $requestId), default => throw new \InvalidArgumentException("Invalid batchKey: $batchKey") }; //remove this batch @@ -180,76 +191,59 @@ LUA; return date('Ymd_His'); } - private static function calculateUserSeedBonus(\Redis $redis, $batch, $logPrefix) + private static function calculateUserSeedBonus(\Redis $redis, $batch, $requestId): int { - $haremAdditionFactor = Setting::get('bonus.harem_addition'); - $officialAdditionFactor = Setting::get('bonus.official_addition'); - $donortimes_bonus = Setting::get('bonus.donortimes'); - $autoclean_interval_one = Setting::get('main.autoclean_interval_one'); - - $logFile = getLogFile("seed-bonus-points"); - do_log("$logPrefix, logFile: $logFile"); - $fd = fopen($logFile, 'a'); - $count = 0; - $size = 1000; $it = NULL; + $length = $redis->hLen($batch); + $page = 0; /* Don't ever return an empty array until we're done iterating */ $redis->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY); - while($arr_keys = $redis->hScan($batch, $it, "*", $size)) { - $uidArr = array_keys($arr_keys); - $sql = sprintf("select %s from users where id in (%s)", implode(',', User::$commonFields), implode(',', $uidArr)); - $results = NexusDB::select($sql); - foreach ($results as $userInfo) - { - $uid = $userInfo['id']; - $isDonor = is_donor($userInfo); - $seedBonusResult = calculate_seed_bonus($uid); - $bonusLog = "[CLEANUP_CLI_CALCULATE_SEED_BONUS], user: $uid, seedBonusResult: " . nexus_json_encode($seedBonusResult); - $all_bonus = $seedBonusResult['seed_bonus']; - $bonusLog .= ", all_bonus: $all_bonus"; - if ($isDonor) { - $all_bonus = $all_bonus * $donortimes_bonus; - $bonusLog .= ", isDonor, donortimes_bonus: $donortimes_bonus, all_bonus: $all_bonus"; - } - if ($officialAdditionFactor > 0) { - $officialAddition = $seedBonusResult['official_bonus'] * $officialAdditionFactor; - $all_bonus += $officialAddition; - $bonusLog .= ", officialAdditionFactor: $officialAdditionFactor, official_bonus: {$seedBonusResult['official_bonus']}, officialAddition: $officialAddition, all_bonus: $all_bonus"; - } - if ($haremAdditionFactor > 0) { - $haremBonus = calculate_harem_addition($uid); - $haremAddition = $haremBonus * $haremAdditionFactor; - $all_bonus += $haremAddition; - $bonusLog .= ", haremAdditionFactor: $haremAdditionFactor, haremBonus: $haremBonus, haremAddition: $haremAddition, all_bonus: $all_bonus"; - } - if ($seedBonusResult['medal_additional_factor'] > 0) { - $medalAddition = $seedBonusResult['medal_bonus'] * $seedBonusResult['medal_additional_factor']; - $all_bonus += $medalAddition; - $bonusLog .= ", medalAdditionFactor: {$seedBonusResult['medal_additional_factor']}, medalBonus: {$seedBonusResult['medal_bonus']}, medalAddition: $medalAddition, all_bonus: $all_bonus"; - } - $dividend = 3600 / $autoclean_interval_one; - $all_bonus = $all_bonus / $dividend; - $seed_points = $seedBonusResult['seed_points'] / $dividend; - $updatedAt = now()->toDateTimeString(); - $sql = "update users set seed_points = ifnull(seed_points, 0) + $seed_points, seed_points_per_hour = {$seedBonusResult['seed_points']}, seedbonus = seedbonus + $all_bonus, seed_points_updated_at = '$updatedAt' where id = $uid limit 1"; - do_log("$bonusLog, query: $sql"); - NexusDB::statement($sql); - if ($fd) { - $log = sprintf( - '%s|%s|%s|%s|%s|%s|%s|%s', - date('Y-m-d H:i:s'), $uid, - $userInfo['seed_points'], number_format($seed_points, 1, '.', ''), number_format($userInfo['seed_points'] + $seed_points, 1, '.', ''), - $userInfo['seedbonus'], number_format($all_bonus, 1, '.', ''), number_format($userInfo['seedbonus'] + $all_bonus, 1, '.', '') - ); - fwrite($fd, $log . PHP_EOL); - } else { - do_log("logFile: $logFile is not writeable!", 'error'); - } - } - sleep(rand(1, 10)); + while($arr_keys = $redis->hScan($batch, $it, "*", self::$scanSize)) { + $delay = self::getDelay(0, $length, $page); + $idStr = implode(",", array_keys($arr_keys)); + $command = sprintf( + 'cleanup --action=seed_bonus --begin_id=%s --end_id=%s --id_str=%s --request_id=%s --delay=%s', + 0, 0, $idStr, $requestId, $delay + ); + $output = executeCommand($command, 'string', true); + do_log(sprintf('command: %s, output: %s', $command, $output)); + $page++; + $count += count($arr_keys); } return $count; } + private static function getOneTaskSeconds(): float|int + { + if (self::$oneTaskSeconds == 0) { + //最低间隔,要在这个时间内执行掉全部任务 + $totalSeconds = get_setting("main.autoclean_interval_one"); + //每个任务能分到的秒数,不能到顶,任务数+1计算 + self::$oneTaskSeconds = floor($totalSeconds / (self::$totalTask + 1)); + } + return self::$oneTaskSeconds; + } + + private static function getDelayBase($taskIndex): float|int + { + return self::getOneTaskSeconds() * $taskIndex; + } + + private static function getDelay(int $taskIndex, int $length, int $page): float + { + //超始基数 + $base = self::getDelayBase($taskIndex); + //一共有这么多时间可以使用 + $totalSeconds = self::getOneTaskSeconds(); + //分几份 + $totalPage = ceil($length / self::$scanSize); + //每份多长 + $perPage = floor($totalSeconds / $totalPage); + //page 从 0 开始 + $offset = $page * $perPage; + + return floor($base + $offset); + } + } diff --git a/include/cleanup.php b/include/cleanup.php index 496a9e71..9d82512e 100644 --- a/include/cleanup.php +++ b/include/cleanup.php @@ -242,6 +242,7 @@ function docleanup($forceAll = 0, $printProgress = false) { global $enablenoad_advertisement, $noad_advertisement; global $Cache; global $rootpath; + $requestId = nexus()->getRequestId(); require_once($rootpath . '/lang/_target/lang_cleanup.php'); @@ -299,13 +300,7 @@ function docleanup($forceAll = 0, $printProgress = false) { // } // } - //chunk async - $command = sprintf( - 'cleanup --action=seed_bonus --begin_id=%s --end_id=%s --request_id=%s --delay=%s', - 0, 0, nexus()->getRequestId(), 0 - ); - $output = executeCommand($command, 'string', true); - do_log(sprintf('command: %s, output: %s', $command, $output)); + \App\Repositories\CleanupRepository::runBatchJobCalculateUserSeedBonus($requestId); $log = 'calculate seeding bonus'; do_log($log); diff --git a/include/constants.php b/include/constants.php index a975f47e..dbc74e58 100644 --- a/include/constants.php +++ b/include/constants.php @@ -1,6 +1,6 @@