Een terugkerende gebeurtenis is per definitie een gebeurtenis die met een interval terugkeert; het wordt ook wel een periodieke gebeurtenis genoemd. Er zijn veel applicaties waarmee gebruikers terugkerende evenementen kunnen instellen. Hoe beheert een databasesysteem terugkerende gebeurtenissen? In dit artikel onderzoeken we een manier waarop ze worden afgehandeld.
Herhaling is niet gemakkelijk voor toepassingen om te gaan met. Het kan een orkaantaak worden, vooral als het gaat om het afdekken van elk mogelijk terugkerend scenario - inclusief het creëren van tweewekelijkse of driemaandelijkse evenementen of het opnieuw plannen van alle toekomstige evenementen.
Twee manieren om terugkerende gebeurtenissen te beheren
Ik kan tenminste twee manieren bedenken om periodieke taken in een datamodel af te handelen. Laten we, voordat we ze bespreken, snel de vereisten van deze taak doornemen. In een notendop, effectief beheer betekent:
- Gebruikers mogen regelmatige en terugkerende evenementen maken.
- Dagelijkse, wekelijkse, tweewekelijkse, maandelijkse, driemaandelijkse, tweejaarlijkse en jaarlijkse evenementen kunnen worden gemaakt zonder beperkingen op de einddatum.
- Gebruikers kunnen een instantie van een evenement of alle toekomstige instanties van een evenement opnieuw plannen of annuleren.
Rekening houdend met deze parameters, denk je aan twee manieren om terugkerende gebeurtenissen in het gegevensmodel te beheren. We noemen ze de naïeve manier en de deskundige manier.
De naïeve manier: Het opslaan van alle mogelijke terugkerende instanties van een gebeurtenis als afzonderlijke rijen in een tabel. In deze oplossing hebben we slechts één tabel nodig, namelijk event
. Deze tabel heeft kolommen zoals event_title
, start_date
, end_date
, is_full_day_event
, enz. De start_date
en end_date
kolommen zijn tijdstempelgegevenstypen; op deze manier kunnen ze evenementen accommoderen die niet de hele dag duren.
De pluspunten: Dit is een vrij eenvoudige benadering en de eenvoudigste om te implementeren.
De nadelen: De naïeve manier heeft een aantal belangrijke nadelen, waaronder:
- De noodzaak om alle mogelijke instanties van een gebeurtenis op te slaan. Als u rekening houdt met de behoeften van een groot aantal gebruikers, is een groot stuk ruimte vereist. Ruimte is echter vrij goedkoop, dus dit punt heeft geen grote impact.
- Een erg rommelig updateproces. Stel dat een evenement wordt verplaatst. In dat geval moet iemand alle exemplaren ervan bijwerken. Er moeten enorme aantallen DML-bewerkingen worden uitgevoerd bij het opnieuw plannen, wat een negatief effect heeft op de applicatieprestaties.
- Behandelen van uitzonderingen. Alle uitzonderingen moeten netjes worden afgehandeld, vooral als u terug moet gaan en de oorspronkelijke afspraak moet bewerken nadat u een uitzondering hebt gemaakt. Stel dat u het derde exemplaar van een terugkerende gebeurtenis een dag vooruit schuift. Wat als u vervolgens de tijd van de oorspronkelijke gebeurtenis wijzigt? Voegt u een andere gebeurtenis op de oorspronkelijke dag opnieuw toe en laat u de gebeurtenis die u naar voren bracht, achterwege? De uitzondering ontkoppelen? Probeer het op de juiste manier te veranderen?
Event_id
– Deze kolom is afkomstig van hetevent
tabel, en het fungeert als de primaire sleutel in deze tabel. Het toont de identificerende relatie tussenevent
enrecurring_pattern
tafels. Deze kolom zorgt er ook voor dat er maximaal één terugkerend patroon bestaat voor elke gebeurtenis.Recurring_type_id
– Deze kolom geeft het type herhaling aan, of het nu dagelijks, wekelijks, maandelijks of jaarlijks is.Max_num_of_occurrances
– Er zijn momenten waarop we de exacte einddatum van een evenement niet weten, maar we weten wel hoeveel gebeurtenissen (vergaderingen) er nodig zijn om het te voltooien. In deze kolom wordt een willekeurig getal opgeslagen dat het logische einde van een gebeurtenis definieert.Separation_count
– U vraagt zich misschien af hoe een tweewekelijkse of tweejaarlijkse gebeurtenis kan worden geconfigureerd als er slechts vier mogelijke herhalingswaarden zijn (dagelijks, wekelijks, maandelijks, jaarlijks). Het antwoord is deseparation_count
kolom. Deze kolom geeft het interval aan (in dagen, weken of maanden) voordat de volgende gebeurtenisinstantie is toegestaan. Als een evenement bijvoorbeeld om de week moet worden geconfigureerd, dan separation_count ="1" om aan deze eis te voldoen. De standaardwaarde voor deze kolom is "0".- De
recurring_type_id
zou "wekelijks" zijn. - De
separation_count
zou "1" zijn. - De
day_of_week
zou "2" zijn. Week_of_month
– Deze kolom is voor evenementen die zijn gepland voor een bepaalde week van de maand - d.w.z. de eerste, tweede, laatste, voorlaatste, etc. We kunnen deze waarden opslaan als 1,2,3, 4,.. (geteld vanaf het begin van de maand) of -1,-2,-3,... (gerekend vanaf het einde van de maand).Day_of_month
– Er zijn gevallen waarin een evenement is gepland op een bepaalde dag van de maand, bijvoorbeeld de 25e. Deze kolom voldoet aan deze eis. Likeweek_of_month
, het kan worden gevuld met positieve getallen ("7" voor de 7e dag vanaf het begin van de maand) of negatieve getallen ("-7" voor de zevende dag vanaf het einde van de maand).- De
recurring_type_id
zou "maandelijks" zijn. - De
separation_count
zou "2" zijn. - De
day_of_month
zou "11" zijn. - Alle resterende kolommen zijn null.
- Evenementen die plaatsvinden op feestdagen. Wanneer een bepaald geval van een gebeurtenis op een feestdag plaatsvindt, moet deze dan automatisch worden verplaatst naar de werkdag direct na de feestdag? Of moet het automatisch worden geannuleerd? In welke omstandigheden zou een van deze van toepassing zijn?
- Conflicten tussen evenementen. Wat als bepaalde gebeurtenissen (die elkaar uitsluiten) op dezelfde dag vallen?
De deskundige manier: Het opslaan van een terugkerend patroon en het programmatisch genereren van eerdere en toekomstige gebeurtenisinstanties. Deze oplossing pakt de nadelen van de naïeve oplossing aan. We zullen de expertoplossing in detail uitleggen in dit artikel.
Het voorgestelde model
Evenementen maken
Alle geplande evenementen, ongeacht hun reguliere of terugkerende karakter, worden vastgelegd in het event
tafel. Niet alle evenementen zijn terugkerende evenementen, dus we hebben een vlagkolom nodig, is_recurring
, in deze tabel om terugkerende gebeurtenissen expliciet op te geven. De event_title
en event_description
kolommen slaan het onderwerp op en een korte samenvatting van gebeurtenissen. Gebeurtenisbeschrijvingen zijn optioneel, daarom is deze kolom nullable.
Zoals hun namen doen vermoeden, is de start_date
en end_date
kolommen bevatten de begin- en einddatum van gebeurtenissen. In het geval van reguliere evenementen slaan deze kolommen de werkelijke start- en einddatum op. Ze slaan echter ook de datums op van de eerste en laatste keer dat periodieke gebeurtenissen plaatsvinden. We behouden de end_date
kolom als nullable, aangezien gebruikers terugkerende gebeurtenissen zonder einddatum kunnen configureren. In dit geval worden toekomstige gebeurtenissen tot een hypothetische einddatum (bijvoorbeeld een jaar) weergegeven in de gebruikersinterface.
Het is_full_date_event
kolom geeft aan of een evenement een evenement van een hele dag is. In het geval van een evenement dat een hele dag duurt, wordt de start_time
en end_time
kolommen zouden null zijn; dat is de reden om beide kolommen nullable te houden.
De created_by
en created_date
kolommen slaan op welke gebruiker een evenement heeft gemaakt en de datum waarop dat evenement is gemaakt.
Vervolgens is er de parent_event_id
kolom. Dit speelt een grote rol in ons datamodel. De betekenis ervan zal ik later uitleggen.
Herhalingen beheren
Nu komen we meteen bij de belangrijkste probleemstelling:wat als een terugkerende gebeurtenis wordt gemaakt in de event
tabel – d.w.z. de is_recurring
vlag voor het evenement is "Y"?
Zoals eerder uitgelegd, zullen we een terugkerend patroon voor gebeurtenissen opslaan, zodat we al zijn toekomstige gebeurtenissen kunnen construeren. Laten we beginnen met het maken van het recurring_pattern
tafel. Deze tabel heeft de volgende kolommen:
Laten we eens kijken naar de betekenis van de resterende kolommen in termen van de verschillende soorten recidieven.
Dagelijkse herhaling
Moeten we echt een patroon vastleggen voor een dagelijks terugkerend evenement? Nee, want alle details die nodig zijn om een dagelijks herhalingspatroon te genereren, zijn al vastgelegd in het event
tafel.
Het enige scenario dat een patroon vereist, is wanneer gebeurtenissen worden gepland om andere dagen of om de X aantal dagen. In dit geval is de separation_count
kolom zal ons helpen het herhalingspatroon te begrijpen en verdere instanties af te leiden.
Wekelijkse herhaling
We hebben slechts één extra kolom nodig, day_of_week
, om op te slaan op welke dag van de week dit evenement zal plaatsvinden. Ervan uitgaande dat maandag de eerste dag van de week is en zondag de laatste, zijn de mogelijke waarden 1,2,3,4,5,6 en 7. Indien nodig moeten de nodige wijzigingen worden aangebracht in de code die afzonderlijke gebeurtenissen genereert. Alle overige kolommen zijn null voor wekelijkse evenementen.
Laten we een klassiek soort wekelijkse gebeurtenis nemen:de tweewekelijkse gebeurtenis. In dit geval zeggen we dat het elke andere week op een dinsdag, de tweede dag van de week, gebeurt. Dus:
Maandelijks herhaling
Naast day_of_week
, hebben we nog twee kolommen nodig om te voldoen aan elk maandelijks herhalingsscenario. In het kort zijn deze kolommen:
Laten we nu een ingewikkelder voorbeeld bekijken:een driemaandelijks evenement. Stel dat een bedrijf een kwartaalresultaatprojectie-evenement plant voor de 11e dag van de eerste maand van elk kwartaal (meestal januari, april, juli en oktober). Dus in dit geval:
In het bovenstaande voorbeeld gaan we ervan uit dat de gebruiker de kwartaalresultaatprognose in januari maakt. Houd er rekening mee dat deze scheidingslogica begint te tellen vanaf de maand, week of dag waarop de afspraak is gemaakt.
Op dezelfde manier kunnen halfjaarlijkse evenementen worden vastgelegd als maandelijkse evenementen met een
Jaarlijkse herhaling is vrij eenvoudig. We hebben kolommen voor bepaalde dagen van de week en de maand, dus we hebben slechts één extra kolom nodig voor de maand van het jaar. We hebben deze kolom de naam
Laten we nu naar de uitzonderingen gaan. Wat als een bepaald geval van een terugkerend evenement wordt geannuleerd of verplaatst? Al dergelijke instanties worden afzonderlijk geregistreerd in de
Laten we eens kijken naar twee kolommen,
Afgezien van deze twee kolommen, werken alle overige kolommen hetzelfde als in de
Er zijn applicaties waarmee gebruikers alle toekomstige gevallen van een terugkerend evenement opnieuw kunnen plannen. In dergelijke gevallen hebben we twee opties. We kunnen alle toekomstige instanties opslaan in
Met deze oplossing kunnen we alle eerdere gebeurtenissen van een gebeurtenis ophalen, zelfs als het herhalingspatroon is gewijzigd.
Er zijn een aantal complexere gebieden rond terugkerende evenementen die we niet hebben besproken. Hier zijn er twee:
Welke veranderingen moeten we doorvoeren om deze mogelijkheden in te bouwen? Vertel ons uw mening in het opmerkingengedeelte.separation_count
van “5”.Jaarlijks herhaling
month_of_year
.Uitzonderingen van terugkerende gebeurtenissen afhandelen
event_instance_exception
tafel. Is_rescheduled
en is_cancelled
. Deze kolommen geven aan of deze instantie wordt verplaatst naar een latere datum/tijd of helemaal wordt geannuleerd. Waarom heb ik hiervoor twee aparte kolommen? Nou, denk maar aan evenementen die eerst opnieuw werden gepland en later volledig werden geannuleerd. Dit gebeurt, en we hebben een manier om het op te nemen met deze kolommen. event
tafel.Waarom twee evenementen koppelen door middel van
parent_event_id
?event_instance_exception
(tip:geen acceptabele oplossing). Of we kunnen een nieuw evenement maken met nieuwe datum/tijd parameters in het event
tabel en koppel deze met zijn eerdere gebeurtenis (de bovenliggende gebeurtenis) door middel van de id_parent_event
kolom. Hoe de afhandeling van terugkerende gebeurtenissen verbeteren?