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
[email protected]