1

This question mainly relates to HOW to do this using the CRNK framework however I have also tagged it as JSON-API as I am interested in whether or not the approach is generally correct within the confines of JSON-API spec.

I don't want to complicate things by going into specifics of the exact domain the problem relates to, so I am going to simplify things a little.

I have a queue, which has various attributes such as name, description etc. Another attribute of the queue is some historical timestamped data, essentially an array of objects that look something like:

{ "time": "21/10/2018 10:15 GMT", "value": 35 }

In fact the queue can have a number of these attributes that relate to different data for that queue. The amount of data in the array can be quite big depending on how much data has been collected.

My first instinct was to model this an attribute on the queue:

{
  data: {
    ...
    attributes: {
      ...
      history: [
        { "time": "21/10/2018 10:15 GMT", "value": 35 },
        { "time": "21/10/2018 10:30 GMT", "value": 35 },
        { "time": "21/10/2018 10:45 GMT", "value": 35 }
      ]
    }
  }
}

The issue I have with this approach however is that the entire data set is going to come back with the queue (which could be quite large and not always required). I could combat this issue by using sparse fieldsets, but I don't particularly like this concept of requesting the queue over and over again with a different fields parameter in order to get the data I am after in a particular scenario.

What I wanted to do was to model this history data as a relationship, that way the data can be accessed through a relationship URL, e.g. /api/queues/1/history This seems to make most sense to me as the intended use of the API is various screens would make use of the different sets of data attached to a queue, so each screen would have the queue object and can then request the data it is interested in through these relationship links.

The issue I am having however is that the history data here doesn't exist as an identifiable resource in the backend, only as a sub-resource of the queues (i.e. select * from historydata where queueid = 1). This is where I am unsure how to implement it in CRNK. It seems as though to model a relationship I have to also create a ResourceRepository for the sub-resource (/api/history/{id}). But I don't want this.

So my question around the CRNK implementation is how do I configure my resources and repositories such that:

GET /api/history/{id} - always returns 404 (ideally without having to implement this myself in a HistoryResourceRepository)
GET/PATCH /api/queues/1/history - will go through the queue repository to access and update the history data using the queue ID as the identifier

Also, on a side note, what is the recommended approach for assigning an ID to the sub-resource, given it doesn't exist as an identifiable entity in that respect and the ID is largely irrelevant?

DaveJohnston
  • 10,031
  • 10
  • 54
  • 83

1 Answers1

1

the way repositories are implemented aligns strongly with what the JSON API specification writes about how to work with relationships (see http://jsonapi.org/format/#crud-updating-relationships). Meaning each history item must be resource and can be set into relation with, for example, those queue items. As such a resource and relationship repository must be implemented. Relationship repositories really only establish connections and can by themselve not work with data. So only the resource repositories are able to do insert, update and deletes of data.

However, in this particular use case (history), GET access with a relationship repository would be sufficient. It would not be overly hard to make the resource repository optional (or at least hide it from the rest api/crnk-home). But it may go slightly against the JSON API specification.

Another thing that can be done, should you have multiple history records, is to make use of nested urls like "history/queue", "history/xy", to establish a clean API and have all history-related resources at one place / sub-directory. Personally I do that in applications.

Remo Meier
  • 141
  • 2
  • Rather than using the relationship repository to do any of the inserts/updates/deletes of the data, what I was proposing was that updating the history data would be done through the queue repository, i.e. PATCH /queues/1/history would be used to make changes to the history data and the code would live in QueueRepository since we are using the queue ID to reference the history data. – DaveJohnston Mar 29 '18 at 18:24
  • If I were to go down this route of making the history data a relationship and had to implement a repository for it, how would I go about defining an ID for the data given that the data is only referenced through the queue ID? – DaveJohnston Mar 29 '18 at 18:28
  • yes, definitely, history items don't need POST/PATCH/DELETE. – Remo Meier Mar 31 '18 at 11:41
  • maybe the time would be sufficient if a single queue item does not get changed twice at the same moment. – Remo Meier Mar 31 '18 at 11:43