Query optimisations for last_messages and traffic

This commit is contained in:
Deon George
2022-01-06 00:19:57 +11:00
parent 3d6f233c1d
commit 6b0bf32552
8 changed files with 104 additions and 130 deletions

View File

@@ -5,10 +5,8 @@ namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use MongoDB\BSON\UTCDateTime;
use App\Traits\{QueryCacheableConfig,ScopeActive};
@@ -46,7 +44,7 @@ class Domain extends Model
return $this->hasMany(Zone::class);
}
/* CASTS */
/* ATTRIBUTES */
public function getHomePageAttribute($value)
{
@@ -60,82 +58,68 @@ class Domain extends Model
/* METHODS */
public function daily_area_stats(): Collection
/**
* Get some message area stats for this domain
*
* @param bool $byarea
* @param Collection|NULL $systems
* @return Collection
*/
public function daily_area_stats(bool $byarea=FALSE,Collection $systems=NULL): Collection
{
if (! $this->echoareas->count())
return collect();
$key = sprintf('%s_%d','daily_area_stats',$this->id);
Cache::forget($key);
return Cache::remember($key,self::CACHE_TIME,function() {
$gb ="CONCAT(EXTRACT('year',datetime)::string,'-',LPAD(EXTRACT('month',datetime)::string,2,'0'),'-',LPAD(EXTRACT('day',datetime)::string,2,'0')) AS datetime";
$echostats = Echomail::select([DB::raw($gb),DB::raw('COUNT(*)')])
->whereIn('id',$this->echoareas->pluck('id')->toArray())
$echostats = Echomail::cacheFor(self::CACHE_TIME)->select([DB::raw('datetime::date as date'),'echoarea_id','echoareas.name',DB::raw('COUNT(*)')])
->join('echoareas',['echoareas.id'=>'echomails.echoarea_id'])
->join('domains',['domains.id'=>'echoareas.domain_id'])
->where('domain_id',$this->id)
->when($systems?->count(),function($query) use ($systems) { return $query->whereIn('fftn_id',$systems->pluck('addresses')->flatten()->pluck('id')->toArray()); })
->where('datetime','>=',Carbon::now()->subMonths(self::STATS_MONTHS)->startOfMonth())
->groupBy('datetime')
->orderBy('datetime')
->groupBy(['echoarea_id','echoareas.name','date'])
->orderBy('echoareas.name')
->orderBy('date')
->with(['echoarea'])
->get();
if ($byarea)
return $echostats
->map(function($item) { return ['x'=>$item->datetime->timestamp*1000,'y'=>$item->count]; })
->groupBy(['echoarea_id'])
->map(function($item,$key) {
return [
'name' => $item->first()->echoarea->name,
'data' => $item->groupby('date')->map(function($item) {
return [
'x' => Carbon::create($item->first()->date)->timestamp*1000,
'y' => $item->sum('count')
];
})->values(),
'dashStyle' => 'ShortDot',
];
})->values();
else
return $echostats
->groupBy('date')
->map(function($item) { return ['x'=>Carbon::create($item->first()->date)->timestamp*1000,'y'=>$item->sum('count')]; })
->values();
});
}
public function daily_echoarea_stats(Echoarea $o): Collection
/**
* Get the latest message in each echomail area
*
* @return Collection
*/
public function latest_echomail_message(): Collection
{
if (! $this->echoareas->count())
return collect();
$key = sprintf('%s_%d-%d','daily_echoarea_stats',$this->id,$o->id);
Cache::forget($key);
return Cache::remember($key,self::CACHE_TIME,function() use ($o) {
$gb ="CONCAT(EXTRACT('year',datetime)::string,'-',LPAD(EXTRACT('month',datetime)::string,2,'0'),'-',LPAD(EXTRACT('day',datetime)::string,2,'0')) AS datetime";
$echostats = Echomail::select([DB::raw($gb),DB::raw('COUNT(*)')])
->whereIn('echoarea_id',[$o->id])
->where('datetime','>=',Carbon::now()->subMonths(self::STATS_MONTHS)->startOfMonth())
->groupBy('datetime')
->orderBy('datetime')
->get();
return $echostats
->map(function($item) { return ['x'=>$item->datetime->timestamp*1000,'y'=>$item->count]; })
->values();
});
}
public function stats(System $o=NULL): Collection
{
if (! $this->echoareas->count())
return collect();
$key = sprintf('%s_%d_%d','stats',$this->id,$o?->id);
return Cache::driver('redis')->remember($key,self::CACHE_TIME,function() use ($o) {
$where = collect(['echoarea_id'=>$this->echoareas->pluck('id')->toArray()]);
$where->put('datetime',['$gte',new UTCDateTime(Carbon::now()->subMonths(self::STATS_MONTHS)->startOfMonth())]);
if ($o)
$where->put('fftn_id',$o->addresses()->pluck('id'));
$echostats = Echomail::countGroupBy(['echoarea_id'],$where->toArray());
return $this->echoareas->map(function($item) use ($echostats) {
$stats = $echostats->filter(function($x) use ($item) {
return $x->id->echoarea_id == $item->id;
});
$item->count = 0;
foreach ($stats as $o)
$item->count += $o->count;
return $item;
});
});
return Echoarea::cacheFor(self::CACHE_TIME)
->select([
'echoareas.*',DB::raw('max(datetime) as last_message')
])
->leftJoin('echomails',['echomails.echoarea_id'=>'echoareas.id'])
->where('domain_id',$this->id)
->groupBy('echoareas.id')
->orderBy('echoareas.name')
->get();
}
}

View File

@@ -6,16 +6,18 @@ use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Cache;
use Rennokki\QueryCache\Traits\QueryCacheable;
use App\Traits\ScopeActive;
class Echoarea extends Model
{
use SoftDeletes,ScopeActive;
use SoftDeletes,ScopeActive,QueryCacheable;
private const CACHE_TIME = 3600;
protected $dates = [ 'last_message' ];
/* RELATIONS */
public function addresses()
@@ -34,31 +36,30 @@ class Echoarea extends Model
->orderBy('datetime','ASC');
}
/* ATTRIBUTES */
public function getLastMessageAttribute(): ?Carbon
{
return $this->echomail?->last()->datetime;
}
/* METHODS */
public function messages_count(int $period): int
{
$key = sprintf('%s_%d_%d','echo_messages_count',$this->id,$period);
$eo = Echomail::cacheFor(self::CACHE_TIME)
->where('echoarea_id',$this->id);
return Cache::remember($key,self::CACHE_TIME,function() use ($period) {
switch ($period) {
case 1: // day
return $this->echomail()->where('datetime','>=',Carbon::now()->startOfday()->subDay())->count();
case 7: // week
return $this->echomail()->where('datetime','>=',Carbon::now()->startOfday()->subWeek())->count();
case 30: // month
return $this->echomail()->where('datetime','>=',Carbon::now()->startOfday()->subMonth())->count();
default:
return 0;
}
});
$dt = Carbon::now()->startOfday();
switch ($period) {
case 1: // day
$eo->where('datetime','>=',$dt->subDay());
break;
case 7: // week
$eo->where('datetime','>=',$dt->subWeek());
break;
case 30: // month
$eo->where('datetime','>=',$dt->subMonth());
break;
default:
return 0;
}
return $eo->count();
}
/**

View File

@@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Rennokki\QueryCache\Traits\QueryCacheable;
use App\Classes\FTN\Message;
use App\Interfaces\Packet;
@@ -14,7 +15,7 @@ use App\Traits\{EncodeUTF8,MsgID};
final class Echomail extends Model implements Packet
{
use SoftDeletes,EncodeUTF8,MsgID;
use SoftDeletes,EncodeUTF8,MsgID,QueryCacheable;
private const LOGKEY = 'ME-';
private array $set_seenby = [];

View File

@@ -8,11 +8,10 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\DomainController;
use App\Traits\QueryCacheableConfig;
class System extends Model
{
use HasFactory,QueryCacheableConfig;
use HasFactory;
protected $dates = ['last_session'];