Ad esempio, ho un servizio web RESTful e devo supportare la creazione di un widget tramite una richiesta HTTP POSTed. Ho bisogno di
- Deserializza il widget POSTed.
- Convalida il widget deserializzato.
- Persiste il widget su un servizio di supporto.
- Invia una risposta positiva al client.
Ora, il problema è che il mio SLA non consente al 3 di bloccare 4 - la persistenza in questo caso richiede troppo tempo e il client deve sapere subito che la richiesta è riuscita (questo è il caso d'uso standard per la 202
codice di stato http).
Quasi ovunque io guardi, il presupposto è che il modo per risolverlo sia quello di "fare da sfondo" alla costosa parte di persistenza. Questo è in genere un processo scomodo con molte parti mobili e spesso la propria latenza (ad esempio, effettuare una chiamata di blocco a un servizio di accodamento separato).
Il semplice parallelismo tra 3 e 4 usando i costrutti nativi è generalmente fuori discussione, così come lo è l'ordine in modo tale che 4 blocchi 3. Per quanto posso dire, questo è principalmente dovuto al fatto che i server web e app sono costruiti con il fondamentale Supponendo che un processo (e tutti i bambini a cui è stato biforcato) sia libero di essere ucciso / riutilizzato non appena viene inviata la sua risposta. O, equivalentemente, che la risposta non può essere inviata fino a quando l'app non ha finito di fare tutto ciò che sta per fare.
Questo è estremamente frustrante per me! In qualsiasi altro contesto, posso fare ciò che mi piace con il flusso di controllo del programma. Ma quando gestisco un Phusion Passenger - > Installazione di Ruby on Rails, e voglio fare una cosa dopo aver inviato la risposta, mi rimane una grande varietà di opzioni barocche che sembrano considerare tutto perfettamente naturale e accettabile, per esempio, serializzare lo stato dell'applicazione, postarlo ad Amazon SQS, hanno fondamentalmente separato il servizio web che esegue il polling di SQS, deserializza il vecchio stato dell'applicazione, quindi fa la cosa. Avevo lo stato dell'applicazione impostato come volevo dopo aver inviato la risposta! Perché non c'è niente scritto quindi posso solo fare
def create
widget = Widget.new(params[:widget])
if widget.valid?
respond_with(widget)
widget.save
else
respond_with(widget.errors)
end
end
Perché esiste un'ipotesi pervasiva che gli stack di servizi Web non supporteranno mai questo tipo di flusso? C'è un inconveniente nascosto, o un compromesso, per rendere possibile farlo?