Open nickevansuk opened 3 years ago
Further note on this:
C1
, C2
, P
and B
endpoints, and the Orders Feed of the booking spec all require opportunities to be referenced using a pair of @type
and @id
. Hence if an Event
was reclassified, the Orders Feed would also need to be updated with the new @type
.The reason for reflecting the structure of C1
, C2
, P
and B
endpoints for @id
references simplifies use of the model for both requests and responses, e.g:
"orderedItem": [
{
"@type": "OrderItem",
"acceptedOffer": {
"@type": "Offer",
"@id": "https://example.com/events/452#/offers/878"
},
"orderedItem": {
"@type": "ScheduledSession",
"@id": "https://example.com/events/452/subEvents/132"
}
}
]
This is in contrast with the referencing approach used in feeds, which uses the @id
as a direct reference e.g. for superEvent
below:
"data": {
"@context": "https://openactive.io/",
"@type": "ScheduledSession",
"@id": "https://id.ourparks.org.uk/api/session-series/1234#/subEvent/C5EE1E55-2DE6-44F7-A865-42F268A82C63",
"superEvent": "https://id.ourparks.org.uk/api/session-series/1234",
...
}
A move towards internal consistency would be to use the following in the Orders feed (and also potentially in C1, C2, B, P etc too):
"orderedItem": [
{
"@type": "OrderItem",
"acceptedOffer": "https://example.com/events/452#/offers/878",
"orderedItem": "https://example.com/events/452/subEvents/132"
}
]
A move towards external consistency would be to use the following in all feeds and APIs (as per this example):
"orderedItem": [
{
"@type": "OrderItem",
"acceptedOffer": { "@id": "https://example.com/events/452#/offers/878" },
"orderedItem": { "@id": "https://example.com/events/452/subEvents/132" }
}
]
Both of the above approaches are valid JSON-LD (https://www.w3.org/TR/json-ld/#advanced-concepts), however the latter does not require changes to the @context
to support it in different scenarios (though the changes to @context
would be trivial to make, and are already set on several OpenActive terms) (N.B. this is not a comment on the validity of changing the @type
)
Although @type
in the Orders Feed can help data consumers to match the @id
to the relevant feed, a data consumer will want to compare all received @id
to their stored Orders rather than the other way around, which means this is unlikely to be used for this purpose.
Given that @type
is optional in JSON-LD, can be an array, and in some cases can be inferred (https://www.w3.org/TR/json-ld/#specifying-the-type), it seems that reassigning the @type
is not an issue here?
An issue with using the same @id
namespace across multiple feeds is that RPDE is not designed to resolve conflicts between feeds - the modified
timestamp is only local to the feed (and globalising the scope of modified
creates sync issues for data users consuming multiple parallel feeds, as well as breaking the RPDE transport-level abstraction). Therefore each feed requires a unique @id
namespace to ensure that the latest data is discernible to the data user.
Another option here is to simply use the Replacement within the Orders feed when a booked event changes type. This would mean that the @type
and @id
could then be easily updated when an Event
is recategorised. This would trigger a notification to the user by default, however.
Reviewing this thread, it doesn't appear to me that there are any good options for changing @type
unobtrusively.
The chief difficulty is that at the very least we're forcing data consumers to consume all feeds, on the off-chance that one of the items they've harvested has changed @type
and henceforth jumped feeds.
It would be possible to get around this to some degree by ensuring all changes are listed in the Orders feed, but problems of modelling arise: if the change from e.g. Event
to CourseInstance
includes the addition of Course-specific data, consumers developed to process Events
will not be able to parse the relevant data. This points to a larger problem of differentiating between cases where the change in @type
is trivial (and hence shouldn't trigger operations knock-ons such as automated emails, cancellations, etc.) and where it's significant (and therefore should).
On reflection, the guidance should simply be that changes in @type
result in:
@type
This implies that all @type
changes will be significant: bookings will be cancelled in the event of a @type
change and so forth. Given the difficulty of automatically determining which changes should be considered significant and which not, however, this is preferable to the alternative of treating all changes as insignificant.
Interfaces that allow users to change @type
easily, however, should probably add guidance or e.g. modal dialogue boxes warning users of the possible consequences of @type
changes.
Further alternative solutions are considered below:
Issues:
Advantages:
Issues:
Advantages:
Issues:
SessionSeries
and Event
, sharing the @id
between typesWould still require separate RPDE items and deletion for the different types within the same feed unless @ids could be reused between types in the same feed
Advantages:
Issues:
Advantages:
Issues:
@id
and change the @type
, and unify feeds around parents/child: so one feed of Event+ScheduledSession, another for CourseInstance+SessionSeriesAllow types to change within the same feed, just as updates. This lessens the importance of the “type” attribute for how it is when storing data.
Could prioritise the latest @id
based on the “modified” timestamp for conflict resolution, which means it doesn’t matter which feed it comes from (though processing “delete” across feeds is difficult - if one feed deletes it and it appears in the other, what then? RPDE doesn’t currently support cross-feed deletes)
Issues:
Advantages:
Issues
Simple implementation:
remainingAttendeeCapacity
or remainingUses
? Almost certainlyAdvantages:
@type
s, which is perhaps less of a tall order? Perhaps this should be feature flagged?)Issues:
Potential Solution 7 and Potential Solution 8 have the least number of issues and complexity.
Hence, if both were supported, the tradeoff for the booking system is between:
Background
The types of opportunities in OpenActive have a specific semantic meaning:
SessionSeries
andScheduledSession
: This is an event (usually 1 or 2 hours in duration), that happens with some regularity. It is expected that if a user attends one of these events, that they would find another event in the series happening soon afterwards. [ref]Event
: These events are one-off occurrences, e.g. a fun run organised by a local group may run as a standalone event on a particular date or an organisation that runs many individual events e.g. Human Race, Race for Life, International Women's Day. [ref]CourseInstance
: Courses generally involve an upfront commitment to a number of sessions, with a consistent attendee group and/or organisers for the duration of the course. [ref]Within booking systems, the difference between an
Event
and aScheduledSession
is usually as subtle as whether theEvent
is part of a recurrence rule - often the user can tick a box to say "repeat every Tuesday" as they can in Google Calendar, and anEvent
then becomes aScheduledSession
.The current guidance for this scenario is for the booking system to remove the
Event
from theirEvent
s feed, and add it into theirSessionSeries
/ScheduledSession
s feed.According to Bookwhen this is not an uncommon occurrence, e.g. an organiser scheduling the first
Event
, and then deciding to add a recurrence to it afterwards for it to become part of aSessionSeries
. Potentially bookings have already been made against theEvent
when this happens.Challenges
Within the booking system an
Event
and aSessionSeries
/ScheduledSession
are usually represented by the same underlying structure. Forcing the same underlying structure to output two feeds can create extra work for the booking system, and also is in opposition to one of the principles of RPDE (which exists for the same reason):When an
Event
becomes aScheduledSession
and visa versa, the current guidance implies that the item be marked asdeleted
in its current feed, and a new item (with a new@id
) be added to a new feed. When the Open Booking API is implemented, changing the@id
of an item will break Change of Logistics Notifications (openactive/open-booking-api#138) (e.g. if anEvent
becomes aScheduledSession
then itslocation
is updated).Potential solutions
If we want to retain the semantics of
Event
and its subclasses, given that it is possible for systems to switch between the types after bookings have been made, one potential solution is to allow an opportunity to have its@type
changed, while maintaining its@id
.The feed split could then be:
SessionSeries
ScheduledSession
+Event
(where this feed contains both types, with the same@id
namespace used for both)When an
Event
becomes aScheduledSession
in the second feed, it is then linked to the schedule it is now part of (SessionSeries
). When aScheduledSession
becomes anEvent
in the second feed, it is effectively unlinked from the schedule, as it is a one-off session.(N.B in the case of Bookwhen this doesn’t actually help as their Events feed and ScheduledSession feed are driven from two different underlying database tables)
Further investigation is required to determine whether having a JSON-LD object change
@type
while maintaining its@id
is (a) allowable and (b) best practice