Skip to content

Commit

Permalink
⚡ improve performance of ics generator (#1840)
Browse files Browse the repository at this point in the history
  • Loading branch information
MrKrisKrisu authored Aug 8, 2023
1 parent 495e351 commit d319963
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 36 deletions.
64 changes: 33 additions & 31 deletions app/Http/Controllers/Backend/IcsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,50 +26,52 @@ public static function generateIcsCalendar(
): Calendar {
$icsToken = IcsToken::where([['token', $token], ['user_id', $user->id]])->firstOrFail();

$trainCheckIns = TrainCheckin::where('user_id', $user->id)
//I don't know why, but the "with" eager loading doesn't work in prod. "HafasTrip" is always null then
->orderByDesc('departure')
->limit($limit);
$checkinQuery = TrainCheckin::with(['originStation', 'destinationStation', 'HafasTrip.stopovers'])
->where('user_id', $user->id)
->orderByDesc('departure')
->limit($limit);

if ($from !== null) {
$trainCheckIns->where('departure', '>=', $from);
$checkinQuery->where('departure', '>=', $from);
}
if ($until !== null) {
$trainCheckIns->where('departure', '<=', $until);
$checkinQuery->where('departure', '<=', $until);
}

$calendar = Calendar::create()
->name(__('profile.last-journeys-of') . ' ' . $user->name)
->description(__('ics.description', [], $user->language));

foreach ($trainCheckIns->get() as $checkIn) {
try {
$name = '';
if ($useEmojis) {
$name .= $checkIn?->HafasTrip?->category?->getEmoji() . ' ';
}
$name .= __(
key: 'export.journey-from-to',
replace: [
'origin' => $checkIn->originStation->name,
'destination' => $checkIn->destinationStation->name
],
locale: $user->language
);
$checkinQuery->chunk(1000, function($checkins) use ($calendar, $useRealTime, $user, $useEmojis) {
foreach ($checkins as $checkin) {
try {
$name = '';
if ($useEmojis) {
$name .= $checkin?->HafasTrip?->category?->getEmoji() . ' ';
}
$name .= __(
key: 'export.journey-from-to',
replace: [
'origin' => $checkin->originStation->name,
'destination' => $checkin->destinationStation->name
],
locale: $user->language
);

$event = Event::create()
->name($name)
->uniqueIdentifier($checkIn->id)
->createdAt($checkIn->created_at)
->startsAt($useRealTime ? $checkIn->origin_stopover->departure : $checkIn->origin_stopover->departure_planned)
->endsAt($useRealTime ? $checkIn->destination_stopover->arrival : $checkIn->destination_stopover->arrival_planned);
$calendar->event($event);
} catch (Throwable $throwable) {
report($throwable);
$event = Event::create()
->name($name)
->uniqueIdentifier($checkin->id)
->createdAt($checkin->created_at)
->startsAt($useRealTime ? $checkin->origin_stopover->departure : $checkin->origin_stopover->departure_planned)
->endsAt($useRealTime ? $checkin->destination_stopover->arrival : $checkin->destination_stopover->arrival_planned);
$calendar->event($event);
} catch (Throwable $throwable) {
report($throwable);
}
}
}
});

$icsToken->update(['last_accessed' => Carbon::now()]);
$icsToken->update(['last_accessed' => now()]);
return $calendar;
}

Expand Down
10 changes: 5 additions & 5 deletions app/Http/Controllers/Frontend/IcsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class IcsController extends Controller
{
public function renderIcs(Request $request): ?Response {
$validated = $request->validate([
'user_id' => ['required', 'exists:users,id'],
'token' => ['required', 'exists:ics_tokens,token'],
'user_id' => ['required', 'numeric'],
'token' => ['required', 'string'],
'limit' => ['nullable', 'numeric', 'gte:1', 'lte:10000'],
'from' => ['nullable', 'date'],
'until' => ['nullable', 'date'],
Expand All @@ -31,16 +31,16 @@ public function renderIcs(Request $request): ?Response {
user: $user,
token: $validated['token'],
limit: $validated['limit'] ?? 1000,
from: Carbon::parse($validated['from']),
until: Carbon::parse($validated['until']),
from: isset($validated['from']) ? Carbon::parse($validated['from']) : null,
until: isset($validated['until']) ? Carbon::parse($validated['until']) : null,
useEmojis: $validated['emojis'] ?? true,
useRealTime: $validated['realtime'] ?? false,
);
return response($calendar->get())
->header('Content-Type', 'text/calendar')
->header('charset', 'utf-8');
} catch (ModelNotFoundException) {
return response(null, 404);
abort(404);
}
}

Expand Down

0 comments on commit d319963

Please sign in to comment.