2

We have a RESTful API with /devices and /buttons, whereas one device may have 0 to ca. 1000 buttons. The request GET /devices/{deviceId}/buttons implements therefore pagination (with startIndex and limit). Each button has a sortSequence property, which is a number. Buttons must be sorted based on this property (there is no relation to alphabetic name or sth else, buttons are ordered based on the wishes of the end user with drag and drop in the list).

The question is, how do you handle the modification of the sortSequence? Now we have it in the PUT /devices/{deviceId}/buttons/{buttonId} Payload: [... and new sequence]. But what about other buttons? E.g. if we have four buttons with sequences 1,2,3,4 and the user drag and drops the last button on the first position, not one change, but several take place: 4->1, 1->2, 2->3, 3->4.

Who is responsible for the ensuing changes, the client or the server?

If client, than:

  • Through one drag and drop, the client has to send possibly hundreds of REST calls to modify the sequence of all buttons in between
  • As there is paging, the client cannot create a new button without querying all of them, as it needs to know the highest sequence

If server, than:

  • A PUT to one resource (button) updates a bunch of other buttons, which I see as a violation of REST principles. Also it triggers a bunch of web socket update events for each button, which slow the UI down.
  • If create/modify/delete buttons requests are coming quickly, and sequences somewhere in the middle are modified, the server shall run into concurrency exceptions, when multiple parallel request threads will try to update the same objects possibly to different values

And of course, whoever does it, if a button is created nearly at the same time from two clients, the sequence might dublicate itself.

Both approaches seem rather bad and problematic. So is there a generally accepted best practice how to handle such modifications?

Infrastructure: .net core server, signalR, web/iOS/Android clients, ms sql db

8
  • which I see as a violation of REST principles - which principles specifically? Commented Nov 10, 2019 at 0:09
  • well, REST principles are rather shady, but I understand that it's generally accepted that one REST call SHOULD modify one resource. In other cases it should be operation on collection, if it's exposed as a resource. Commented Nov 11, 2019 at 8:10
  • You could implement a linked list of buttons (in the storage layer). But it could cause problems with pagination (depending on the type of storage). Is pagination a must? How do you implement drag-n-drop within a paginated list? What do you use for storage? Commented Nov 12, 2019 at 8:43
  • Oh didn't see that you already metnioned the stack. Anyway the other questions still stand. Commented Nov 12, 2019 at 8:54
  • Linked list is an interesting idea, which I will give some thinking. Pagination is a must, and currently not yet implemented by the UI team. I think it will be an endless scroll, as I cannot imagine drag and drop with real pages.. Commented Nov 12, 2019 at 9:09

1 Answer 1

0

Here is my practice.

I am using a relative change value to make the sequence change.

In HTTP request:

PATCH /buttons/:buttonId/sequence?deviceId=:deviceId

{ "$change": n }

n is allowed to be any integer or +/-'INFINITY'.

Be aware the query part will be your scope for ordering.

Then in server I make this field change in these cases:

  • If n is a number, update all n items' sequence in order by +/-1, and update the :buttonId item +/-n. The plus/minus is based on direction.
  • If n is +/-'INFINITY', means you want to put it to top or tail. Then get the max/min sequence in scope and plus/minus 1 will be the value you will set.

Any of these cases will do no more than 2 SQL query (exclude SELECT).

Most logic you could find in my JS code as a reference: ModelService.js of mytharcher/exprest.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.