I'm building a web application that involves both recurrence and nested dependencies, and I'm struggling to pin down the appropriate data model.
The problem that the application aims to solve is: we have a few processes that we need to do at regular intervals, which involve multiple steps and multiple people. Some of those steps can't begin until earlier steps are completed. For example:
- Every month, we need to produce an exec briefing on the previous month's performance. Once the month ends, 3 people need to pull data from 3 systems. Once all 3 have been pulled, a fourth person needs to analyse the data and prepare the briefing. This process should begin on the 1st of the month, though exceptions are made for weekends/holidays, etc.
The web application should be able to:
- Show all tasks that are currently actionable (e.g. not blocked by other tasks they depend on)
- Modify future occurrences (e.g. skip one, or change a date) like you would a repeating event on a calendar
- Keep history for each task, e.g. completion date and who completed it, and comments
I think the nested dependency aspect is a bit easier to solve, or at least more familiar to me: a recursive common table expression seems a good fit for it. Where I'm struggling is making this work with recurrence.
Options I've considered so far:
A. 'definitions' and 'instances' tables
e.g. process_definitions
, process_instances
, task_definitions
, and task_instances
.
Project future instances using the schedule from the definition (e.g. via generate_series()
), and create the instances at the point the user interacts with one (e.g. to change its date, mark it completed, leave a comment).
The trouble with this is:
- What about the dependencies? I'd normally have a
task_dependencies
table, since it's a many-to-many relationship. I'd either need to copy these records for each task instance (which could quickly amount to a very large table), or do a rather convoluted join (instead oftask_instances
->task_instance_dependencies
->task_instances
, it would betask_instances
->task_definitions
->task_dependencies
->task_definitions
->task_instances
)
B. denormalised version
Similar to (my understanding of) an iCalendar feed, just have a single table of processes
and a single table of tasks
with the definitions copied to each instance. This is potentially simpler (though may just shift the complexity), but would still lead to a very large task_dependencies
table.
C. array column
Store task dependencies as an ARRAY
column, but then I wouldn't get the benefit of foreign key constraints (and I'm not actually sure how to do JOINs that way anyway)
How would you design the data model for this use case?