<!DOCTYPE html><html><head><title></title><style type="text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style></head><body><div style="font-family:Arial;">This is triggered by the fact that our current updates of calendar participants on overridden events is broken, and the reason is this:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"> 'recurrenceOverrides/2019-03-01T09:00:00/participants~1baz/participationStatus' => 'accepted',<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">This is a patch against an event with the following overrides.<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"> "recurrenceOverrides": {<br></div><div style="font-family:Arial;"> "2019-02-01T09:00:00": {<br></div><div style="font-family:Arial;"> "duration": "PT2H"<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"> "2019-03-01T09:00:00": {<br></div><div style="font-family:Arial;"> "participants/baz": {<br></div><div style="font-family:Arial;"> "@type": "Participant",<br></div><div style="font-family:Arial;"> "sendTo": {<br></div><div style="font-family:Arial;"> "imip": "mailto:baz@local"<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"> "email": "baz@local",<br></div><div style="font-family:Arial;"> "name": "Baz",<br></div><div style="font-family:Arial;"> "kind": "individual",<br></div><div style="font-family:Arial;"> "roles": {<br></div><div style="font-family:Arial;"> "attendee": true<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"> "locationId": "loc3",<br></div><div style="font-family:Arial;"> "participationStatus": "needs-action",<br></div><div style="font-family:Arial;"> "expectReply": true,<br></div><div style="font-family:Arial;"> "scheduleSequence": 0<br></div><div style="font-family:Arial;"> }<br></div><div style="font-family:Arial;"> }<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">And the following participants at the top level:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"> "participants": {<br></div><div style="font-family:Arial;"> "bar": {<br></div><div style="font-family:Arial;"> "@type": "Participant",<br></div><div style="font-family:Arial;"> "sendTo": {<br></div><div style="font-family:Arial;"> "imip": "mailto:bar@local"<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"> "email": "bar@local",<br></div><div style="font-family:Arial;"> "name": "Bar",<br></div><div style="font-family:Arial;"> "kind": "individual",<br></div><div style="font-family:Arial;"> "roles": {<br></div><div style="font-family:Arial;"> "attendee": true<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"> "locationId": "loc2",<br></div><div style="font-family:Arial;"> "participationStatus": "needs-action",<br></div><div style="font-family:Arial;"> "expectReply": true,<br></div><div style="font-family:Arial;"> "scheduleSequence": 0<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"> "foo": {<br></div><div style="font-family:Arial;"> "@type": "Participant",<br></div><div style="font-family:Arial;"> "sendTo": {<br></div><div style="font-family:Arial;"> "imip": "mailto:foo@local"<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"> "email": "foo@local",<br></div><div style="font-family:Arial;"> "name": "Foo",<br></div><div style="font-family:Arial;"> "kind": "individual",<br></div><div style="font-family:Arial;"> "roles": {<br></div><div style="font-family:Arial;"> "owner": true,<br></div><div style="font-family:Arial;"> "attendee": true,<br></div><div style="font-family:Arial;"> "chair": true<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"> "locationId": "loc1",<br></div><div style="font-family:Arial;"> "participationStatus": "accepted",<br></div><div style="font-family:Arial;"> "expectReply": false,<br></div><div style="font-family:Arial;"> "scheduleSequence": 0,<br></div><div style="font-family:Arial;"> "participationComment": "Sure; see you \\"soon\\"!"<br></div><div style="font-family:Arial;"> }<br></div><div style="font-family:Arial;"> },<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">Note that if 'baz' was also present on the top level, the patch with this syntax would be:<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">'recurrenceOverrides/2019-03-01T09:00:00/participants~1baz~1participationStatus' => 'accepted',<br></div><div style="font-family:Arial;"><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">And theoretically if there were no participants on the top level event (not possible in this model) it would be:<br></div><div style="font-family:Arial;"><br></div></div><div style="font-family:Arial;">'recurrenceOverrides/2019-03-01T09:00:00/participants/baz/participationStatus' => 'accepted',<br></div><div style="font-family:Arial;"><br>Because there would be a rich participants object in the override.</div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"><b>My contention is this:</b><b><br></b></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;"><div style="font-family:Arial;"><div style="font-family:Arial;">We should always patch the model, not the wire representation. The wire representation is a compact representation of the event, in which each recurrence override is just a patch of what needs to be changed, but critically <b>an entire copy of the event is a valid patch as well</b>.<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">I would argue that we should always patch the overrides as if we were patching a complete copy of the event, so that the last format is always correct. Otherwise, we're assuming that the server always calculates the patch in the same way, and there's no guarantee of that.<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">This means the client would need to be changed rather than Cyrus to fix our production bug. I have vague memories of discussing this with Robert and deciding that patching the entire model as if the datastructure was fully resolved is the only sane approach, now that I come back an dig into this some more. This means that it doesn't matter how the calendar event is stored on the server, because it always has a way to expand every recurrence out to the full object, and then calculate the minimised version for storage and /get again.<br></div><div style="font-family:Arial;"><br></div><div style="font-family:Arial;">This also means that we never get weird '~1' items in the patch paths when we update an event over the wire, which is kinda nice - and the same patch will still apply cleanly even if 'baz' got invited to the master event in the meantime. <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></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>