(Fix) Slow online users section on home page 🐛

This commit is contained in:
Jack Price-Burns
2019-06-17 19:21:03 +01:00
parent 474e6652a9
commit bd8f28d168
7 changed files with 124 additions and 88 deletions
+9 -1
View File
@@ -22,6 +22,7 @@ use App\Models\Topic;
use App\Models\Article;
use App\Models\Torrent;
use App\Models\Bookmark;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use App\Models\FreeleechToken;
use App\Models\FeaturedTorrent;
@@ -107,7 +108,14 @@ class HomeController extends Controller
});
// Online Block
$users = new User();
$users = User::with('group', 'privacy')
->withCount([
'warnings' => function (Builder $query) {
$query->whereNotNull('torrent')->where('active', '1');
}
])
->where('last_action', '>', now()->subMinutes(5))
->get();
$groups = cache()->remember('user-groups', $expiresAt, function () {
return Group::select(['name', 'color', 'effect', 'icon'])->oldest('position')->get();
+1 -1
View File
@@ -60,8 +60,8 @@ class Kernel extends HttpKernel
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Http\Middleware\UpdateLastAction::class,
],
'api' => [
'throttle:60,1',
'bindings',
+40
View File
@@ -0,0 +1,40 @@
<?php
/**
* NOTICE OF LICENSE.
*
* UNIT3D is open-sourced software licensed under the GNU General Public License v3.0
* The details is bundled with this project in the file LICENSE.txt.
*
* @project UNIT3D
*
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
* @author HDVinnie
*/
namespace App\Http\Middleware;
use Closure;
class UpdateLastAction
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!$user = $request->user()) {
return $next($request);
}
$user->last_action = now();
$user->save();
return $next($request);
}
}
+10
View File
@@ -689,6 +689,16 @@ class User extends Authenticatable
return $this->hasMany(FreeleechToken::class);
}
/**
* Has many warnings.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function warnings()
{
return $this->hasMany(Warning::class);
}
/**
* Get the Users username as slug.
*
+8 -63
View File
@@ -13,74 +13,19 @@
namespace App\Traits;
use Carbon\Carbon;
trait UsersOnlineTrait
{
public function allOnline()
{
return $this->all()->filter->isOnline();
}
/**
* Check if the current user is online.
*
* @return bool
*/
public function isOnline()
{
return cache()->has($this->getCacheKey());
}
public function leastRecentOnline()
{
return $this->allOnline()
->sortBy(function ($user) {
return $user->getCachedAt();
});
}
public function mostRecentOnline()
{
return $this->allOnline()
->sortByDesc(function ($user) {
return $user->getCachedAt();
});
}
public function getCachedAt()
{
if (empty($cache = cache()->get($this->getCacheKey()))) {
return 0;
if (!$this->last_action) {
return false;
}
return $cache['cachedAt'];
}
public function setCache($seconds = 300)
{
return cache()->put(
$this->getCacheKey(),
$this->getCacheContent(),
$seconds
);
}
public function getCacheContent()
{
if (! empty($cache = cache()->get($this->getCacheKey()))) {
return $cache;
}
$cachedAt = Carbon::now();
return [
'cachedAt' => $cachedAt,
'user' => $this,
];
}
public function pullCache()
{
cache()->pull($this->getCacheKey());
}
public function getCacheKey()
{
return sprintf('%s-%s', 'UserOnline', $this->id);
return $this->last_action->gt(now()->subMinutes(5));
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddLastActionToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->dateTime('last_action')->after('last_login')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('last_action');
});
}
}
+24 -23
View File
@@ -3,36 +3,37 @@
<div class="panel panel-chat shoutbox">
<div class="panel-heading">
<h4>@lang('blocks.users-online')
<span class="label label-default">{{ $users->allOnline()->count() }}</span>
<span class="label label-default">{{ $users->count() }}</span>
</h4>
</div>
<div class="panel-body">
@foreach ($users->mostRecentOnline() as $user)
@if($user->hidden == 1 || !$user->isVisible($user,'other','show_online'))
<span class="badge-user text-orange text-bold" style="margin-bottom: 10px;">
<i class="{{ config('other.font-awesome') }} fa-user-ninja"></i> {{ strtoupper(trans('common.hidden')) }}
@if (auth()->user()->group->is_modo)
<a href="{{ route('profile', ['username' => $user->username, 'id' => $user->id]) }}">
{{ $user->username }}
@if ($user->getWarning() > 0)
<i class="{{ config('other.font-awesome') }} fa-exclamation-circle text-orange" aria-hidden="true"
data-toggle="tooltip" data-original-title="@lang('common.active-warning')"></i>
@endif
</a>
@endif
</span>
@else
<a href="{{ route('profile', ['username' => $user->username, 'id' => $user->id]) }}">
<span class="badge-user text-bold" style="color:{{ $user->group->color }}; background-image:{{ $user->group->effect }}; margin-bottom: 10px;">
<i class="{{ $user->group->icon }}" data-toggle="tooltip" data-original-title="{{ $user->group->name }}"></i>
@foreach ($users as $user)
@if (!$user->isVisible($user, 'other', 'show_online'))
<span class="badge-user text-orange text-bold" style="margin-bottom: 10px;">
<i class="{{ config('other.font-awesome') }} fa-user-ninja"></i> {{ strtoupper(trans('common.hidden')) }}
@if (auth()->user()->group->is_modo)
<a href="{{ route('profile', ['username' => $user->username, 'id' => $user->id]) }}">
{{ $user->username }}
@if ($user->getWarning() > 0)
@if ($user->warnings_count > 0)
<i class="{{ config('other.font-awesome') }} fa-exclamation-circle text-orange" aria-hidden="true"
data-toggle="tooltip" data-original-title="@lang('common.active-warning')"></i>
@endif
</span>
</a>
@endif
</a>
@endif
</span>
@else
<a href="{{ route('profile', ['username' => $user->username, 'id' => $user->id]) }}">
<span class="badge-user text-bold" style="color:{{ $user->group->color }}; background-image:{{ $user->group->effect }}; margin-bottom: 10px;">
<i class="{{ $user->group->icon }}" data-toggle="tooltip" data-original-title="{{ $user->group->name }}"></i>
{{ $user->username }}
@if ($user->warnings_count > 0)
<i class="{{ config('other.font-awesome') }} fa-exclamation-circle text-orange" aria-hidden="true"
data-toggle="tooltip" data-original-title="@lang('common.active-warning')"></i>
@endif
</span>
</a>
@endif
@endforeach
</div>
<div class="panel-footer">