Calendar alarms and replication are a real problem for the following reason: 1) calalarmd needs to only run on the master, not the replica - otherwise the alarm will fire on both, and the alarmd on the replica will write annotations, causing split brain issues. 2) the caldav_alarms.sqlite3 database on the replica needs to have all the nextalarm values in sync with the master, so if there's a failover event, the calalarmd on the ex-replica knows which records are interesting without having to parse every single mailbox! 3) replication and annotations is a disaster - the record gets written first, and the annotations later. So we solve this as follows:
a) if record.silent is set, we don't write the caldav_alarms.sqlite3 event line for the record immediately. b) AFTER we have applied both the record and any annotations for the record in sync_support.c, we call caldav_alarm_touch_record(), which can then read the annotation to see when the nextalarm should be. The problem is this: if there's already a nextalarm value, and we change a record to have an earlier alarm for whatever reason, the alarm annotation just gets copied by dav_store_resource to the new record, and hence there's already a nextalarm in the future. This OVERWRITES the earlier alarm value created by caldav_alarm_new_record(). The fix is this: instead of blindly overwriting, caldav_alarm_touch_record needs to have two modes: sync mode and non- sync mode. In sync mode, it's a replica - so it just does what it does now - blindly writes the value from the annotation. In non-sync mode, it instead always reads the record (plus any per-user overrides) and finds the time that it next needs to be checked. Easy-peasy :) I might even just call it two different things to make it extra clear what's going on! Bron. -- Bron Gondwana, CEO, FastMail Pty Ltd br...@fastmailteam.com