Fix Care settings 500s and slow saves under Queue/demo load.
Deploy Ladill Care / deploy (push) Successful in 52s

Defer Queue provision and ticket backfill after the settings response, harden messaging credential creation against lock races, and stop wrapping demo seed in a long-held transaction.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-17 22:57:25 +00:00
co-authored by Cursor
parent 88b5a4e3ab
commit 640b62010a
3 changed files with 123 additions and 79 deletions
@@ -79,7 +79,7 @@ class SettingsController extends Controller
]);
}
public function update(Request $request, QueueClient $queue, CareQueueProvisioner $provisioner): RedirectResponse
public function update(Request $request, QueueClient $queue): RedirectResponse
{
$this->authorizeAbility($request, 'settings.manage');
$organization = $this->organization($request);
@@ -136,6 +136,8 @@ class SettingsController extends Controller
$wantsQueue = false;
}
$settings['queue_integration_enabled'] = $wantsQueue;
$queueWasEnabled = (bool) data_get($organization->settings, 'queue_integration_enabled');
$queueJustEnabled = $wantsQueue && ! $queueWasEnabled;
$settings[AppointmentPatientNotifier::SETTING_BOOKED_SMS] = $request->boolean('notify_appointment_booked_sms');
$settings[AppointmentPatientNotifier::SETTING_BOOKED_EMAIL] = $request->boolean('notify_appointment_booked_email');
@@ -184,27 +186,49 @@ class SettingsController extends Controller
}
}
// Queue department sync + waiting-ticket backfill can take minutes over HTTP.
// Never block the settings response on it — run after the redirect goes out.
if ($wantsQueue && $queue->configured()) {
try {
$organization = $organization->fresh();
$provisioner->provisionOrganization($organization);
// Backfill tickets for patients already waiting when Queue was just linked.
$bridge = app(CareQueueBridge::class);
$branches = Branch::owned($owner)
->where('organization_id', $organization->id)
->where('is_active', true)
->pluck('id');
foreach ($branches as $branchId) {
foreach (array_keys(CareQueueContexts::departments()) as $context) {
if ($context === CareQueueContexts::RECEPTION) {
continue;
}
$bridge->syncMissingTickets($organization, $context, (int) $branchId, 50);
}
$organizationId = (int) $organization->id;
$backfillTickets = $queueJustEnabled;
dispatch(function () use ($organizationId, $owner, $backfillTickets) {
$organization = Organization::query()->find($organizationId);
if (! $organization) {
return;
}
} catch (\Throwable) {
// Best-effort; role pages will lazy-ensure on next use.
}
try {
app(CareQueueProvisioner::class)->provisionOrganization($organization);
} catch (\Throwable) {
return;
}
if (! $backfillTickets) {
return;
}
try {
$bridge = app(CareQueueBridge::class);
$branches = Branch::owned($owner)
->where('organization_id', $organization->id)
->where('is_active', true)
->pluck('id');
foreach ($branches as $branchId) {
foreach (array_keys(CareQueueContexts::departments()) as $context) {
if ($context === CareQueueContexts::RECEPTION) {
continue;
}
try {
$bridge->syncMissingTickets($organization, $context, (int) $branchId, 25);
} catch (\Throwable) {
// Continue other contexts/branches.
}
}
}
} catch (\Throwable) {
// Best-effort; role pages will lazy-ensure on next use.
}
})->afterResponse();
}
AuditLogger::record($owner, 'organization.updated', $organization->id, $owner, Organization::class, $organization->id);