Skip to content
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

Feedback and Thoughts #34

Closed
brixen opened this issue May 6, 2013 · 12 comments
Closed

Feedback and Thoughts #34

brixen opened this issue May 6, 2013 · 12 comments

Comments

@brixen
Copy link
Contributor

brixen commented May 6, 2013

This issue was opened by @ghempton on the defunct https://github.com/emberjs/jsonapi. I've migrated it here.


Stumbled across this document for the first time today and wanted to start a discussion around some perceived missing features of this protocol. If we are going to commit to a data transfer format that is intended to be "A generic protocol that can work across a broad set of use cases, including the generally used relationship types", I hope the following cases will be considered:

Sync Semantics and Deletion

I understand that there is a desire for this protocol to be "REST-style". In that light, the notion of passively communicating (read "sideloading") deletions and other operations feels a bit foreign, however I think it is very necessary. For a long running client-side application to function correctly, it will need to stay in sync with the server; its state cannot be purely a reflection of the RESTful actions that it has taken.

In the case of delete, depending on the backend, there can be some ambiguity as to what deleted documents should be sent to the client. Surely the client should not be aware of all models on the server. In most cases, I think that it is enough to only send down deletions that are relevant to that request: e.g. a DELETE request to a "group_member" document could potentially result in its parent "group" document being deleted in certain cases.

Taken a step further, it might be necessary for the protocol to handle the server sending down compound documents that contain "operations" in addition to related documents. This could be used to preserve intent (OT) in the case of conflicts. Maybe this could use a similar convention as PATCH?

I suppose this could just use the meta key:

"meta": {
    "deleted": {
       "comments": [ 5, 12, 17, 20 ]
    }
},

But I feel that it should have first-class support within the specification.

Non-CRUD Verbs

I feel that in any non-trivial application, it is an extremely tall order for all the business logic pertaining to a model to be handled by CRUD operators. Are there any thoughts around support non-CRUD verbs?

@brixen
Copy link
Contributor Author

brixen commented May 6, 2013

This comment was added by @wycats.


I like the side-deletion feature (we've discussed this before). Any thoughts on how this interacts with the URL ideas in the spec?

@brixen
Copy link
Contributor Author

brixen commented May 6, 2013

This response was added by @ghempton.


Not really sure. Seems like once a record is deleted, there is no corresponding URL. Will think on it more.

@reinh
Copy link
Contributor

reinh commented May 6, 2013

IRT "sync": This seems to me to be an attempt at bolting client statefulness back onto REST, which seems bad. One of the main design goals of REST was to facilitate a move away from the then-prevalent thick-client model. If we're moving back towards the thick-client model with front-end frameworks like Ember, perhaps REST is not the best abstraction to build upon?

No real suggestion here, just an observation.

@ghempton
Copy link

ghempton commented May 6, 2013

Based on the spec it seems like the goal is indeed to support a thick-client model. I think you are right that pure REST is not the best abstraction for this.

@reinh
Copy link
Contributor

reinh commented May 7, 2013

The more I think about it, the more I think this "meta" attribute breaks statelessness at a fundamental level. The only way for the server to send a meaningful "deleted" meta-payload is for the client or the server (or both) to keep track of state between requests.

If a thick/stateful client is the goal then wouldn't a streaming protocol be more appropriate?

@ghempton
Copy link

ghempton commented May 7, 2013

I don't think that it breaks statelessness at a fundamental level. The server is just telling the client what the result of a particular action–a single request–is. There is no notion of the server understanding what the client has seen in the past nor is the client subscribing to updates from a model.

For instance, if a DELETE is issued for a particular model which cascades deletes to some child relationships, isn't the server communicating to the client that the children were deleted still stateless?

@reinh
Copy link
Contributor

reinh commented May 7, 2013

@ghempton Ok, it looks like I misinterpreted the intent of "sync" based on my reading of:

For a long running client-side application to function correctly, it will need to stay in sync with the server; its state cannot be purely a reflection of the RESTful actions that it has taken.

Please disregard.

@ghempton
Copy link

ghempton commented May 7, 2013

I was just responding to the idea that the meta attribute breaks statelessness at a fundamental level. I still have concerns that the protocol is insufficient for long-running fat-client apps.

@reinh
Copy link
Contributor

reinh commented May 7, 2013

@ghempton Yep, and I was just responding to your response. Isn't discussing things on the internet fun and easy?

Sync doesn't do what I thought it did so my comment is invalid. No worries.

@lukfugl
Copy link

lukfugl commented May 7, 2013

I think the concern about "drift" in a long running client can be addressed without introducing client state on the server through use of ETags and If-None-Match/If-Match headers, treating the client's data model as a cache of the server resources. An example (off the top of my head, I'm sure there are holes):

Any time I receive a document (or update for a document) that I will interpret into my data model, I also get an ETag and store that ETag and a "last checked" timestamp alongside the data model representation of that document.

When performing a read action on the data model, if the "last checked" timestamp exceeds a client configured age, I perform an asynchronous GET request with an If-None-Match header containing the stored ETag, then update the "last checked" timestamp; this does not block the read action. If the GET returns with a 412 Precondition Failed status, the resource is unchanged and I need take no action in the data model; otherwise, I update the data model from the response (also update the accompanying ETag and "last checked" timestamp).

When writing back to the server with a POST, PUT, or DELETE, I include an If-Match header containing the stored ETag ("last checked" is irrelevant). If the operation returns with a 412 Precondition Failed status, the server should include a current representation of the resource which I can use to update the data model (and ETag and "last checked" timestamp), effectively rolling back the write.

It's not HATEOAS, but it does keep client state off the server and avoids the need for any form of "event stream" being side-loaded in unrelated requests.

@tchak
Copy link

tchak commented May 7, 2013

I have another use case. I am using a since token to refresh a collection of records on the client. In my current implementation since is juste the timestamp of the last request and on the server I return any records with updated_at after this timestamp. Sofare so good. My problem is some of my records can "expire" on the server. Or can be deleted by other clients. So I want my refresh request to include information about what records should be unloaded. The state on the server dose not seem such a big issue. In our case and in my experience it is quite a common strategy, we newer really delete records from DB. We just mark them with a deleted_at or expired_at attribute, so it is easy to find the list of recently deleted records.

@steveklabnik
Copy link
Contributor

Side deletion is covered by #18

We won't be adding any verbs to HTTP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants