-
Notifications
You must be signed in to change notification settings - Fork 830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for parallel relationships #1361
Comments
Great write-up, thanks @gabesullice! I think the third and fourth bullet (both talking about ordering) could be clarified: the third says One thing that hasn't been mentioned yet: @FlorentTorregrosa opened #1156 about this ~1.5 year ago. We implemented the recommendation that @beauby made at #1156 (comment). |
I'm struggling to think of a way to clarify if, maybe you can help? In the third bullet, what I'm trying to say is that In the fourth bullet, I'm trying to indicate that |
I updated the example, perhaps that's enough? |
Just stumbled upon #1332, which is definitely related. See |
I think the fourth bullet conflicts with
That explicitly says that the order may be meaningful to the server, but it's up to the server implementation. Third bullet: clarify the order aspect in relation to elsewhere in the spec
Fourth bullet: do we really need it?Why does the arity, if present, need to be monotonically increasing with parsing order of resource identifier objects? Does this truly make a meaningful difference to the client? Why? In other words: Why even have the fourth bullet? |
@wimleers, I think you're misinterpreting bullets 3 and 4. Did you see my comment about them?(#1361 (comment)). It's also possible I don't understand what you're trying to point out. |
I do not see the connection. |
Something similar has been considered a few times. The tricky part with proposals like this is always: how do you update the attributes associated with each resource identifier object (i.e., the data that you put in This question inevitably comes up because the whole point of allowing the same resource identifier object to appear multiple times is to associate different metadata with each occurrence; if you only cared about representing the number of times that a given resource is included in a relationship, you would actually just include the target resource's So, again, any proposal like this needs some way to update the attributes associated with each resource identifier object. And, to do that, clients need to have some way to identify the identifier object they want to target for an update. In your proposal, iiuc, the client does that by sending the arity value with a Sure, you could use some form of optimistic concurrency control to prevent this, but that probably shouldn't be a requirement; instead, a good design would probably allow the server to assign a stable id to each identifier object. And then another question comes up: what if you want one of the pieces of data associated with your identifier object to actually be a pointer to another JSON:API resource? E.g., in your team members example, what if there are At this point, I personally start to think "Gee, these identifier objects are becoming a lot like standard resource objects". I'm gonna write a longer comment about this soon, but a key thing I've been thinking about is "What should have identity in JSON:API?" Key point from that link:
Once we start talking about having mutable attributes on resource identifier objects, at a fundamental level, we're talking about turning resource identifier objects from values into identities. Personally, I think JSON:API already has way to many distinct concepts -- look at the mess around links vs. relationships -- so I'm loathe to add another one when a similar one already seems to exist. In this case, I think that's resource objects, which already are JSON:API's key identities (they're named by their ~~ You say that modeling these as standard resource objects is challenging technically or raises performance issues, but I don't really understand that part. Can you explain it to me? If you already have a facility to store and update the metadata, it would seem that whether these show up as identifier objects or as distinct resources is more a question of serialization logic than data storage or anything else. I.e., I'm imagining you have a table like:
Can't that just as easily become: {
"type": "team-members"
"id": team_members.id,
"attributes": {
"role": team_members.role,
"from": team_members.start_date,
"until": team_members.end_date
},
"relationships": {
"team": {
data: { "type": "user", "id": team_members.team_id }
},
"member": {
"data": { "type": "user", "id": team_members.member_id }
}
}
} Maybe the tricky part here is now for the client, which needs to add an extra What I do think would be very useful is a profile that standardizes this pattern of "lifting up" identifier objects into full resource objects to attach attributes to them. So, for example, the profile might say that these resource objects should always use the same type value (or have a specific key in meta) and should always have at least two relationships — e.g. |
Thanks for the detailed reply! I'm only able to respond to it in part ATM.
Partially correct. For
This is true, but partially mitigated by the fact that in this proposal each set of parallel relationships have their own series of arities. IOW, if Client A deletes a resource identifier that is not parallel to the relationship that Client B is updating, there would be no cross-effect. What you say is true if the relationships are parallel though and I admit this falls down without either a stable identifier or It seems concurrency control is a recurring impediment (I've seen it mentioned in a couple issues now). The obvious answer seems to be to recommend the use of the UPDATE: Looks like there was a lot of discussion about |
The request to support attributes for relationships has come up multiple times. Often Parallel relationships seems to be a special case of this. I haven't seen an use case yet for parallel relationships without having additional attributes for each relationship. Going forward, I assume that parallel relationships are only needed if having attributes on the relationship. Please speak up if you have an use case for parallel relationships, whoch does not require having attributes on the relationship. @ethanresnick well summarized the challenges if supporting attributes pee relationship. And described the alternative approach to use an intermediate resource instead. I agree with that. I would tend towards explicitly forbidding parallel relationships to be honest. One could argue that doing so would be a clarification. And not a breaking change. Processing rules for @dgeb Would be great to hear your opinions. |
I think we need to tread very carefully here. The spec's constraints regarding resource identity ( In general, I agree with the impression that @ethanresnick expresses above:
I also have concerns about the stability of the
So I am definitely not in favor of supporting a new field such as
@jelhan I agree in spirit with this because, in my experience, parallel relationships were not explicitly considered to be valid at the time of writing the original spec. However, at this point we may only have the option to restrict their usage (SHOULD NOT) rather than explicitly prevent it (MUST NOT). This feels more fair to those who have found edge cases that use these relationships and for those who want to explore an extension. I am also curious to hear from others in the community, especially since this topic was raised a few years back. |
Hey! Received a few notifications for this. +1 to not adding my original proposal to the spec and +1 to the @dgeb's hesitance to forbidding parallel relationships at this point with "must not". I still struggle with the idea of recommending that they be modeled as separate resources. I'll provide a bit more context from the Drupal-perspective: Drupal has a concept of "fieldable entities" (models with attributes that can be added/removed at runtime). It also has a concept of file entities. File entities store metadata about files Drupal knows about such as: the owner, a description, label, etc. Finally, Drupal has an image field (that can be added to the aforementioned fieldable entities). Image fields store a file ID and alt text for the referenced image. They can also have more than one value (e.g. for multiple images on a product). It is possible to reference the same image file entity twice, with different alt text. And that's where the snag lies: Should Drupal's JSON:API implementation have entirely separate resources for the relationship between a product and its photos? Honestly, in retrospect, maybe it would have been worth implementing them as resources. In practice, I've never encountered a bug report about concurrent update problems with the I think a recommendation (using RECOMMENDED) with a note explaining the pitfalls may be the best outcome here. It may have pushed us in a better direction. Finally, I agree with @dgeb that an extension is the right approach for mutable, parallel relationships. |
Thanks so much for weighing in here, @gabesullice! This use case is quite interesting.
Yeah, I probably would have chosen to model these as separate resources, especially if It occurs to me that another way to think about |
Thanks a lot @gabesullice and @dgeb for sharing your thoughts. I think we have an agreement. I will try creating a PR implementing it the next days. |
The spec is silent about parallel relationships (that is, more than one resource identifier object with the same
type
andid
combo) in all but one case:I think it would be useful for this spec to provide explicit support for parallel relationships. This would mean relaxing the above statement and then clarifying their treatment and serialization.
Let's think about a real-world example:
type
:organization
members
.type
:user
user
who is both a "founder" of the organization and the "treasurer" & these roles have start and end dates.A request to
/organizations/1/relationships/members
should return:Obviously, one could model these memberships as standalone resource objects, however this can pose a significant technical challenge on systems which do not natively model relationships this way (my scenario). Moreover, in a traditional relational database, modeling relationships in that way can lead to application performance issues due to an increase in the average number of
JOIN
s required for its typical queries.We currently work around this shortcoming by adding a new member to the
meta
object of resource objects that we callarity
:We use this member to help a client disambiguate parallel relationships, to identify the relationship to delete on relationship
DELETE
requests and to provide a stable mechanism to add a parallel relationship viaPOST
(this is the part that's in conflict with the spec).I found this issue while attempting to author a profile for this mechanism, but realized it was in conflict with the spec. This made me think that it might actually be more valuable to add support for parallel relationships in the base spec and not in a profile since it's so closely related to core functionality.
So, what's my proposal?
Add an
arity
member to a resource identifier object with the following language:This is proposal is exactly what we have been doing successfully in our own implementation (except we put
arity
under themeta
member). In doing so, we've worked all the gritty details out for complete CRUD support too. More information here: https://www.drupal.org/node/2992674The text was updated successfully, but these errors were encountered: