ical-org / ical.net

ical.NET - an open source iCal library for .NET
Other
789 stars 231 forks source link

What is the correct Logic to obtain unique Id of recurring meeting instances #90

Closed kb99 closed 8 years ago

kb99 commented 8 years ago

I am implementing logic that will allow a user to upload ICS files and import a number of meetings/events into a DB.

For single instance meetings, I can just use the Uid to check if we already have the meeting.

For recurring meetings though, I'd like to clarify what logic I should use to correctly get a unique Id for each instance of the recurring meeting series.

Are the following statements correct?

If the RecurrenceRules collection contains any items then the event is a recurring meeting instance and I should use the StartTime field from the occurrence Period as a unique identifier for that instance. The Start field from the event itself contains the start date of the recurring series and not of the individual instance.

If the RecurrenceID field is populated then this should be used as the unique identifier for the instance. My understanding is that this field will only be populated for exceptions to the recurring meeting series and will contain updated information for a single instance of a recurring meeting series. The Sequence field indicates that there can be multiple updates to a instance of a recurring meeting. The highest sequence number should contain the most recent changes to the instance.

Is there any wrapper method available that has already implemented logic to determine the recurring event ID and I can use that instead of having to implement my own logic?

rianjs commented 8 years ago

(Pardon me for the delayed response. I was on a long holiday out of the country, and was quite ill when I returned, so I'm digging out.)

If the RecurrenceRules collection contains any items then the event is a recurring meeting instance

Most of the time, but AFAIK this isn't guaranteed by the spec, and even if the spec was explicit about this, you'd still have do the recurrence computation just to be safe. If an RRULE is missing, yes, there's only one occurrence, but the other way isn't guaranteed to be true. Until recently, evaluating recurrence rules was slow, but it should be fairly quick now, so you should feel comfortable seeing if GetOccurrences returns anything if the RecurrenceRule collection isn't empty.

and I should use the Start field as a unique identifier for that instance

That's what the spec says, yes. Reading it more closely would indicate that there's arguably a bug here. More specifically, each element in the recurrence set contains two properties: a Period and Source. Source is a pointer back to the original Event that the occurrence is associated with, so that's some shared state across the entire collection, which means you can't meaningfully change the RecurrenceID value without doing a deep copy first. The recurrence instance should have the RecurrenceID on it, and could just be implemented as an expression body: RecurrenceID => Period.StartTime. So that's a bug in the data model. Annoying.[1]

Pulling apart type dependencies has been slow going. Unfortunately in dday, all the types pretty much depend on all the other types, so fixing issues in the data model is difficult.

If the RecurrenceID field is populated then this should be used as the unique identifier for the instance.

If the bug we discovered just above weren't true... yes. Speaking for myself, I don't really like the spec, here. I think Google Calendar has a better API in this regard. GCal provides a UUID for the event that has the recurrence rules, and it also allows you to materialize the collection those recurrences, each of which also has their own UUID. This strikes me as being a better way to model the problem space than what the spec says. (DateTimes as identifiers seems crazy to me.)

My understanding is that this field will only be populated for exceptions to the recurring meeting series and will contain updated information for a single instance of a recurring meeting series.

Nothing in the ical.net changes the value of this property. I would recommend you avoid using it, for the reasons outlined above.

The Sequence field indicates that there can be multiple updates to a instance of a recurring meeting. The highest sequence number should contain the most recent changes to the instance.

Incrementing the SEQUENCE value indicates that the event, journal, etc. was changed, yes. Nothing in the ical.net library changes the value of this property, which makes sense, as it's a client-side idea anyway.

Is there any wrapper method available that has already implemented logic to determine the recurring event ID and I can use that instead of having to implement my own logic?

Honestly, I would step outside the spec here and ical.net's shortcomings and do what makes sense for your domain and needs. If materializing a projection of recurrences into fully-formed Event objects, each with their own Uid makes sense, do that. If that's not necessary, don't.

Since these are ics files generated from some other application, I think I would (reading between the lines), go with an append-only database design:

If you need fast queries on attendees or resources, create those association tables.

Select the EventId with the highest EventRevisionNbr and the ical string, and then do the computations to answer the question the client is asking in the application layer. At that point, all your CRUD operations become INSERTs.

[1] If my commentary seems weird to you, read history.md at the root of the repo.

kb99 commented 8 years ago

thanks for the detailed response. Its been very helpful.