Provare a fare questo con qualsiasi tipo di processo leggero (processi asincroni, thread o qualsiasi altra cosa del genere) è una ricetta per il fallimento, a meno che tu non sia in un ambiente che ti dà garanzie rigide su quando il codice verrà eseguito. Inoltre, non aiuta che se il tuo programma muore e venga riavviato, qualsiasi aggiornamento dello stato in sospeso andrà perso a meno che tu non abbia un modo per ricostituirli e fare aggiornamenti che dovrebbero essere accaduti mentre il programma non era in esecuzione.
L'avviso preliminare che ricevi di un nuovo stato e quando ha effetto sono i dati e quale modo migliore di gestirli rispetto a metterli nel database? Dopotutto, stavi per fare una transazione per aggiornare lo stato comunque una volta che il tuo LWP aveva deciso che era ora. In questo modo si ottiene tutta l'ACIDity che il database ha da offrire e si ridimensionerà a qualsiasi database possa essere archiviato piuttosto che al numero di lavori che l'ambiente LWP in uso può raccogliere.
Per fare ciò è necessario interrompere lo stato degli eventi in una tabella separata che elenca gli intervalli di tempo e quale stato è in vigore in ognuno di essi.
Questo esempio è nominalmente PostgreSQL, ma puoi fare l'equivalente in qualsiasi database relazionale:
CREATE TABLE event (
id BIGSERIAL PRIMARY KEY,
-- All other columns except the status
);
CREATE TABLE event_status (
event BIGINT REFERENCES events(id), -- Which event
times TSTZRANGE, -- Range of times this status is valid
status INTEGER -- The status (doesn't have to be INTEGER)
);
Questa è la struttura della tabella. * Devi impostare vincoli e trigger per assicurarti che le righe in event_status
per un dato evento esprimano un intervallo di tempo contiguo che copre l'alba del tempo all'infinito e quell'inserimento di una nuova riga regola correttamente gli orari finali delle righe circostanti.
Con questo, ottenere lo stato corrente è un JOIN
delle due tabelle che elimina le righe che non sono più in vigore o non hanno ancora effetto. Funziona bene in una vista:
CREATE VIEW event_current_status AS
SELECT event.*, event_status.status
FROM event JOIN event_status ON event_status.event = event.id
-- The && operator means containment, i.e., the current time
-- falls within the range of the 'times' column.
WHERE event_status.times && now()
;
Indicato correttamente ( event
e times
nello stesso indice su event_status
dovrebbe fare), non dovresti avere problemi di rendimento.
* Hai menzionato in un commento che questa informazione è disponibile altrove nel database; Sto per salutarlo a mano per ora. Detto questo, potrebbe essere una buona idea investigare il merito di estrarlo direttamente dalle tabelle in cui è originato invece di avere una tabella di stato duplicata. Ci sono dei compromessi per entrambi che dipenderanno dalla tua situazione.