1

In my application I have the concept of a Draw, and that Draw has to always be contained within an Order.

A Draw has a set of attributes: background_color, font_size, ...

Quoting the famous REST thesis:

Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on.

So, my collection of other resources here would be an Order. An Order is a set of Draws (usually more than thousands). I want to let the User create an Order with several Draws, and here is my first approach:

{
    "order": {
      "background_color" : "rgb(255,255,255)", "font_size" : 10,
      "draws_attributes": [{
            "background_color" : "rgb(0,0,0)", "font_size" : 14
        }, {
           "other_attribute" : "value",
        },
       ]
       }
}

A response to this would look like this:

"order": {
          "id" : 30,
          "draws": [{
                "id" : 4
            }, {
               "id" : 5
            },
           ]
           }
    }

So the User would know which resources have been created in the DB. However, when there are many draws in the request, since all those draws are inserted in the DB, the response takes a while. Imagine doing 10.000 inserts if an Order has 10.000 draws.

Since I need to give the User the ID of the draws that were just created (by the way, created but not finished, because when the Order is processed we actually build the Draw with some image manipulation libraries), so they can fetch them later, I fail to see how to deal with this in a RESTful way, avoiding to make the HTTP request take a lot time, but at the same time giving the User some kind of Ids for the draws, so they can fetch them later.

How do you deal with this kind of situations?

Hommer Smith
  • 26,772
  • 56
  • 167
  • 296

2 Answers2

0

Accept the request wholesale, queue the processing, return a status URL that represents the state of the request. When the request is finished processing, present a url that represents the results of the request. Then, poll.

POST /submitOrder

301
Location: http://host.com/orderstatus/1234

GET /orderstatus/1234

200
{ status:"PROCESSING", msg: "Request still processing"}

...

GET /orderstaus/1234

200
{ status:"COMPLETED", msg: "Request completed", rel="http://host.com/orderresults/3456" }

Addenda:

Well, there's a few options.

1) They can wait for the result to process and get the IDs when it's done, just like now. The difference with what I suggested is that the state of the network connection is not tied to the success or failure of the transaction.

2) You can pre-assign the order ids before hitting the database, and return those to the caller. But be aware that those resources do not exist yet (and they won't until the processing is completed).

3) Speed up your system to where the timeout is simply not an issue.

Will Hartung
  • 115,893
  • 19
  • 128
  • 203
  • Thanks for the answer. However, how would the User know which Draw is each in the Order if they don't get an Id right when they do the request? Now, I give them an Id saying, the first Draw you submitted have this ID, the second one has this other ID. I mean, imagine that by some reason one of the Draws could not be processed, they could not do the mapping sequentially to find out which one is which, right? – Hommer Smith Jul 09 '14 at 18:57
  • @Nobita: You could use a sequence in your database, you could use a guid, there are several mechanisms for this outside of the database. Regarding the enqueuing, yea, you could just shove the entire document on to the queue, and then let the job figure it all out on its time. – Will Hartung Jul 09 '14 at 23:06
  • I am not sure I understand what do you mean by a 'sequence in the database' or a guid. An Order POST request comes with N draws. If I want to give the User some kind of UNIQUE id for the Order and all the Draws, without having to hit the DB, so that later they can actually use that ID to fetch any of those resources, how do you do that? I guess that first of all it would be necessary to see how many Draws are in the passed JSON, so you know how many IDs you have to give back, but what concerns me the most is: How do I know which Ids should I give back? – Hommer Smith Jul 09 '14 at 23:47
  • a solution that I see is letting them pass an ID for each of the Draw, so when I actually create the Draws and give them back to the User, they can map them. What do you think? – Hommer Smith Jul 10 '14 at 16:42
  • @HommerSmith: There are several mechanisms that can be use to create identifiers that do not load the database. For example, you can have a simple service that returns IDs, but only updates the database once every 100 requests. Some GUID algorithms are simply very large random numbers, where they just hope they will not get a collision. (i.e. collision is possible, just very, very unlikely). Others use a combination of current time, and local identifiers (like the machine ID, or a MAC address). There are several schemes to generate IDs that have little DB impact. – Will Hartung Jul 10 '14 at 17:38
  • Will Hartung, thanks a lot for taking the time to comment. My concern is: If I create the UUIDs before even creating the records, and then I give those UUIDs back to the user, that would mean I actually need to go one by one Draw within an Order, and create a UUID, so I can pass them in order to the process that will actually create the record in the DB. Right? – Hommer Smith Jul 10 '14 at 17:44
0

I think your exposed granularity is too fine - does the user need to be able to modify each Draw separately? If not, then present a document that represents an Order, and that contains naturally the Draws.

Will you need to query specific Draws from the database based on specific criteria that are unrelated to the Order? If not, then represent all the Draws as a single blob that is part of a row that represents the Order.

Tassos Bassoukos
  • 16,017
  • 2
  • 36
  • 40
  • Tassos, the user MUST be able to GET a specific Draw within an Order. If when he creates the Order with the nested Draws, I don't give him back the Ids of the draws, how is he going to be able to GET a specific draw? – Hommer Smith Jul 09 '14 at 22:53