<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style>
</head>
<body><div style="font-family:Arial;">Calendar alarms and replication are a real problem for the following reason:<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">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.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">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!<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">3) replication and annotations is a disaster - the record gets written first, and the annotations later.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">So we solve this as follows:<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">a) if record.silent is set, we don't write the caldav_alarms.sqlite3 event line for the record immediately.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">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.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">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().<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">The fix is this: instead of blindly overwriting, caldav_alarm_touch_record needs to have two modes: sync mode and non-sync mode.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">In sync mode, it's a replica - so it just does what it does now - blindly writes the value from the annotation.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">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.<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">Easy-peasy :)  I might even just call it two different things to make it extra clear what's going on!<br></div>
<div style="font-family:Arial;"><br></div>
<div style="font-family:Arial;">Bron.<br></div>
<div style="font-family:Arial;"><br></div>
<div id="sig56629417"><div class="signature">--<br></div>
<div class="signature">  Bron Gondwana, CEO, FastMail Pty Ltd<br></div>
<div class="signature">  brong@fastmailteam.com<br></div>
<div class="signature"><br></div>
</div>
<div style="font-family:Arial;"><br></div>
</body>
</html>