Design – How to Create a Recurring Event in an Agenda

Architecturedesign

I have an entity (model) called Notification, shown to Users of the system. So far, Notifications were created and showed instantly to users when they were enabled, and hidden when disabled or deleted. Also, Users can close/cancel the Notification so they don't see it anymore and that action is persisted in a collection (database table) of Notifications viewed by Users. The system must now implement repetitions of those Notifications, like agendas or calendars in which entries can be repeated daily, weekly, monthly, etc. and also send a email to the User the day before the Notification instance date. Conceptually how it is implemented? How about calculation of repetition?

So far, I've been thinking of persisting three new properties on the Notification entity, one for the type of repetition (daily, weekly, etc.), one for the start date(time) and another for the end date(time) and a new collection (database table) where I save "instances" of those Notifications (not instances like class instance, but a more generic concept of a single occurrence of something), with properties like notification id and start and end date(time) of that instance. That way Notifications themselves wouldn't be presented to Users, but the instances of those Notifications.
Then, I thought of a scheduled task (cronjob) that runs couple of times a day, generating instances from Notifications collection calculating when those repetitions should happen and also sending email when calculated instance date is tomorrow.

Not sure if this is the best way and I'd like to hear recommendations. I started to implement it that way and so far it seems easy, but I'm about to start with the logic of the scheduled task (the hardest part) and I wonder if it will be very complex to calculate the date of the instances based on repetition specification (daily seems easy, add a day to the date value, but how about each third friday of the month?).

Best Answer

This is when separating interface from implementation is important. Your interface should handle third Friday of every month and worse (The 3rd Friday of every month except move to the next business day that both parties to the contract agree is a business day based on the holiday table for the region the business is incorporated under), but you should only have to implement the cases that are real right now.

So I would make a scheduler interface that can be passed a time period, and the scheduler can fill the time period with instances when you tell it to. The logic of how to do that lives inside the scheduler object.

As far as the cron job - you could use this design and have a cron job that creates new instances, but you may find you just don't need it. It might be helpful to do something like the cron job if you need to write a database query against instances and you don't care about the logic of the schedule that created them. If the cron job runs quickly enough you may be able to just trigger the job whenever you need the data to be current, instead of using cron.

Related Topic