torrent bought user cache use hash + err() use warning message sometime

This commit is contained in:
xiaomlove
2023-06-08 01:59:28 +08:00
parent 98375f23ef
commit 3bf2b3591a
7 changed files with 181 additions and 24 deletions
+1 -3
View File
@@ -97,9 +97,7 @@ class Test extends Command
*/
public function handle()
{
$authkey = "12|52|abc";
$subAuthkey = substr($authkey, 0, strrpos($authkey, "|"));
$r = $subAuthkey;
$r = TorrentUpdated::dispatch(5);
dd($r);
}
@@ -0,0 +1,37 @@
<?php
namespace App\Console\Commands;
use App\Jobs\LoadTorrentBoughtUsers;
use App\Repositories\TorrentRepository;
use Illuminate\Console\Command;
class TorrentLoadBoughtUser extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'torrent:load_bought_user {torrent_id}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Load torrent all bought users. argument: torrent_id';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$torrentId = $this->argument('torrent_id');
LoadTorrentBoughtUsers::dispatch($torrentId);
do_log("torrentId: $torrentId");
return Command::SUCCESS;
}
}
+51
View File
@@ -0,0 +1,51 @@
<?php
namespace App\Jobs;
use App\Repositories\TorrentRepository;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class LoadTorrentBoughtUsers implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private int $torrentId;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(int $torrentId)
{
$this->torrentId = $torrentId;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$rep = new TorrentRepository();
$result = $rep->loadBoughtUser($this->torrentId);
do_log("result: $result");
}
/**
* Handle a job failure.
*
* @param \Throwable $exception
* @return void
*/
public function failed(\Throwable $exception)
{
do_log("failed: " . $exception->getMessage() . $exception->getTraceAsString(), 'error');
}
}
+40
View File
@@ -21,6 +21,7 @@ use App\Models\StaffMessage;
use App\Models\Standard;
use App\Models\Team;
use App\Models\Torrent;
use App\Models\TorrentBuyLog;
use App\Models\TorrentOperationLog;
use App\Models\TorrentSecret;
use App\Models\TorrentTag;
@@ -36,6 +37,8 @@ use Nexus\Database\NexusDB;
class TorrentRepository extends BaseRepository
{
const BOUGHT_USER_CACHE_KEY_PREFIX = "torrent_purchasers:";
/**
* fetch torrent list
*
@@ -715,4 +718,41 @@ HTML;
return sprintf('<span title="%s" style="vertical-align: %s"><svg t="1676058062789" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3406" width="%s" height="%s"><path d="M554.666667 810.666667v42.666666h-85.333334v-42.666666c-93.866667 0-170.666667-76.8-170.666666-170.666667h85.333333c0 46.933333 38.4 85.333333 85.333333 85.333333v-170.666666c-93.866667 0-170.666667-76.8-170.666666-170.666667s76.8-170.666667 170.666666-170.666667V170.666667h85.333334v42.666666c93.866667 0 170.666667 76.8 170.666666 170.666667h-85.333333c0-46.933333-38.4-85.333333-85.333333-85.333333v170.666666h17.066666c29.866667 0 68.266667 17.066667 98.133334 42.666667 34.133333 29.866667 59.733333 76.8 59.733333 128-4.266667 93.866667-81.066667 170.666667-174.933333 170.666667z m0-85.333334c46.933333 0 85.333333-38.4 85.333333-85.333333s-38.4-85.333333-85.333333-85.333333v170.666666zM469.333333 298.666667c-46.933333 0-85.333333 38.4-85.333333 85.333333s38.4 85.333333 85.333333 85.333333V298.666667z" fill="#CD7F32" p-id="3407"></path></svg></span>', nexus_trans('torrent.paid_torrent'), $verticalAlign, $size, $size);
}
public function loadBoughtUser($torrentId): int
{
$size = 500;
$page = 1;
$key = $this->getBoughtUserCacheKey($torrentId);
$redis = NexusDB::redis();
$total = 0;
while (true) {
$list = TorrentBuyLog::query()->where("torrent_id", $torrentId)->forPage($page, $size)->get(['torrent_id', 'uid']);
if ($list->isEmpty()) {
break;
}
foreach ($list as $item) {
$redis->hSet($key, $item->uid, 1);
$total += 1;
do_log(sprintf("hset %s %s 1", $key, $item->uid));
}
$page++;
}
do_log("torrent_purchasers:$torrentId LOAD DONE, total: $total");
if ($total > 0) {
$redis->expire($key, 86400*30);
}
return $total;
}
public function addBoughtUserToCache($torrentId, $uid)
{
NexusDB::redis()->hSet($this->getBoughtUserCacheKey($torrentId), $uid, 1);
}
private function getBoughtUserCacheKey($torrentId): string
{
return self::BOUGHT_USER_CACHE_KEY_PREFIX . $torrentId;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<?php
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.8.4');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2023-06-05');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2023-06-08');
defined('IN_TRACKER') || define('IN_TRACKER', false);
defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP");
defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org");
+25 -7
View File
@@ -61,17 +61,35 @@ function benc_resp_raw($x) {
else
echo $x;
}
function err($msg, $userid = 0, $torrentid = 0)
function err($msg)
{
benc_resp(['failure reason' => $msg]);
if (isset($GLOBALS['rep_dict'])) {
$d = $GLOBALS['rep_dict'];
} else {
$torrent = $GLOBALS['torrent'] ?? [];
$d = [
"interval" => (int)\App\Repositories\TrackerRepository::MIN_ANNOUNCE_WAIT_SECOND,
"min interval" => (int)\App\Repositories\TrackerRepository::MIN_ANNOUNCE_WAIT_SECOND,
"complete" => intval($torrent['seeders'] ?? 0),
"incomplete" => intval($torrent['leechers'] ?? 0),
"peers" => [],
];
if (!empty($_REQUEST['compact'])) {
$d['peers'] = ''; // Change `peers` from array to string
$d['peers6'] = ''; // If peer use IPv6 address , we should add packed string in `peers6`
}
}
if (!empty($_REQUEST['event'])) {
//keep fail response, next request keep event param
$d['failure reason'] = $msg;
} else {
//avoid retry frequent
$d['warning message'] = $msg;
}
benc_resp($d);
exit();
}
function warn($msg)
{
benc_resp(['warning message' => $msg]);
exit();
}
function check_cheater($userid, $torrentid, $uploaded, $downloaded, $anctime, $seeders=0, $leechers=0){
global $cheaterdet_security,$nodetect_security, $CURUSER;
+26 -13
View File
@@ -53,7 +53,7 @@ if (!empty($_GET['authkey'])) {
if (!$isReAnnounce && !$redis->set($reAnnounceCheckByAuthKey, TIMENOW, ['nx', 'ex' => 60])) {
$msg = "Request too frequent(a)";
do_log(sprintf("[ANNOUNCE] %s key: %s already exists, value: %s", $msg, $reAnnounceCheckByAuthKey, TIMENOW));
warn($msg);
err($msg);
}
if ($redis->get("$authKeyInvalidKey:$authkey")) {
$msg = "Invalid authkey";
@@ -89,7 +89,7 @@ $torrentReAnnounceKey = sprintf('reAnnounceCheckByInfoHash:%s:%s', $userAuthenti
if (!$isReAnnounce && !$redis->set($torrentReAnnounceKey, TIMENOW, ['nx', 'ex' => 60])) {
$msg = "Request too frequent(h)";
do_log(sprintf("[ANNOUNCE] %s key: %s already exists, value: %s", $msg, $torrentReAnnounceKey, TIMENOW));
warn($msg);
err($msg);
}
@@ -216,6 +216,7 @@ if (!$torrent) {
$redis->set("$torrentNotExistsKey:$info_hash", TIMENOW, ['ex' => 24*3600]);
err("torrent not registered with this tracker");
}
$GLOBALS['torrent'] = $torrent;
$torrentid = $torrent["id"];
if (isset($authKeyTid) && $authKeyTid != $torrentid) {
$redis->set("$authKeyInvalidKey:$authkey", TIMENOW, ['ex' => 3600*24]);
@@ -250,8 +251,8 @@ else{
if ($newnumpeers > $rsize)
$limit = " ORDER BY RAND() LIMIT $rsize";
else $limit = "";
$announce_wait = \App\Repositories\TrackerRepository::MIN_ANNOUNCE_WAIT_SECOND;
$announce_wait = \App\Repositories\TrackerRepository::MIN_ANNOUNCE_WAIT_SECOND;
$fields = "id, seeder, peer_id, ip, ipv4, ipv6, port, uploaded, downloaded, userid, last_action, UNIX_TIMESTAMP(last_action) as last_action_unix_timestamp, prev_action, (".TIMENOW." - UNIX_TIMESTAMP(last_action)) AS announcetime, UNIX_TIMESTAMP(prev_action) AS prevts";
//$peerlistsql = "SELECT ".$fields." FROM peers WHERE torrent = ".$torrentid." AND connectable = 'yes' ".$only_leech_query.$limit;
/**
@@ -279,7 +280,7 @@ if ($compact == 1) {
$rep_dict['peers'] = ''; // Change `peers` from array to string
$rep_dict['peers6'] = ''; // If peer use IPv6 address , we should add packed string in `peers6`
}
$GLOBALS['rep_dict'] = $rep_dict;
if ($isReAnnounce) {
do_log("$log, [YES_RE_ANNOUNCE]");
benc_resp($rep_dict);
@@ -440,29 +441,41 @@ if (!isset($self))
&& $torrent['owner'] != $userid
&& get_setting("torrent.paid_torrent_enabled") == "yes"
) {
$hasBuyCacheKey = sprintf("user_has_buy_torrent:%s:%s", $userid, $torrentid);
$hasBuyCacheTime = 86400*10;
$hasBuy = \Nexus\Database\NexusDB::remember($hasBuyCacheKey, $hasBuyCacheTime, function () use($userid, $torrentid) {
$exists = \App\Models\TorrentBuyLog::query()->where('uid', $userid)->where('torrent_id', $torrentid)->exists();
return intval($exists);
});
$hasBuyCacheKey = \App\Repositories\TorrentRepository::BOUGHT_USER_CACHE_KEY_PREFIX . $torrentid;
$hasBuy = $redis->hGet($hasBuyCacheKey, $userid);
if ($hasBuy === false) {
//no cache
$lockName = "load_torrent_bought_user:$torrentid";
$loadBoughtLock = new \Nexus\Database\NexusLock($lockName, 300);
if ($loadBoughtLock->get()) {
//get lock, do load
executeCommand("torrent:load_bought_user $torrentid", "string", true, false);
} else {
do_log("can not get loadBoughtLock: $lockName", 'debug');
}
//simple cache the hasBuy result
$hasBuy = \Nexus\Database\NexusDB::remember(sprintf("user_has_buy_torrent:%s:%s", $userid, $torrentid), 86400*10, function () use($userid, $torrentid) {
$exists = \App\Models\TorrentBuyLog::query()->where('uid', $userid)->where('torrent_id', $torrentid)->exists();
return intval($exists);
});
}
if (!$hasBuy) {
$lock = new \Nexus\Database\NexusLock("buying_torrent:$userid", 5);
if (!$lock->get()) {
$msg = "buying torrent, wait!";
do_log("[ANNOUNCE] user: $userid, torrent: $torrentid, $msg", 'error');
warn($msg);
err($msg);
}
$bonusRep = new \App\Repositories\BonusRepository();
try {
$bonusRep->consumeToBuyTorrent($az['id'], $torrent['id'], 'Web');
$redis->set($hasBuyCacheKey, 1, $hasBuyCacheTime);
$redis->hSet($hasBuyCacheKey, $userid, 1);
$lock->release();
} catch (\Exception $exception) {
$msg = $exception->getMessage();
do_log("[ANNOUNCE] user: $userid, torrent: $torrentid, $msg " . $exception->getTraceAsString(), 'error');
$lock->release();
warn($msg);
err($msg);
}
}
}