Re: RECURRENCE-ID discussion
<Bruce_Kahn <at> notesdev.ibm.com>
2003-08-04 15:36:48 GMT
Satya asked on 07/31/2003 06:43:38 PM:
> Is there an update on when the iCal authors will post their thinking
on
> the subject?
I had hoped that reading the RFCs and
searching the archives would have put this to rest once and for all but
perhaps not for some. So let me take some time to review both the
RFC text and to technically analyze why the iCalendar specified a fixed
RECURRENCE-ID. This is going to be a somewhat long posting in order
to cover both iCalendar, iTIP and the claims that purportedly define a
changing RECURRENCE-ID model.
First, lets start with a review of the
RFCs. The 2 RFCs in question are 2445 (iCalendar) and 2446 (iTIP).
iCalendars role is to define the various properties and property
parameters as well as specify their behaviour / intent. iTIPs role
is to give the iCalendar properties semantic meaning that all implementations
can follow to interop. So lets start with reviewing the actual definition
of RECURRENCE-ID (Section 4.8.4.4 Recurrence ID).
Description: The full range of calendar
components specified by a
recurrence set is referenced by referring to just the "UID"
property
value corresponding to the calendar component. The "RECURRENCE-ID"
property allows the reference to an individual instance within
the
recurrence set.
[Snip]
The date/time value is set to the time when the original recurrence
instance would occur; meaning that if the intent is to change a
Friday meeting to Thursday, the date/time is still set to the
original Friday meeting.
The "RECURRENCE-ID" property is used in conjunction with
the "UID"
and "SEQUENCE" property to identify a particular instance
of a
recurring event, to-do or journal. For a given pair of "UID"
and
"SEQUENCE" property values, the "RECURRENCE-ID"
value for a
recurrence instance is fixed. When the definition of the recurrence
set for a calendar component changes, and hence the "SEQUENCE"
property value changes, the "RECURRENCE-ID" for a given
recurrence
instance might also change. [Snip]
Some folks seem to blindly ignore the 2nd (above, 3rd in the actual RFC)
paragraph which clearly and unequivocally says that when a reschedule takes
place the RECURRENCE-ID value "is still set to the original"
value! This of course flat out defeats the claim that "RECURRENCE-ID
changes on each reschedule" as some have claimed so its easy to see
why overlooking it happens.
In looking at the oft cited last paragraph
you will find that the key phrase is "When
the definition of the recurrence set for a calendar component changes...the
"RECURRENCE-ID" for a given recurrence instance might also change".
The important bit that seems to be misread is "definition
of the recurrence set";
it does not say "definition of the recurrence
_instance_".
So its likely that this is partly to blame for some misinterpreting the
description to mean "Whenever the instance is rescheduled, the recurrence
instance also changes" This does make a couple minor but not
insignficant changes to the phrasing such as changing "might also
change" into "always changes" but these changes are best
ignored if you want to change the model.
Of course these changes would conflict
with the entire paragraph before it so some would just ignore it in favor
of their reinterpreatation of the prose. However it must be noted
that iCalendar clearly proscribes a "fixed" RECURRENCE-ID in
at least 2 places.
In addition Doug has claimed that "'original'
means currently booked version" but thats nowhere near the meaning
of the word original. Instead of arguing a common sense meaning Ill
instead defer to Merriam-Webster who define it as:
Main Entry: 2original
Function: adjective
Date: 14th century
1 : of, relating to, or constituting an origin or beginning
: INITIAL
<the original part of the house>
2 a : not secondary, derivative, or imitative b :
being the first instance or source from which a copy, reproduction, or
translation is or can be made
So "original" means the the
same as the "initial" value, NOT the "latest" or "most
recent". This definition matches the paragraph in describing
how RECURRENCE-ID stayed at the Friday date/time. The reason that
a fixed RECURRENCE-ID was specified over a varying one will become evident
as we move into analyzing iTIP so lets do that now.
iTIP defines its role in relation to
iCalendar as:
iTIP complements the iCalendar object specification by adding
semantics for group scheduling methods commonly available in current
calendar systems.
so its role is NOT to impart (or modify)
any defintion to the iCalendar properties or property parameters, thats
the function of iCalendar. The semantics for "group
scheduling methods" are
done in the various iTIP methods or messages. iTIP messages can be
sent over any kind of media or using assorted methods so the protocol had
to first define some guidelines to apply to all messages to properly deal
with missequencing on the receiving end. That is done in Section
2.1.5 Message Sequencing, before any direct discussion of individual messages
was done. In Section 2.1.5 Message Sequencing we see:
1. The primary key for referencing
a particular iCalendar component
is the "UID" property value. To reference
an instance of a
recurring component, the primary key is composed
of the "UID" and
the "RECURRENCE-ID" properties.
2. The secondary key for referencing a component is the "SEQUENCE"
property value. For components where the "UID"
is the same, the
component with the highest numeric value for the
"SEQUENCE"
property obsoletes all other revisions of the component
with
lower values.
Thus for repeating instances the primary
key value used to find the instance the message refers to is the UID /
RECURRENCE-ID pair. Once this pair is used to find the instance in
question the SEQUENCE property can be used to determine if the message
is newer or older than the one the recipient has. Or in iTIP terms,
tell if the message has already been obsoleted or if it should obsolete
the recipients copy. Nothing here claims that RECURRENCE-ID changes
on each reschedule and in order to be fault tolerant and easily recoverable
RECURRENCE-ID should not change (iCalendar prose not withstanding). This
can be seen in the prose found in other sections in iTIP such as Sections
3.2.2 REQUEST, 3.2.2.1 Rescheduling an Event, 3.2.2.2 Updating or Reconfirmation
of an Event, or even the often misquoted Section 4.7.2 Bad RECURRENCE-ID.
Section 3 of iTIP is where the actual
protocol definitions happen. Its where iTIP defines what a meeting
request or response look like, etc. Section 4 of iTIP is where the
authors provided assorted examples of actual iTIP messages from Section
3. As such its merely the demonstrative part of the iTIP RFC and
does not carry the same weight. The authors were always grumbling
about the inclusion of examples ("If we put in an example of X then
everyone will code to that and not to the text" as they so often lamented
in meetings, emails and here on the list) and now this has come back to
haunt us based on a misreading of iCalendar and a line or two in the examples
section of iTIP (not even in the defintion section of iTIP). In any case,
lets continue the analysis promised.
iTIP Section 3.2.2 REQUEST in part reads:
The "UID" and "SEQUENCE"
properties are used to distinguish the
various uses of the "REQUEST" method. If the "UID"
property value in
the "REQUEST" is not found on the recipient's calendar,
then the
"REQUEST" is for a new "VEVENT" calendar component.
If the "UID"
property value is found on the recipient's calendar, then the
"REQUEST" is for a rescheduling, an update, or a reconfirm
of the
"VEVENT" calendar component.
and if you apply the rules from Section
2.1.5 to this you should get that if the UID/RECURRENCE-ID are not found
in the recipients calendar then its a new REQUEST, otherwise its an update.
Implicitly this concurs with iCalendar and Section 2.1.5 because
if the RECURRENCE-ID changed and one or more iTIP REQUESTs were missed
(or delayed!) then the recipient has NO way to properly perform this match
and thus they would treat the REQUEST as a new invitation rather than a
reschedule.
In case that was not clear enough for
some Ill try to make it as clear as I can: If I send you a REQUEST for
a particular UID and RECURRENCE-ID that you do not have then you are to
treat it as a new invitation by the definition of REQUEST. So you
want the UID / RECURRENCE-ID values to never change from that point on
or else you will think you got _another_ new invitation rather than a rescheduling
of the one you already have!
If RECURRENCE-ID did change on each
reschedule (iCalendar prohibitions aside) then you have NO way to distinguish
between a new invitation and the case where you missed one or more reschedules.
This means that for the model where RECURRENCE-ID changes on each
reschedule, any single delayed or missequenced REQUEST can _only_ be recovered
by rescying up _all_instances_ of the repeat set! In addition if
the messages were just missequenced this results in _tons_ of extra wasted
workflow thrashing.
Lets compare the iCalendar defined fixed
RECURRENCE-ID model to the changing RECURRENCE-ID model of some and see
how they deal with missequenced messages. The scenario is I invite
you to an instance of a repeating meeting. After the initial invitation
I reschedule it two times to accomodate other invitees. So for simplicity
in references Ill refer to the initial invitation as SEQUENCE:0 and the
two reschedules as SEQUENCE:1 and SEQUENCE:2 respectively. Because
of network/server issues you recieve them in the order of SEQUENCE:0 then
SEQUENCE:2 and then SEQUENCE:1; a not uncommon case when using email (aka
iMIP).
First the fixed RECURRENCE-ID model
analysis:
When you receive the SEQUENCE:0 invitation
you apply Section 2.1.5 and 3.2.2 and determine that this is a new meeting
invitation which you take some action on to get it onto your calendar.
You then receive SEQUENCE:2 and you
can match the UID / RECURRENCE-ID values and determine that the message
is newer and that it obsoletes your current copy. You may notice
that its SEQUENCE value is more than 1 different but since the higher valued
SEQUENCE "obsoletes all other revisions of
the component withlower values"
it is not an issue that you did not see SEQUENCE:1 (yet). You can
simply take action on it and send back a REPLY with the correct UID / RECURRENCE-ID
/ SEQUENCE:3 info on it and we are in sync.
You later receive the SEQUENCE:1 REQUEST.
You apply Section 2.1.5 and determine that your version is newer
and as such this REQUEST is obsoleted and should be ignored. No further
action is required by you since you are already in sync with me.
Now for the changing RECURRENCE-ID model
analysis:
When you receive the SEQUENCE:0 invitation
you apply Section 2.1.5 and 3.2.2 and determine that this is a new meeting
invitation which you take some action on to get it onto your calendar.
You then receive SEQUENCE:2 and you
can NOT match the UID / RECURRENCE-ID values in your calendar so you determine
that "something has gone wrong" (to borrow from the misquoted
Section 4.7.2). You MUST therefore take NO action on the REQUEST
since you cannot match the instance to one you currently have. You
can ONLY send a REFRESH message back to me with just the UID and NO RECURRENCE-ID.
This will cause me to generate another REQUEST to you "with
the latest description and version of the event"
(per iTIP Section 3.2.6 REFRESH). So I send you another REQUEST with
the latest RECURRENCE-ID at SEQUENCE:2 which happens to _exactly_
match the REQUEST you just tossed out. If you receive this new REQUEST
_before_ you get the missequenced SEQUENCE:1 REQUEST then you can _only_
repeat this loop indefinitely without recovery!
In the interim the SEQUENCE:1 REQUEST
arrives and you are able to apply Section 2.1.5 rules and find the correct
UID / RECURRENCE-ID instance and determine that the REQUEST obsoletes the
SEQUENCE:0 one you have. Now you can apply the currently obsolete
SEQUENCE:1 change to your SEQUENCE:0 instance and send back a REPLY to
me. I would of course detect that the UID / RECURRENCE-ID / SEQUENCE:1
REPLY is for an old copy (by applying 2.1.5) and thus I would have to ignore
it and send you yet another REQUEST at SEQUENCE:2. Now that you are
at SEQUENCE:1 you can safely match the UID / RECURRENCE-ID values and re-respond
at SEQUENCE:3.
This model has lots of drawbacks (hence
why we long ago opt'd for a "fixed" RECURRENCE-ID model). They
include:
1: Any missequencing of iTIP messages
cannot be recovered on a single instance case. You MUST resync up
ALL instances in the set, not just the instance in question. This
means potentially LOTS of extra wasted workflow messaging. All just
because of _1_ missquenced REQUEST (or REPLY if you invert the picture
for my side as Organizer).
2: If the problem is NOT a missequencing
of REQUESTs but rather recovery from a lost REQUEST (ie: an interim copy
got lost in a server crash, disk failure, admin purge, etc) then it is
not possible to recover when just one or some instances are involved since
RECURRENCE-IDs are always involved in the REQUEST/REPLY(/COUNTER/...) messages
when you correctly apply the restriction tables from iTIP. REQUEST
clearly says:
RECURRENCE-ID 0 or 1 only
if referring to an instance of a
recurring calendar component. Otherwise
it
MUST NOT be present.
so any initial or subsequent REQUESTs
MUST have a RECURRENCE-ID on them when referring to a particular instance.
Had you not received the SEQUENCE:1 REQUEST at some point you would
be infinitely stuck in the REFRESH/REQUEST loop above.
3: Since each instance can be reschedule
independently of its siblings, it can be shown that if the RECURRENCE-ID
changes it takes just 5 steps to misidentify the correct instance in question
in a REPLY (on the Organizers side). For the steps, go check the
archives for the 2 times its been pointed out.
The same kind of fault _intolerant_
behaviour can be seen for other cases in iTIP if you lay out the scenarios
(and ignore iCalendar too).
Now lets visit that misquoted iTIP Examples
Section 4.7.2 Bad RECURRENCE-ID lest some claim we are ignoring their citations
for justifying a changing RECURRENCE-ID model. iTIP Section 4.7.2
Bad RECURRENCE-ID is intended as an example section on how to deal with
problems matching UID / RECURRENCE-ID / SEQUENCE. It says "there
are three cases in which an instance cannot be found."
and describes them as:
1. The component with the referenced
"UID" and "RECURRENCE-ID" has
been found but the "SEQUENCE" number in
the calendar store does
not match that of the ITIP message.
2. The component with the referenced "UID" has
been found, the
"SEQUENCE" numbers match, but the "RECURRENCE-ID"
cannot be
found.
3. The "UID" and "SEQUENCE" numbers are
found but the CUA does not
support recurrences.
Case 3 is not germane and will be ignored
for this analysis.
Case 1 is dealt with in:
In case (1), two things can happen. If
the "SEQUENCE" number of the
"Attendee's" instance is larger than that in the "Organizer's"
message then the "Attendee" is receiving an out-of-sequence
message
and MUST ignore it. If the "SEQUENCE" number of
the "Attendee's"
instance is smaller, then the "Organizer" is sending
out a newer
version of the component and the "Attendee's" version
needs to be
updated. Since one or more updates have been missed, the "Attendee"
SHOULD send a "REFRESH" message to the "Organizer"
to get an updated
version of the event.
Here SEQUENCE is described as "smaller"
and "larger"
rather than "highest" and "lower" found in Section
2.1.5 but the implicit behaviour still matches. In order to match
a UID / RECURRENCE-ID / SEQUENCE combo where the UID and RECURRENCE-ID
values are "found" but the SEQUENCE value is "smaller"
or "larger" then it should be intuitive that UID and RECURRENCE-ID
do not change. Otherwise they could not be found to mismatch SEQUENCE!
So this description matches the behaviour under Section 2.1.5.
The last ine about "one
or more updates have been missed"
has been misused as justification for the recipient (ie: you in the above
examples) having to send a REFRESH to the Organizer (ie: me...). However
2 things need to be noted here:
A: The case is described as the one
where UID / RECURRENCE-ID matched but SEQUENCE did NOT and
B: The text says that the recipient
"SHOULD" send a REFRESH, not "MUST".
Now if you apply normal logic to the
analysis you should see that bullet A above cannot be done in a changing
RECURRENCE-ID model since the RECURRENCE-ID value changed! However
this is incongruence needs to be overlooked to use Section 4.7.2 as justifying
a changing RECURRENCE-ID model.
Also, bullet B does not say "MUST"
because it is NOT necessary! The larger/higher SEQUENCE version obsoletes
all smaller/lower SEQUENCE versions and as such a REFRESH is not really
necessary (except in a changing RECURRENCE-ID model).
Case 2 is dealt with in:
In case (2), something has gone wrong.
Both the "Organizer" and the
"Attendee" should have the same instances, but the "Attendee"
does
not have the referenced instance. In this case the "Attendee"
SHOULD
send a "REFRESH" to the "Organizer" to get
an updated version of the
event.
Aha, we now have problem with the fixed
RECURRENCE-ID model or do we? Actually we do not. If you receive
a REQUEST for an unknown UID / RECURRENCE-ID pair then if you apply the
text from Section 3.2.2 REQUEST correctly you simply view the REQUEST as
a new invitation. In this case to a new instance you did not know
about before. No problem here. Simply treat it as what it is,
a REQUEST to another instance and workflow functions as before.
Ah, we do have a problem though if we
used a changing RECURRENCE-ID model. The "something has gone
wrong" is that the message was missequenced. Gee, something
as simple as that means there is a problem?? Thats the sign of a
poor model (and one of the reasons the WG opt'd for the fixed RECURRENCE-ID
model) because to recover means lots of extraneous iTIP messages in both
directions.
In addition it should be noted that
not all Attendees are invited to all instances so the 2nd line is a bit
misleading. If I want to add you to an instance (or subset of instances)
of a repeating meeting Im organzing then obviously you wont have the "the
same instances". I suspect that this is an artifact of editing
because we do not expect / require that all attendees be invited to all
instances.
Also, this example also uses "SHOULD"
instead of "MUST". Had the RECURRENCE-ID model been one
of a changing RECURRENCE-ID value then the it would have to say "MUST"
in order to attempt to resync the invitee with the Organzier. Some
folks have seized on this Case as justification for a changing RECURRENCE-ID
model. However they have modified it in the process by changing the
"SHOULD" into a "MUST" and ignoring all of the other
sections of iTIP that contradict them.
Ok by now it should be clear that iCalendar
and iTIP specify and use a fixed RECURRENCE-ID model. So the next
thing to consider is the Working Group history on this subject and looking
at how its been implemented by folks.
As previously noted in recent discussions
the question of a fixed or changing RECURRENCE-ID model was raised at least
as far back as July 1999. The concensus then was that RECURRENCE-ID
was fixed (essentially for the reasons demonstrated above). I invite
anyone who still thinks that RECURRENCE-ID should changing on a reschedule
to go reread the archives and search for yourself.
Finally, lets take a look at how at
least the RFC authors have implemented RECURRENCE-ID in their various products.
Surely they would have implemented it the way the RFC intended it,
yes?!
If you take a look at Microsofts Outlook
98 (and higher) and Exchange you will find that all implementations (done
by different development teams) all implement a fixed RECURRENCE-ID. You
need to be configured for Internet Mode to get iCalendar support (or you
can use the Exchange server if you configure it for iCalendar). In
any case they have a fixed RECURRENCE-ID model.
If you take a look at Lotus Organizer,
Lotus Notes and the eSeries offerings you will find that all of them (also
done by different development teams) implement a fixed RECURRENCE-ID.
I do not have current access to Evolution
or to Netscapes offerings but in looking over my notes from CalConnects
I see that we did not have any interoperability issues with anyone participating
so they must have also implemented fixed RECURRENCE-IDs.
Ok, to recap this (assuming you are
still with me to here):
1: iCalendar clearly and unequivocally
says that on a reschedule RECURRENCE-ID does not change; it keeps the "original"
value. RECURRENCE-ID "might also change"
only in the case "When the definition of the
recurrence _set_ for a calendar component changes"
and not "When the definition of the recurrence
_instance_ for a calendar component changes"
2: iTIP prose specifying Message Sequencing
and messages themselves do not disagree with iCalendar.
3: iCalendar defines the RECURRENCE-ID
property; iTIP defines its semantics. As such iTIP cannot redefine
RECURRENCE-ID, that is not its job/function.
4: The changing or delta RECURRENCE-ID
model has been demonstrated as being fault intolerant and flawed in dealing
with sequencing and recovery of lost messages.
5: The WG already discussed this long
ago and confirmed that RECURRENCE-ID did not change on a reschedule.
6: ALL the implementations from all
the authors use a fixed RECURRENCE-ID. So either they ALL misunderstood
their own model or they properly implemented it based on iCalendar and
iTIP.
RECURRENCE-ID is akin to "the UID
for a particular instance" and as such it needs to have the similar
behavior as the UID property. Otherwise iTIP workflow gets lots more
complicated and verbose and so does a CUAs design.
Bruce
===========================================================================
Bruce Kahn
INet: Bruce_Kahn <at> notesdev.ibm.com
Messaging & Collaboration
Phone: 978.399.6496
IBM Software Group
FAX: and nothing but the FAX...
Standard disclaimers apply, even where prohibited by law...