2022-10-28 14:17:10 +08:00
< ? php
namespace App\Jobs ;
2025-09-08 03:05:55 +07:00
use App\Models\BonusLogs ;
2025-10-14 14:54:44 +07:00
use App\Models\IpLog ;
2022-10-28 14:17:10 +08:00
use App\Models\Setting ;
use App\Models\User ;
2025-10-14 14:54:44 +07:00
use App\Repositories\IpLogRepository ;
2022-10-28 14:17:10 +08:00
use Illuminate\Bus\Queueable ;
use Illuminate\Contracts\Queue\ShouldBeUnique ;
use Illuminate\Contracts\Queue\ShouldQueue ;
use Illuminate\Foundation\Bus\Dispatchable ;
use Illuminate\Queue\InteractsWithQueue ;
2024-11-08 20:14:45 +08:00
use Illuminate\Queue\Middleware\WithoutOverlapping ;
2022-10-28 14:17:10 +08:00
use Illuminate\Queue\SerializesModels ;
use Nexus\Database\NexusDB ;
2024-02-21 21:11:16 +08:00
use Nexus\Nexus ;
2022-10-28 14:17:10 +08:00
2022-11-05 18:43:49 +08:00
class CalculateUserSeedBonus implements ShouldQueue
2022-10-28 14:17:10 +08:00
{
use Dispatchable , InteractsWithQueue , Queueable , SerializesModels ;
private int $beginUid ;
private int $endUid ;
2024-02-21 21:11:16 +08:00
private string $idStr ;
2023-07-15 01:44:48 +08:00
2022-11-05 18:43:49 +08:00
private string $requestId ;
2024-02-21 21:11:16 +08:00
private string $idRedisKey ;
2022-10-28 14:17:10 +08:00
/**
* Create a new job instance .
*
* @ return void
*/
2024-02-21 21:11:16 +08:00
public function __construct ( int $beginUid , int $endUid , string $idStr , string $idRedisKey , string $requestId = '' )
2022-10-28 14:17:10 +08:00
{
$this -> beginUid = $beginUid ;
$this -> endUid = $endUid ;
2024-02-21 21:11:16 +08:00
$this -> idStr = $idStr ;
$this -> idRedisKey = $idRedisKey ;
2022-11-05 18:43:49 +08:00
$this -> requestId = $requestId ;
}
2023-02-21 01:49:17 +08:00
public $tries = 1 ;
2025-12-18 13:09:54 +08:00
public $timeout = 120 ;
2023-02-21 01:49:17 +08:00
2024-11-08 20:14:45 +08:00
/**
* 获取任务时,应该通过的中间件。
*
* @ return array
*/
public function middleware ()
{
return [ new WithoutOverlapping ( $this -> idRedisKey )];
}
2022-10-28 14:17:10 +08:00
/**
* Execute the job .
*
* @ return void
*/
public function handle ()
{
2023-07-15 01:44:48 +08:00
$beginTimestamp = time ();
2024-11-08 20:14:45 +08:00
$logPrefix = sprintf (
" [CLEANUP_CLI_CALCULATE_SEED_BONUS_HANDLE_JOB], commonRequestId: %s, beginUid: %s, endUid: %s, idStr: %s, idRedisKey: %s " ,
$this -> requestId , $this -> beginUid , $this -> endUid , $this -> idStr , $this -> idRedisKey
);
2024-11-15 20:52:31 +08:00
do_log ( " $logPrefix , job start ... " );
2025-12-18 13:09:54 +08:00
2023-07-15 01:44:48 +08:00
$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' );
2024-02-21 21:11:16 +08:00
$idStr = $this -> idStr ;
$delIdRedisKey = false ;
if ( empty ( $idStr ) && ! empty ( $this -> idRedisKey )) {
$delIdRedisKey = true ;
$idStr = NexusDB :: cache_get ( $this -> idRedisKey );
}
if ( empty ( $idStr )) {
do_log ( " $logPrefix , no idStr or idRedisKey " , " error " );
return ;
}
$sql = sprintf ( " select %s from users where id in (%s) " , implode ( ',' , User :: $commonFields ), $idStr );
2023-07-15 01:44:48 +08:00
$results = NexusDB :: select ( $sql );
2025-09-08 03:05:55 +07:00
if ( empty ( $results )) {
do_log ( " $logPrefix , no data from idStr: $idStr " , " error " );
return ;
}
2023-07-15 01:44:48 +08:00
$logFile = getLogFile ( " seed-bonus-points " );
do_log ( " $logPrefix , [GET_UID_REAL], count: " . count ( $results ) . " , logFile: $logFile " );
$fd = fopen ( $logFile , 'a' );
2025-11-21 00:41:03 +07:00
$seedPointsUpdates = $seedPointsPerHourUpdates = $seedBonusPerHourUpdates = $seedBonusUpdates = [];
2025-06-09 02:29:15 +07:00
$seedingTorrentCountUpdates = $seedingTorrentSizeUpdates = [];
2024-11-07 03:35:21 +08:00
$logStr = " " ;
2025-09-08 03:05:55 +07:00
$bonusLogInsert = [];
2023-07-15 01:44:48 +08:00
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 );
2025-09-08 03:05:55 +07:00
$all_bonus = $basicBonus = $seedBonusResult [ 'seed_bonus' ];
2025-09-19 21:02:34 +07:00
$oldValue = $userInfo [ 'seedbonus' ];
2023-07-15 01:44:48 +08:00
$bonusLog .= " , all_bonus: $all_bonus " ;
2025-09-19 21:02:34 +07:00
$this -> appendBonusLogInsert ( $bonusLogInsert , $uid , BonusLogs :: BUSINESS_TYPE_SEEDING_BASIC , $oldValue , $basicBonus );
$oldValue += $basicBonus ;
2025-09-11 00:27:24 +07:00
/**
* BUG : can ' t add this , case when not include info in where condition $idStr will be reset to 0
* // BUG: 不能添加这部分, case when 不包含某些 uid 的数据,而 $idStr 里面又有,会被重置为 0
* // 而且 seed_points_per_hour, seeding count/size 这些也是要实时更新为0的, 不能添加这个跳过。
*/
// if ($all_bonus == 0) {
// do_log("$bonusLog, all_bonus is zero, skip");
// continue;
// }
2024-10-29 23:43:38 +08:00
if ( $isDonor && $donortimes_bonus != 0 ) {
2025-09-08 03:05:55 +07:00
$donorAddition = $basicBonus * $donortimes_bonus ;
$all_bonus += $donorAddition ;
2023-07-15 01:44:48 +08:00
$bonusLog .= " , isDonor, donortimes_bonus: $donortimes_bonus , all_bonus: $all_bonus " ;
2025-09-19 21:02:34 +07:00
$this -> appendBonusLogInsert ( $bonusLogInsert , $uid , BonusLogs :: BUSINESS_TYPE_SEEDING_DONOR_ADDITION , $oldValue , $donorAddition );
$oldValue += $donorAddition ;
2023-07-15 01:44:48 +08:00
}
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 " ;
2025-09-19 21:02:34 +07:00
$this -> appendBonusLogInsert ( $bonusLogInsert , $uid , BonusLogs :: BUSINESS_TYPE_SEEDING_OFFICIAL_ADDITION , $oldValue , $officialAddition );
$oldValue += $officialAddition ;
2023-07-15 01:44:48 +08:00
}
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 " ;
2025-09-19 21:02:34 +07:00
$this -> appendBonusLogInsert ( $bonusLogInsert , $uid , BonusLogs :: BUSINESS_TYPE_SEEDING_HAREM_ADDITION , $oldValue , $haremAddition );
$oldValue += $haremAddition ;
2023-07-15 01:44:48 +08:00
}
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 " ;
2025-09-19 21:02:34 +07:00
$this -> appendBonusLogInsert ( $bonusLogInsert , $uid , BonusLogs :: BUSINESS_TYPE_SEEDING_MEDAL_ADDITION , $oldValue , $medalAddition );
$oldValue += $medalAddition ;
2023-07-15 01:44:48 +08:00
}
2024-11-08 20:14:45 +08:00
do_log ( $bonusLog );
2023-07-15 01:44:48 +08:00
$dividend = 3600 / $autoclean_interval_one ;
$all_bonus = $all_bonus / $dividend ;
$seed_points = $seedBonusResult [ 'seed_points' ] / $dividend ;
2024-11-07 03:35:21 +08:00
// $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);
2024-11-08 20:14:45 +08:00
$seedPointsUpdates [] = sprintf ( " when %d then ifnull(seed_points, 0) + %f " , $uid , $seed_points );
$seedPointsPerHourUpdates [] = sprintf ( " when %d then %f " , $uid , $seedBonusResult [ 'seed_points' ]);
2025-11-21 00:41:03 +07:00
$seedBonusPerHourUpdates [] = sprintf ( " when %d then %f " , $uid , $seedBonusResult [ 'seed_bonus' ]);
2025-09-24 14:46:14 +07:00
$seedingTorrentCountUpdates [] = sprintf ( " when %d then %f " , $uid , $seedBonusResult [ 'torrent_peer_count' ]);
2025-06-09 02:29:15 +07:00
$seedingTorrentSizeUpdates [] = sprintf ( " when %d then %f " , $uid , $seedBonusResult [ 'size' ]);
2024-11-08 20:14:45 +08:00
$seedBonusUpdates [] = sprintf ( " when %d then seedbonus + %f " , $uid , $all_bonus );
2023-07-15 01:44:48 +08:00
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 , '.' , '' )
);
2024-11-07 03:35:21 +08:00
// fwrite($fd, $log . PHP_EOL);
$logStr .= $log . PHP_EOL ;
2023-07-15 01:44:48 +08:00
} else {
do_log ( " logFile: $logFile is not writeable! " , 'error' );
}
}
2024-11-07 03:35:21 +08:00
$nowStr = now () -> toDateTimeString ();
$sql = sprintf (
2025-11-21 00:41:03 +07:00
" update users set seed_points = case id %s end, seed_points_per_hour = case id %s end, seed_bonus_per_hour = case id %s end, seedbonus = case id %s end, seeding_torrent_count = case id %s end, seeding_torrent_size = case id %s end, seed_points_updated_at = '%s' where id in (%s) " ,
implode ( " " , $seedPointsUpdates ), implode ( " " , $seedPointsPerHourUpdates ), implode ( " " , $seedBonusPerHourUpdates ), implode ( " " , $seedBonusUpdates ), implode ( " " , $seedingTorrentCountUpdates ), implode ( " " , $seedingTorrentSizeUpdates ), $nowStr , $idStr
2024-11-07 03:35:21 +08:00
);
2024-11-07 20:53:23 +08:00
$result = NexusDB :: statement ( $sql );
2024-02-21 21:11:16 +08:00
if ( $delIdRedisKey ) {
NexusDB :: cache_del ( $this -> idRedisKey );
}
2025-09-19 21:02:34 +07:00
if ( $fd ) {
fwrite ( $fd , $logStr );
}
2025-09-08 03:05:55 +07:00
if ( ! empty ( $bonusLogInsert )) {
2025-09-19 21:02:34 +07:00
// BonusLogs::query()->insert($bonusLogInsert);
$this -> insertIntoClickHouseBulk ( $bonusLogInsert );
2025-09-08 03:05:55 +07:00
}
2023-07-15 01:44:48 +08:00
$costTime = time () - $beginTimestamp ;
2024-11-07 03:35:21 +08:00
do_log ( sprintf (
2024-11-08 04:05:37 +08:00
" $logPrefix , [DONE], update user count: %s, result: %s, cost time: %s seconds " ,
count ( $seedPointsUpdates ), var_export ( $result , true ), $costTime
2024-11-07 03:35:21 +08:00
));
2024-11-08 04:05:37 +08:00
do_log ( " $logPrefix , sql: $sql " , " debug " );
2022-10-28 14:17:10 +08:00
}
2023-02-21 01:04:28 +08:00
/**
* Handle a job failure .
*
* @ param \Throwable $exception
* @ return void
*/
public function failed ( \Throwable $exception )
{
do_log ( " failed: " . $exception -> getMessage () . $exception -> getTraceAsString (), 'error' );
}
2025-09-08 03:05:55 +07:00
2025-09-19 21:02:34 +07:00
private function appendBonusLogInsert ( array & $bonusLogInsert , int $uid , int $businessType , $oldValue , $delta ) : void
2025-09-08 03:05:55 +07:00
{
2025-09-19 21:02:34 +07:00
if ( $delta > 0 ) {
$bonusLogInsert [] = [
'business_type' => $businessType ,
'uid' => $uid ,
'old_total_value' => $oldValue ,
'value' => $delta ,
'new_total_value' => $oldValue + $delta ,
'comment' => BonusLogs :: $businessTypes [ $businessType ][ 'text' ] ? ? '' ,
'created_at' => getDtMicro (),
];
}
}
private function insertIntoClickHouseBulk ( array $bonusLogInsert ) : void
{
if ( ! Setting :: getIsRecordSeedingBonusLog ()) {
do_log ( " not enabled " );
return ;
}
$host = config ( 'clickhouse.connection.host' );
if ( ! $host ) {
do_log ( " clickhouse no host " );
return ;
2025-09-08 03:05:55 +07:00
}
2025-09-22 20:13:56 +07:00
try {
$client = app ( \ClickHouseDB\Client :: class );
$fields = [ 'business_type' , 'uid' , 'old_total_value' , 'value' , 'new_total_value' , 'comment' , 'created_at' ];
$client -> insert ( " bonus_logs " , $bonusLogInsert , $fields );
2025-10-14 14:54:44 +07:00
do_log ( " insertIntoClickHouseBulk done, created_at: { $bonusLogInsert [ 0 ][ 'created_at' ] } , count: " . count ( $bonusLogInsert ));
2025-09-22 20:13:56 +07:00
} catch ( \Exception $e ) {
do_log ( $e -> getMessage (), 'error' );
}
2025-09-08 03:05:55 +07:00
}
2022-10-28 14:17:10 +08:00
}