Un evento ricorrente, per definizione, è un evento che ricorre ad un intervallo; è anche chiamato evento periodico. Esistono molte applicazioni che consentono ai propri utenti di impostare eventi ricorrenti. In che modo un sistema di database gestisce gli eventi ricorrenti? In questo articolo esploreremo un modo in cui vengono gestiti.
La ricorrenza non è facile da gestire per le applicazioni. Può diventare un compito da uragano, soprattutto quando si tratta di coprire ogni possibile scenario ricorrente, inclusa la creazione di eventi bisettimanali o trimestrali o la possibilità di riprogrammare tutte le istanze di eventi futuri.
Due modi per gestire gli eventi ricorrenti
Posso pensare ad almeno due modi per gestire le attività periodiche in un modello di dati. Prima di discuterne, esaminiamo rapidamente i requisiti di questo compito. In poche parole, una gestione efficace significa:
- Gli utenti possono creare eventi regolari e ricorrenti.
- È possibile creare eventi giornalieri, settimanali, bisettimanali, mensili, trimestrali, biennali e annuali senza limitazioni di data di fine.
- Gli utenti possono riprogrammare o annullare un'istanza di un evento o tutte le istanze future di un evento.
Considerando questi parametri, vengono in mente due modi per gestire gli eventi ricorrenti nel modello di dati. Li chiameremo il modo ingenuo e il modo esperto.
Il modo ingenuo: Memorizzazione di tutte le possibili istanze ricorrenti di un evento come righe separate in una tabella. In questa soluzione, abbiamo bisogno di una sola tabella, ovvero event
. Questa tabella ha colonne come event_title
, start_date
, end_date
, is_full_day_event
, ecc. Il start_date
e end_date
le colonne sono tipi di dati timestamp; in questo modo possono ospitare eventi che non durano tutto il giorno.
I professionisti: Questo è un approccio piuttosto semplice e il più semplice da implementare.
I contro: Il modo ingenuo ha alcuni aspetti negativi significativi, tra cui:
- La necessità di memorizzare tutte le possibili istanze di un evento. Se stai prendendo in considerazione le esigenze di una vasta base di utenti, è necessario un grosso pezzo di spazio. Tuttavia, lo spazio è piuttosto economico, quindi questo punto non ha un grande impatto.
- Un processo di aggiornamento molto disordinato. Supponiamo che un evento venga riprogrammato. In tal caso, qualcuno deve aggiornarne tutte le istanze. È necessario eseguire un numero enorme di operazioni DML durante la riprogrammazione, il che crea un impatto negativo sulle prestazioni dell'applicazione.
- Gestione delle eccezioni. Tutte le eccezioni devono essere gestite con garbo, soprattutto se devi tornare indietro e modificare l'appuntamento originale dopo aver fatto un'eccezione. Si supponga, ad esempio, di spostare in avanti di un giorno la terza istanza di un evento ricorrente. Cosa succede se successivamente modifichi l'ora dell'evento originale? Reinserisci un altro evento nel giorno originale e lasci quello che hai anticipato? Scollegare l'eccezione? Provare a cambiarlo in modo appropriato?
Event_id
– Questa colonna è referenziata dall'event
tabella e funge da chiave primaria in questa tabella. Mostra la relazione identificativa traevent
erecurring_pattern
tavoli. Questa colonna assicurerà inoltre che vi sia un massimo di un pattern ricorrente esistente per ogni evento.Recurring_type_id
– Questa colonna indica il tipo di ricorrenza, sia giornaliera, settimanale, mensile o annuale.Max_num_of_occurrances
– Ci sono momenti in cui non conosciamo la data di fine esatta di un evento ma sappiamo quante occorrenze (riunioni) sono necessarie per completarlo. Questa colonna memorizza un numero arbitrario che definisce la fine logica di un evento.Separation_count
– Ci si potrebbe chiedere come si possa configurare un evento bisettimanale o biennale se sono presenti solo quattro possibili valori di tipo di ricorrenza (giornaliero, settimanale, mensile, annuale). La risposta è ilseparation_count
colonna. Questa colonna indica l'intervallo (in giorni, settimane o mesi) prima che sia consentita l'istanza dell'evento successiva. Ad esempio, se è necessario configurare un evento a settimane alterne, separation_count ="1" per soddisfare questo requisito. Il valore predefinito per questa colonna è "0".- Il
recurring_type_id
sarebbe “settimanale”. - Il
separation_count
sarebbe “1”. - Il
day_of_week
sarebbe "2". Week_of_month
– Questa colonna è per gli eventi che sono programmati per una determinata settimana del mese, ovvero il primo, il secondo, l'ultimo, il penultimo, ecc. Possiamo memorizzare questi valori come 1,2,3, 4,.. (contando da l'inizio del mese) o -1,-2,-3,... (contando dalla fine del mese).Day_of_month
– Ci sono casi in cui un evento è programmato in un particolare giorno del mese, diciamo il 25. Questa colonna soddisfa questo requisito. Comeweek_of_month
, può essere popolato con numeri positivi ( “7” per il 7° giorno da inizio mese) o con numeri negativi ( “-7” per il settimo giorno da fine mese).- Il
recurring_type_id
sarebbe “mensile”. - Il
separation_count
sarebbe "2". - Il
day_of_month
sarebbe “11”. - Tutte le colonne rimanenti sarebbero nulle.
- Eventi che si verificano nei giorni festivi. Quando un caso particolare di un evento si verifica in un giorno festivo, dovrebbe essere spostato automaticamente al giorno lavorativo immediatamente successivo al giorno festivo? O dovrebbe essere cancellato automaticamente? In quali circostanze si applicherebbero una di queste due?
- Conflitti tra eventi. Cosa succede se determinati eventi (che si escludono a vicenda) cadono lo stesso giorno?
Il modo degli esperti: Memorizzazione di un modello ricorrente e generazione di istanze di eventi passati e futuri in modo programmatico. Questa soluzione affronta gli aspetti negativi della soluzione ingenua. Spiegheremo in dettaglio la soluzione per esperti in questo articolo.
Il modello proposto
Creazione di eventi
Tutti gli eventi programmati, indipendentemente dalla loro natura regolare o ricorrente, vengono registrati nell'event
tavolo. Non tutti gli eventi sono eventi ricorrenti, quindi avremo bisogno di una colonna flag, is_recurring
, in questa tabella per specificare in modo esplicito gli eventi ricorrenti. Il event_title
e event_description
le colonne memorizzano l'argomento e un breve riepilogo degli eventi. Le descrizioni degli eventi sono facoltative, motivo per cui questa colonna è nullable.
Come suggeriscono i loro nomi, la start_date
e end_date
le colonne mantengono le date di inizio e fine degli eventi. Nel caso di eventi regolari, queste colonne memorizzano le date effettive di inizio e fine. Tuttavia, memorizzano anche le date della prima e dell'ultima occorrenza di eventi periodici. Manterremo il end_date
colonna come nullable, poiché gli utenti possono configurare eventi ricorrenti senza data di fine. In questo caso, le occorrenze future fino a una data di fine ipotetica (ad esempio per un anno) verrebbero visualizzate nell'interfaccia utente.
Il is_full_date_event
colonna indica se un evento è un evento di un'intera giornata. Nel caso di un evento di un'intera giornata, il start_time
e end_time
le colonne sarebbero nulle; questo è il motivo per mantenere entrambe queste colonne annullabili.
Il created_by
e created_date
le colonne memorizzano l'utente che ha creato un evento e la data di creazione dell'evento.
Poi c'è il parent_event_id
colonna. Questo gioca un ruolo importante nel nostro modello di dati. Spiegherò il suo significato più avanti.
Gestione delle ricorrenze
Ora arriviamo direttamente all'affermazione del problema principale:cosa succede se viene creato un evento ricorrente nell'event
tabella – ovvero il is_recurring
il flag per l'evento è "Y"?
Come spiegato in precedenza, memorizzeremo un modello ricorrente per gli eventi in modo da poter costruire tutte le sue occorrenze future. Iniziamo creando il recurring_pattern
tavolo. Questa tabella ha le seguenti colonne:
Consideriamo il significato delle restanti colonne in termini di diversi tipi di ricorrenze.
Ricorrenza quotidiana
Abbiamo davvero bisogno di catturare uno schema per un evento ricorrente quotidiano? No, perché tutti i dettagli necessari per generare un pattern di ricorrenza giornaliera sono già registrati nell'event
tabella.
L'unico scenario che richiede uno schema è quando gli eventi sono programmati per giorni alterni o ogni X numero di giorni. In questo caso, il separation_count
la colonna ci aiuterà a capire il modello di ricorrenza e a derivare ulteriori istanze.
Ricorrenza settimanale
Abbiamo bisogno di una sola colonna aggiuntiva, day_of_week
, per memorizzare il giorno della settimana in cui si svolgerà questo evento. Supponendo che lunedì sia il primo giorno della settimana e la domenica sia l'ultimo, i valori possibili sarebbero 1,2,3,4,5,6 e 7. Le modifiche appropriate al codice che genera le occorrenze di singoli eventi devono essere apportate secondo necessità. Tutte le colonne rimanenti sarebbero nulle per gli eventi settimanali.
Prendiamo un tipo classico di evento settimanale:il bisettimanale. In questo caso, diremo che accade ogni settimana alternata di martedì, il secondo giorno della settimana. Quindi:
Ricorrenza mensile
Oltre a day_of_week
, sono necessarie altre due colonne per soddisfare qualsiasi scenario di ricorrenza mensile. In breve, queste colonne sono:
Consideriamo ora un esempio più complicato:un evento trimestrale. Si supponga che una società pianifichi un evento di proiezione dei risultati trimestrali per l'11 giorno del primo mese di ogni trimestre (di solito gennaio, aprile, luglio e ottobre). Quindi in questo caso:
Nell'esempio sopra, presupponiamo che l'utente stia creando la proiezione del risultato trimestrale a gennaio. Tieni presente che questa logica di separazione inizierà a contare dal mese, dalla settimana o dal giorno in cui viene creato l'evento.
Su righe simili, gli eventi semestrali possono essere registrati come eventi mensili con un
La ricorrenza annuale è abbastanza semplice. Abbiamo colonne per determinati giorni della settimana e del mese, quindi è necessaria solo una colonna aggiuntiva per il mese dell'anno. Abbiamo chiamato questa colonna
Veniamo ora alle eccezioni. Cosa succede se una particolare istanza di un evento ricorrente viene annullata o riprogrammata? Tutte queste istanze vengono registrate separatamente in
Diamo un'occhiata a due colonne,
A parte queste due colonne, tutte le colonne rimanenti funzionano come nell'
Esistono applicazioni che consentono agli utenti di riprogrammare tutte le istanze future di un evento ricorrente. In questi casi, abbiamo due opzioni. Possiamo archiviare tutte le istanze future in
Con questa soluzione, possiamo ottenere tutte le occorrenze passate di un evento, anche quando il suo schema di ricorrenza è stato modificato.
Ci sono alcune aree più complesse intorno agli eventi ricorrenti che non abbiamo discusso. Eccone due:
Quali cambiamenti dobbiamo apportare per sviluppare queste capacità? Per favore, dicci le tue opinioni nella sezione commenti.separation_count
di “5”.Ricorrenza annuale
month_of_year
.Gestione delle eccezioni di eventi ricorrenti
event_instance_exception
tavolo. Is_rescheduled
e is_cancelled
. Queste colonne indicano se questa istanza viene riprogrammata a una data/ora successiva o annullata del tutto. Perché ho due colonne separate per questo? Bene, pensa solo agli eventi che sono stati prima riprogrammati e poi completamente cancellati. Questo accade e abbiamo un modo per registrarlo con queste colonne. event
tabella.Perché collegare due eventi tramite
parent_event_id
?event_instance_exception
(suggerimento:soluzione non accettabile). Oppure possiamo creare un nuovo evento con nuovi parametri di data/ora nell'event
tabella e collegarlo al suo evento precedente (l'evento padre) tramite id_parent_event
colonna. Come migliorare la gestione degli eventi ricorrenti?