alter N+1 detection process

This commit is contained in:
Mark Gregory
2026-06-26 11:13:23 +01:00
parent 4ae70ba737
commit 788bb87b01
10 changed files with 117 additions and 10 deletions
@@ -30,8 +30,8 @@ final class HelpdeskDashboardWidget extends Component
'criticalCount' => $criticalCount,
'closedPercent' => $closedPercent,
'openPercent' => $openPercent,
'recentCommits' => GitCommit::query()->with(['repository', 'ticket'])->latest('committed_at')->limit(6)->get(),
'recentTickets' => (clone $base)->with(['status', 'priority'])->latest('last_activity_at')->limit(5)->get(),
'recentCommits' => GitCommit::query()->with(['repository', 'ticket.user:id,name,email', 'ticket.owner:id,name,email', 'ticket.agent:id,name,email'])->latest('committed_at')->limit(6)->get(),
'recentTickets' => (clone $base)->with(['user:id,name,email', 'owner:id,name,email', 'agent:id,name,email', 'status', 'priority'])->latest('last_activity_at')->limit(5)->get(),
]);
}
}
+3 -3
View File
@@ -61,7 +61,7 @@ final class KanbanBoard extends Component
'last_activity_at' => now(),
])->save();
$freshTicket = $ticket->fresh(['status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems', 'board']) ?? $ticket;
$freshTicket = $ticket->fresh(['user:id,name,email', 'owner:id,name,email', 'agent:id,name,email', 'status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems', 'board']) ?? $ticket;
$workflow->dispatch(
$freshTicket,
@@ -109,7 +109,7 @@ final class KanbanBoard extends Component
$this->board_id = $board->id;
$fresh = $ticket->fresh(['status', 'priority', 'category', 'project', 'team', 'board']) ?? $ticket;
$fresh = $ticket->fresh(['user:id,name,email', 'owner:id,name,email', 'agent:id,name,email', 'status', 'priority', 'category', 'project', 'team', 'board']) ?? $ticket;
$workflow->dispatch($fresh, 'ticket.updated', Auth::user());
$message = 'Ticket ' . $fresh->reference . ' moved from ' . $oldBoardName . ' to ' . $board->name . '.';
@@ -185,7 +185,7 @@ final class KanbanBoard extends Component
}
return Ticket::query()
->with(['status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems', 'board'])
->with(['user:id,name,email', 'owner:id,name,email', 'agent:id,name,email', 'status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems', 'board'])
->visibleTo(Auth::user())
->where('board_id', $board->id)
->latest('last_activity_at')
+3 -2
View File
@@ -248,8 +248,9 @@ final class TicketEdit extends Component
private function freshTicket(Ticket $ticket): Ticket
{
return $ticket->fresh([
'owner',
'agent',
'user:id,name,email',
'owner:id,name,email',
'agent:id,name,email',
'status',
'priority',
'category',
+1 -1
View File
@@ -124,7 +124,7 @@ final class TicketIndex extends Component
$search = trim($this->search);
return Ticket::query()
->with(['owner', 'agent', 'status', 'priority', 'category', 'project', 'team'])
->with(['user:id,name,email', 'owner:id,name,email', 'agent:id,name,email', 'status', 'priority', 'category', 'project', 'team'])
->withCount('attachments')
->visibleTo($user)
->when($this->scope === 'open', static fn (Builder $query): Builder => $query->whereNull('completed_at'))
+1 -1
View File
@@ -365,7 +365,7 @@ final class TicketShow extends Component
->when(! $this->canSeeInternalNotes(), static function ($query): void {
$query->where('is_internal', false);
})
->with(['user.company', 'attachments'])
->with(['user.company', 'owner:id,name,email,company_id', 'agent:id,name,email', 'attachments'])
->oldest()
->get();
+3
View File
@@ -36,6 +36,9 @@ final class Ticket extends Model
'sla_first_response_breached_at', 'sla_resolution_breached_at', 'public_replies_count', 'time_spent_minutes',
];
/** @var list<string> */
protected $with = ['user'];
/** @var array<string, string> */
protected $casts = [
'company_id' => 'integer',
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Modules\Helpdesk\Tests\Feature;
use Tests\TestCase;
final class TicketUserNPlusOneFilesTest extends TestCase
{
public function test_ticket_collection_queries_eager_load_user_owner_and_agent(): void
{
$index = file_get_contents(module_path('Helpdesk', 'Livewire/TicketIndex.php'));
$kanban = file_get_contents(module_path('Helpdesk', 'Livewire/KanbanBoard.php'));
$dashboard = file_get_contents(module_path('Helpdesk', 'Livewire/HelpdeskDashboardWidget.php'));
self::assertIsString($index);
self::assertIsString($kanban);
self::assertIsString($dashboard);
self::assertStringContainsString("'user:id,name,email', 'owner:id,name,email', 'agent:id,name,email'", $index);
self::assertStringContainsString("'user:id,name,email', 'owner:id,name,email', 'agent:id,name,email'", $kanban);
self::assertStringContainsString("'user:id,name,email', 'owner:id,name,email', 'agent:id,name,email'", $dashboard);
}
}
+5
View File
@@ -638,3 +638,8 @@
- Added explicit regression guard text for all selectable GitFlow prefixes used by the ticket developer actions branch command builder.
- Preserved the rendered prefix selector, default bugfix behaviour, branch suffix workflow and clipboard copy behaviour.
- Preserved append-only changelog history.
- version: 1.10.39
date: 2026-06-26
changes:
- Eager loaded direct ticket user, owner and agent relations on ticket list surfaces to remove Helpdesk ticket user N+1 warnings.
+1 -1
View File
@@ -23,5 +23,5 @@
"Modules\\Helpdesk\\Providers\\HelpdeskServiceProvider"
],
"files": [],
"version": "1.10.34"
"version": "1.10.39"
}