This is triggered by the fact that our current updates of calendar participants 
on overridden events is broken, and the reason is this:

 
'recurrenceOverrides/2019-03-01T09:00:00/participants~1baz/participationStatus' 
=> 'accepted',

This is a patch against an event with the following overrides.

 "recurrenceOverrides": {
 "2019-02-01T09:00:00": {
 "duration": "PT2H"
 },
 "2019-03-01T09:00:00": {
 "participants/baz": {
 "@type": "Participant",
 "sendTo": {
 "imip": "mailto:baz@local";
 },
 "email": "baz@local",
 "name": "Baz",
 "kind": "individual",
 "roles": {
 "attendee": true
 },
 "locationId": "loc3",
 "participationStatus": "needs-action",
 "expectReply": true,
 "scheduleSequence": 0
 }
 }
 },

And the following participants at the top level:

 "participants": {
 "bar": {
 "@type": "Participant",
 "sendTo": {
 "imip": "mailto:bar@local";
 },
 "email": "bar@local",
 "name": "Bar",
 "kind": "individual",
 "roles": {
 "attendee": true
 },
 "locationId": "loc2",
 "participationStatus": "needs-action",
 "expectReply": true,
 "scheduleSequence": 0
 },
 "foo": {
 "@type": "Participant",
 "sendTo": {
 "imip": "mailto:foo@local";
 },
 "email": "foo@local",
 "name": "Foo",
 "kind": "individual",
 "roles": {
 "owner": true,
 "attendee": true,
 "chair": true
 },
 "locationId": "loc1",
 "participationStatus": "accepted",
 "expectReply": false,
 "scheduleSequence": 0,
 "participationComment": "Sure; see you \\"soon\\"!"
 }
 },

Note that if 'baz' was also present on the top level, the patch with this 
syntax would be:

'recurrenceOverrides/2019-03-01T09:00:00/participants~1baz~1participationStatus'
 => 'accepted',

And theoretically if there were no participants on the top level event (not 
possible in this model) it would be:

'recurrenceOverrides/2019-03-01T09:00:00/participants/baz/participationStatus' 
=> 'accepted',

Because there would be a rich participants object in the override.

*My contention is this:**
*

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 
*an entire copy of the event is a valid patch as well*.

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.

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.

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. 

Bron.

--
 Bron Gondwana, CEO, Fastmail Pty Ltd
 br...@fastmailteam.com

Reply via email to