En tilbagevendende begivenhed er per definition en begivenhed, der gentager sig med et interval; det kaldes også en periodisk begivenhed. Der er mange applikationer, som giver deres brugere mulighed for at konfigurere tilbagevendende begivenheder. Hvordan håndterer et databasesystem tilbagevendende hændelser? I denne artikel vil vi undersøge en måde, hvorpå de håndteres.
Gentagelse er ikke let for ansøgninger at håndtere. Det kan blive en orkanopgave, især når det kommer til at dække alle mulige tilbagevendende scenarier – herunder oprettelse af to-ugentlige eller kvartalsvise begivenheder eller tillade omlægning af alle fremtidige begivenhedstilfælde.
To måder at administrere tilbagevendende begivenheder på
Jeg kan komme i tanke om mindst to måder at håndtere periodiske opgaver i en datamodel. Før vi diskuterer dem, lad os hurtigt gennemgå kravene til denne opgave. I en nøddeskal betyder effektiv ledelse:
- Brugere har lov til at oprette regelmæssige og tilbagevendende begivenheder.
- Daglige, ugentlige, to-ugentlige, månedlige, kvartalsvise, to-årige og årlige begivenheder kan oprettes uden begrænsninger for slutdato.
- Brugere kan omplanlægge eller annullere en forekomst af en begivenhed eller alle fremtidige forekomster af en begivenhed.
I betragtning af disse parametre kommer to måder at håndtere tilbagevendende hændelser på i datamodellen til at tænke på. Vi vil kalde dem den naive måde og den ekspert måde.
Den naive måde: Lagring af alle mulige tilbagevendende forekomster af en begivenhed som separate rækker i en tabel. I denne løsning kræver vi kun én tabel, nemlig event
. Denne tabel har kolonner som event_title
, start_date
, end_date
, is_full_day_event
osv. start_date
og end_date
kolonner er tidsstempeldatatyper; på denne måde kan de imødekomme begivenheder, der ikke varer hele dagen.
Fordele: Dette er en ret ligetil tilgang og den enkleste at implementere.
Udemper: Den naive måde har nogle væsentlige ulemper, herunder:
- Behovet for at gemme alle mulige forekomster af en begivenhed. Hvis du tager hensyn til en stor brugerbase, kræves der en stor del af pladsen. Pladsen er dog ret billig, så dette punkt har ingen større betydning.
- En meget rodet opdateringsproces. Antag, at en begivenhed er omlagt. I så fald skal nogen opdatere alle forekomster af det. Et stort antal DML-handlinger skal udføres ved omlægning, hvilket har en negativ indvirkning på applikationens ydeevne.
- Håndtering af undtagelser. Alle undtagelser skal håndteres med ynde, især hvis du skal gå tilbage og redigere den oprindelige aftale efter at have lavet en undtagelse. Antag for eksempel, at du flytter den tredje forekomst af en tilbagevendende begivenhed frem med en dag. Hvad hvis du efterfølgende redigerer tidspunktet for den oprindelige begivenhed? Genindsætter du en anden begivenhed på den oprindelige dag og forlader den, du har fremført? Vil du fjerne linket til undtagelsen? Prøv at ændre det korrekt?
Event_id
– Denne kolonne er henvist fraevent
tabel, og den fungerer som den primære nøgle i denne tabel. Det viser det identificerende forhold mellemevent
ogrecurring_pattern
tabeller. Denne kolonne vil også sikre, at der er maksimalt ét tilbagevendende mønster, der eksisterer for hver begivenhed.Recurring_type_id
– Denne kolonne angiver typen af gentagelse, uanset om det er dagligt, ugentligt, månedligt eller årligt.Max_num_of_occurrances
– Der er tidspunkter, hvor vi ikke kender den nøjagtige slutdato for en begivenhed, men vi ved, hvor mange begivenheder (møder), der skal til for at gennemføre den. Denne kolonne gemmer et vilkårligt tal, der definerer den logiske ende for en hændelse.Separation_count
– Du undrer dig måske over, hvordan en hændelse hver anden uge eller anden gang kan konfigureres, hvis der kun er fire mulige værdier af gentagelsestypen (dagligt, ugentligt, månedligt, årligt). Svaret erseparation_count
kolonne. Denne kolonne angiver intervallet (i dage, uger eller måneder), før den næste hændelsesinstans er tilladt. For eksempel, hvis en begivenhed skal konfigureres hver anden uge, så separation_count ="1" at opfylde dette krav. Standardværdien for denne kolonne er "0".- Det
recurring_type_id
ville være "ugentlig". separation_count
ville være "1".day_of_week
ville være "2".Week_of_month
– Denne kolonne er for begivenheder, der er planlagt til en bestemt uge i måneden – dvs. den første, anden, sidste, næstsidste osv. Vi kan gemme disse værdier som 1,2,3, 4,.. (tæller fra kl. begyndelsen af måneden) eller -1,-2,-3,... (tæller fra slutningen af måneden).Day_of_month
– Der er tilfælde, hvor en begivenhed er planlagt på en bestemt dag i måneden, f.eks. den 25. Denne kolonne opfylder dette krav. Ligesomweek_of_month
, kan den udfyldes med positive tal ( "7" for den 7. dag fra begyndelsen af måneden) eller negative tal ( "-7" for den syvende dag fra slutningen af måneden).- Det
recurring_type_id
ville være "månedlig". separation_count
ville være "2".day_of_month
ville være "11".- Alle resterende kolonner er null.
- Begivenheder, der opstår på helligdage. Når et bestemt tilfælde af en begivenhed indtræffer på en helligdag, skal den så automatisk flyttes til arbejdsdagen umiddelbart efter helligdagen? Eller skal det automatisk annulleres? Under hvilke omstændigheder ville en af disse være gældende?
- Konflikter mellem begivenheder. Hvad hvis visse begivenheder (der gensidigt udelukker) falder på samme dag?
The Expert Way: Lagring af et tilbagevendende mønster og generering af tidligere og fremtidige begivenhedstilfælde programmatisk. Denne løsning adresserer ulemperne ved den naive løsning. Vi forklarer ekspertløsningen i detaljer i denne artikel.
Den foreslåede model
Oprettelse af begivenheder
Alle planlagte begivenheder, uanset deres regelmæssige eller tilbagevendende karakter, logges i event
bord. Ikke alle begivenheder er tilbagevendende begivenheder, så vi skal bruge en flagkolonne, is_recurring
, i denne tabel for eksplicit at angive tilbagevendende hændelser. event_title
og event_description
kolonner gemmer emnet og en kort oversigt over begivenheder. Begivenhedsbeskrivelser er valgfri, hvorfor denne kolonne er nullbar.
Som deres navne antyder, er start_date
og end_date
kolonner gemmer start- og slutdatoerne for begivenheder. I tilfælde af regelmæssige begivenheder gemmer disse kolonner faktiske start- og slutdatoer. Men de gemmer også datoerne for den første og sidste forekomst af periodiske begivenheder. Vi beholder end_date
kolonne som nullbar, da brugere kan konfigurere tilbagevendende begivenheder uden slutdato. I dette tilfælde vil fremtidige forekomster op til en hypotetisk slutdato (f.eks. et år) blive vist i brugergrænsefladen.
is_full_date_event
kolonne angiver, om en begivenhed er en heldagsbegivenhed. I tilfælde af en heldagsbegivenhed, start_time
og end_time
kolonner ville være nul; det er grunden til at holde begge disse kolonner ugyldige.
created_by
og created_date
kolonner gemmer, hvilken bruger der har oprettet en begivenhed og datoen, hvor begivenheden blev oprettet.
Dernæst er der parent_event_id
kolonne. Dette spiller en stor rolle i vores datamodel. Jeg vil forklare dens betydning senere.
Håndtering af gentagelser
Nu kommer vi direkte til hovedproblemformuleringen:Hvad hvis der oprettes en tilbagevendende begivenhed i event
tabel – dvs. den is_recurring
flag for begivenheden er "Y"?
Som forklaret tidligere vil vi gemme et tilbagevendende mønster for begivenheder, så vi kan konstruere alle dets fremtidige begivenheder. Lad os starte med at oprette recurring_pattern
bord. Denne tabel har følgende kolonner:
Lad os overveje betydningen af de resterende kolonner i forhold til de forskellige typer af gentagelser.
Daglig gentagelse
Har vi virkelig brug for at fange et mønster for en daglig tilbagevendende begivenhed? Nej, fordi alle de detaljer, der kræves for at generere et dagligt gentagelsesmønster, allerede er logget i event
tabel.
Det eneste scenarie, der kræver et mønster, er, når begivenheder er planlagt til alternative dage eller hvert X antal dage. I dette tilfælde er separation_count
kolonne vil hjælpe os med at forstå gentagelsesmønsteret og udlede yderligere forekomster.
Ugentligt gentagelse
Vi kræver kun én ekstra kolonne, day_of_week
, for at gemme, hvilken dag i ugen denne begivenhed finder sted. Hvis det antages, at mandag er den første dag i ugen, og søndag er den sidste, vil mulige værdier være 1,2,3,4,5,6 og 7. Passende ændringer i koden, der genererer individuelle hændelser, bør foretages efter behov. Alle resterende kolonner vil være nul for ugentlige begivenheder.
Lad os tage en klassisk type ugentlig begivenhed:den to-ugentlige begivenhed. I dette tilfælde vil vi sige, at det sker hver anden uge på en tirsdag, den anden dag i ugen. Så:
Månedlig gentagelse
Udover day_of_week
, kræver vi yderligere to kolonner for at opfylde ethvert månedligt gentagelsesscenarie. Kort fortalt er disse kolonner:
Lad os nu overveje et mere kompliceret eksempel - en kvartalsvis begivenhed. Antag, at en virksomhed planlægger en kvartalsvis resultatfremskrivningsbegivenhed for de 11 dage i den første måned i hvert kvartal (normalt januar, april, juli og oktober). Så i dette tilfælde:
I ovenstående eksempel antager vi, at brugeren opretter den kvartalsvise resultatfremskrivning i januar. Bemærk venligst, at denne adskillelseslogik begynder at tælle fra den måned, uge eller dag, hvor begivenheden oprettes.
På lignende linjer kan halvårlige hændelser logges som månedlige hændelser med en
Årlig gentagelse er ret ligetil. Vi har kolonner for bestemte dage i ugen og måneden, så vi kræver kun én ekstra kolonne for måneden i året. Vi har givet denne kolonne navn til
Lad os nu komme til undtagelserne. Hvad hvis en bestemt forekomst af en tilbagevendende begivenhed aflyses eller omlægges? Alle sådanne forekomster logges separat i
Lad os tage et kig på to kolonner,
Bortset fra disse to kolonner fungerer alle resterende kolonner på samme måde som i
Der er applikationer, som giver brugerne mulighed for at omplanlægge alle fremtidige tilfælde af en tilbagevendende begivenhed. I sådanne tilfælde har vi to muligheder. Vi kan gemme alle fremtidige forekomster i
Med denne løsning kan vi få alle tidligere forekomster af en begivenhed, selv når dens gentagelsesmønster er blevet ændret.
Der er nogle mere komplekse områder omkring tilbagevendende begivenheder, som vi ikke har diskuteret. Her er to:
Hvilke ændringer skal vi foretage for at indbygge disse kapaciteter? Fortæl os venligst dine synspunkter i kommentarfeltet.separation_count
af "5".Årlig gentagelse
month_of_year
.Håndtering af undtagelser fra tilbagevendende begivenheder
event_instance_exception
bord. Is_rescheduled
og is_cancelled
. Disse kolonner angiver, om denne forekomst er omlagt til en senere dato/tid eller helt annulleret. Hvorfor har jeg to separate kolonner til dette? Tænk bare på begivenheder, der først blev flyttet og senere helt aflyst. Dette sker, og vi har en måde at optage det på med disse kolonner. event
tabel.Hvorfor sammenkæde to begivenheder ved hjælp af
parent_event_id
?event_instance_exception
(tip:ikke en acceptabel løsning). Eller vi kan oprette en ny begivenhed med nye dato/tidsparametre i event
tabel og link den til dens tidligere hændelse (den overordnede hændelse) ved hjælp af id_parent_event
kolonne. Hvordan forbedres håndteringen af tilbagevendende begivenheder?