Come usiamo gli aggiornamenti ottimistici di Inertia v3 in There There
Qualche mese fa abbiamo iniziato a costruire There There, un helpdesk che stiamo realizzando in Spatie. La premessa è semplice. Dopo due decenni di supporto clienti per il nostro lavoro open source e per le nostre app SaaS, volevamo lo strumento che avremmo sempre desiderato che esistesse.
Una cosa a cui teniamo in particolare è usare l'IA per aiutare le persone a scrivere risposte migliori, non per sostituirle. L'agente resta al comando della conversazione. Il modello lo aiuta solo a rispondere più velocemente e con un po' più di incisività. There There è attualmente in private beta e puoi richiedere l'accesso anticipato su there-there.app.
Stiamo costruendo There There con Laravel e Inertia e facciamo ampio affidamento sulle ultime funzionalità introdotte da Inertia v3. In questo articolo vorrei fare un esempio: gli aggiornamenti ottimistici.
Usare gli aggiornamenti ottimistici
Un agente di supporto attiva e disattiva un sacco di piccole cose nel corso della giornata. Aggiungere un tag a un ticket, concedere a un collega l'accesso a un canale, attivare o disattivare un workflow. Ognuna di queste azioni è un singolo clic che innesca un round-trip verso il server.
Se l'interfaccia aspetta quel round-trip prima di mostrare il cambiamento, l'app risulta lenta. Non rotta, solo lenta. E in uno strumento in cui vivi tutto il giorno, l'effetto si accumula.
Inertia v3 include un'API di aggiornamenti ottimistici di prim'ordine che gestisce tutto questo in modo elegante. Invece di aspettare una risposta, aggiorniamo immediatamente l'interfaccia per riflettere il cambiamento e lasciamo che Inertia lo annulli se la richiesta fallisce.
Ecco come appare nella nostra pagina di dettaglio del membro. Un admin può attivare o disattivare l'appartenenza di un collega a un team. L'elenco dei team arriva come prop e accanto a ciascuno renderizziamo uno switch.
{teams.map((team) => (
<div key={team.id}>
<span>{team.name}</span>
<Switch
checked={team.is_member}
onCheckedChange={() => handleToggleTeam(team)}
/>
</div>
))}
Quando lo switch viene attivato, viene eseguita handleToggleTeam.
function handleToggleTeam(team) {
const optimistic = router.optimistic((props) => ({
teams: props.teams.map((t) =>
t.id === team.id ? { ...t, is_member: !t.is_member } : t,
),
}));
if (team.is_member) {
optimistic.delete(removeTeamMember.url({
team: team.ulid,
user: member.ulid,
}), { preserveScroll: true });
return;
}
optimistic.post(addTeamMember.url({
team: team.ulid,
user: member.ulid,
}), {}, { preserveScroll: true });
}
La funzione che passiamo a router.optimistic riceve le props correnti e restituisce le chiavi che vogliamo aggiornare. Inertia applica subito quella patch, quindi il toggle nell'interfaccia cambia prima che la richiesta lasci il browser. Quando arriva la risposta, Inertia sovrappone le props reali del server.
Mi piace lo stile concatenato in questo caso, perché la stessa patch ottimistica può portare sia a una post sia a una delete. Catturiamo il builder ottimistico una volta sola e scegliamo il verbo dopo.
Eccolo in azione. Il toggle cambia immediatamente e la richiesta avviene in background.
Per i casi più semplici esiste un secondo stile. Passi optimistic direttamente come opzione al verbo. Ecco il nostro toggle del workflow:
function handleToggle(workflow) {
router.patch(workflowToggle.url(workflow.ulid), {}, {
optimistic: (props) => ({
workflows: props.workflows.map((w) =>
w.id === workflow.id ? { ...w, is_enabled: !w.is_enabled } : w,
),
}),
});
}
Stessa idea. Descrivi la forma aggiornata, la passi a Inertia e lo lasci gestire il resto.
Se il server restituisce una risposta non-2xx, Inertia annulla automaticamente il cambiamento ottimistico. Non c'è codice di ripristino manuale da scrivere. Gli errori di validazione finiscono dove ti aspetti, e solo le chiavi che hai toccato nella callback vengono salvate come snapshot, così lo stato non correlato resta invariato. Le richieste concorrenti portano ciascuna il proprio snapshot, il che significa che una richiesta lenta non annullerà una più veloce che ha già risposto.
In conclusione
Una volta gli aggiornamenti ottimistici significavano mantenere una copia parallela dello stato, ripristinarla in caso di rifiuto e ragionare con attenzione sulle race condition. Con Inertia v3 descrivi lo stato successivo e basta. L'intera interazione è di circa dieci righe.
Puoi leggere la documentazione ufficiale nella guida agli aggiornamenti ottimistici di Inertia v3. E se vuoi provare There There in prima persona, siamo attualmente in private beta e puoi richiedere l'accesso anticipato su there-there.app.
Altri articoli recenti
Laravel AI 1.1 e 1.2: Agent Skills, Cohere e structured output più solidi
Le release 1.1.0 e 1.2.0 di laravel/ai portano gli Agent Skills, l'approvazione obbligatoria per i tool built-in e nuovi provider come Cohere e Laya self-hosted. Sul fronte qualità arrivano i fix allo structured output per Bedrock e il supporto alle provider options. Aggiornati anche i modelli di default, con Claude 4.7+ che ignora i sampling params.
Laravel 13.35.0: scheduler più controllabile, code più flessibili e response Markdown
Laravel 13.35.0 porta Schedule::alwaysOnOneServer(), il supporto a schedule:interrupt per i comandi di lunga durata, --memory in percentuale per queue:work e il nuovo metodo markdown() sulla response factory. Tante piccole migliorie anche a test, view compilate in parallelo e dischi local.
BashBox: un interprete Bash in sandbox per agenti AI in PHP
BashBox è un interprete bash scritto in puro PHP che permette di eseguire gli script generati dagli agenti AI senza mai ricorrere a proc_open, exec o shell_exec. Ogni comando è una classe PHP che lavora su un filesystem virtuale, con limiti di esecuzione, quote disco e accesso di rete configurabili. Ideale per chi sviluppa agenti con il Laravel AI SDK o altre librerie simili.