Message queue: request-response architecture - rabbitmq

I am just learning MQs so in this question I need help with understanding how conversation between two servers is happening. I have following architecture:
Interaction example:
I am sending '{"operation": "get", "key": key}' to Request
chanell or '{"operation": "set", "key": key, "value": value}'
form Gateway Serverhttps://i.stack.imgur.com/zCAUr.png
Expecting Cache Server answering with value and success flag
Questions:
Is it Robust architecture?
Do I use MQ correctly?
Should I add req_id: parameter to message body in order to find response?
What about performance?

Related

Altering the max priority on an existing RabbitMQ queue using the management REST API

Using the REST API I'm trying to update the priority of an existing queue like so:
PUT /api/queues/%2F/TestEvent_ProcessingService HTTP/1.1
Host: localhost:15672
Authorization: Basic <--snip-->
cache-control: no-cache
{
"durable":true,
"arguments":{
"x-max-priority":2
},
}
The response is:
{
"error": "bad_request",
"reason": "inequivalent arg 'x-max-priority' for queue 'TestEvent_ProcessingService' in vhost '/': received the value '2' of type 'long' but current is none"
}
Is there any way to set this value on an existing queue, or do you need to delete the queue and recreate it with a new "x-max-priority" value?
The answer is in RabbitMQ's documentation:
https://www.rabbitmq.com/priority.html
do you need to delete the queue and recreate it with a new
"x-max-priority" value?
Yes.
(cross-posted question here).
NOTE: the RabbitMQ team monitors the rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.

Wit AI response for API requests

I'm using wit ai for a bot and I think it's amazing. However, I must provide the customer with screens in my web app to train and manage the app. And here I found a big problem (or maybe I'm just lost). The documentation of the REST API is not enough to design a client that acts like the wit console (not even close). it's like a tutorial of what endpoints you can hit and an overview of the parameters, but no clean explanation of the structure of the response.
For example, there is no endpoint to get the insights edge. Also and most importantly, no clear documentation about the response structure when hitting the message endpoints (i.e. the structure the returned entities: are they prebuilt or not, and if they are, is the value a string or an object or array, and what the object might contain [e.g. datetime]). Also the problem of the deprecated guide and the new guide (the new guide should be done and complete by now). I'm building parts of the code based on my testing. Sometimes when I test something new (like adding a range in the datetime entity instead of just a value), I get an error when I try to set the values to the user since I haven't parsed the response right, and the new info I get makes me modify the DB structure at my end sometimes.
So, the bottom line, is there a complete reference that I can implement a complete client in my web app (my web app is in Java by the way and I couldn't find a client library that handles the latest version of the API)? Again, the tool is AWESOME but the documentation is not enough, or maybe I'm missing something.
The document is not enough of course but I think its pretty straightforward. And from what I read there is response structure under "Return the meaning of a sentence".
It's response in JSON format. So you need to decode the response first.
Example Request:
$ curl -XGET 'https://api.wit.ai/message?v=20170307&q=how%20many%20people%20between%20Tuesday%20and%20Friday' \
-H 'Authorization: Bearer $TOKEN'
Example Response:
{
"msg_id": "387b8515-0c1d-42a9-aa80-e68b66b66c27",
"_text": "how many people between Tuesday and Friday",
"entities": {
"metric": [ {
"metadata": "{'code': 324}",
"value": "metric_visitor",
"confidence": 0.9231
} ],
"datetime": [ {
"value": {
"from": "2014-07-01T00:00:00.000-07:00",
"to": "2014-07-02T00:00:00.000-07:00"
},
"confidence": 1
}, {
"value": {
"from": "2014-07-04T00:00:00.000-07:00",
"to": "2014-07-05T00:00:00.000-07:00"
},
"confidence": 1
} ]
}
}
You can read more about response structure under Return the meaning of a sentence

Best practice to batch update a collection in a REST Api call [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Hi I'm looking for best practices with API design to batch update a collection with an API call.
My collection has URL /api/v1/cars and I would like to update all the cars in the collection to add a timestamp of the current time.
{
data: [
{
manufacturer: 'Porsche',
timestamp: ...
},
{
manufacturer: 'BMW',
timestamp: ...
}
{
manufacturer: 'Peugeot',
timestamp: ...
}
}
I thought about a few options but I can't figure what is the best practice.
Should it be:
1/ Modelled as another resource such as POST api/v1/cars/updateTimestamp
2/ Passed as a query parameter: PUT api/v1/cars?updateTimestamp
3/ Pass in the body of the request:
POST api/v1/cars
{"operation":"Update timestamps"}
I'd like to emphasize that the whole processing should be done on the back-end and not passed by the client.
Same problem would happen for any complex processing that happens on the back end..
How could I keep the API RESTy in this case.
Thanks a lot for your help/any pointer to relevant ressources.
As there is no partial PUT defined in HTTP, you either need to send the whole entity for each resource to update or use some other operations.
POST
As POST is an all-purpose operation you can use it to create a short-living temporary resource at the server (which further does not even have to have an own URL). On receipt the server can update either all specified entries or all entries in general with some provided field-value combination (certain table alterering may be necessary though if the column is not yet know in relational databases)
A simple request may look like this:
POST /api/v1/cars/addAttributes HTTP/1.1
Host: example.org
Content-Length: 24
Content-Type: application/json
If-Match: "abc123"
{
"timestamp": "..."
}
This approach has the advantage that it could be sent to the server anytime, even without prior knowledge of the current state. This, however, also has the danger that certain entries get updated which shouldn't be affected. This can either be influenced by specifying an If-Match header, which points to a certain version-hash and is changed on every entity update, or by adding a certain restrictor to the JSON body which the server also has to understand.
PATCH
Similar to POST, which can literally send anything to the server, PATCH is intended for modification of resources. A single request explicitely may update multiple resources at once, however, the client needs to define the necessary steps to transform the resources from state A to state B. Therefore, the client also needs to have the latest state of the resource in order to successfully transform the resource to its newest state (-> ETag and If-Modified HTTP headers)
A JSON Patch request for the provided example may therefore look like this:
PATCH /api/v1/cars HTTP/1.1
Host: example.org
Content-Length: 215
Content-Type: application/json-patch+json
If-Match: "abc123"
[
{ "op": "add", "path": "/data/1", "value": [ "timestamp", "..." ] },
{ "op": "add", "path": "/data/2", "value": [ "timestamp", "..." ] },
{ "op": "add", "path": "/data/3", "value": [ "timestamp", "..." ] }
]
Where /data/1, /data/2 and /data/3 are the unique identifiers for the resources of Porsche, BMW and Peugeot.
PATCH specifies that a request has to be atomic which means that either all or none of the instructions succeed which also brings some transaction requirements to the table.
Discussion
As already mentioned, in POST requests you can literally send anything you want to the server at least as long as the server is capable of understanding what you are sending. It is therefore up to you how you design the request structure (and the server logic as well).
PATCH on the other hand, especially with JSON Patch defines some strict rules and predefined operations typically to traditional patching. The transaction requirement can be a burden but also a benefit. In addition to that, PATCH is not yet final and still in RFC though it is already widely available.
I would do a PUT to do an update operation. PUT is for updating objects, POST for creating. You could specify fields using query parameters.
POST /api/v1/cars > create new cars
PUT /api/v1/cars > update car based on id in the object. You could
also create a cars/:id route if you want to use the route without an
id to do an update on all car objects (which seems not to happen in
many applications).
GET /api/v1/cars > list all cars
GET /api/v1/cars/:id > list one car.
To answer your question. You want to update all car objects. In that case I would use the PUT /api/v1/cars and specify a /api/v1/cars/:id to do an update on one car, although I do not see why you want to implement this. If it is a one time operation, I would update all cars in the DB instead of creating an API route.

Can't create replies to some existing youtube comments

I have a software, which allows you to create a reply to a comment on your youtube video. Therefore I use the youtube API v3 comments.insert method.
POST https://www.googleapis.com/youtube/v3/comments?part=id%2Csnippet&access_token=[access_token]
{
"snippet": {
"parentId": "parentId",
"textOriginal": "test message"
}
}
Most of the time the requests are successful. But for some comments I can't create replies this way. The API always returns:
{
"error": {
"errors": [
{
"domain": "youtube.comment",
"reason": "processingFailure",
"message": "The API server failed to successfully process the request. While this can be a transient error, it usually indicates that the requests input is invalid. Check the structure of the <code>comment</code> resource in the request body to ensure that it is valid.",
"locationType": "other",
"location": "body"
}
],
"code": 400,
"message": "The API server failed to successfully process the request. While this can be a transient error, it usually indicates that the requests input is invalid. Check the structure of the <code>comment</code> resource in the request body to ensure that it is valid."
}
}
I'm using a valid access token and the parentId is valid, too, because I can retrieve it through the API.
I took a look at the successful and failing requests, but didn't find any difference. So I assume that the request input isn't invalid as it is mentioned in the error message.
In my opinion this error isn't a transient error, because the same requests are still failing after some days.
I also tried to create a reply on such a comment through the API Explorer but the result was the same.
Does anyone have the same problems or am I doing something wrong?
When I go to the video and look at the comments directly, the comment with ID z13tjxdqnuygy1lga04cilcqxqipg1zbtbs has a "reply" option under it, while the comment with ID z13rgftjgw3bulyou04ccfnbjofztxg54yo0k does not. It seems that the user posted the comment via their Google+ page and disabled replies to their posts.

RESTful API: get/set one "global" single resource without id

TL;DR
In my current API, I've got two endpoints to handle the context:
GET /context/get
POST /context/set '{"id": "123"}'
What's the recommended way of having this global, id-less state accessible from RESTful API?
Please assume that the context concept can't be changed.
Background
Let's say I've got a user that is logged. He's by default assigned to a context that he can change.
After the context change, all the subsequent API calls will return different data, according to the context.
Example:
// Backend
Context = "Poland"
then
$ curl -X GET http://api.myapp.com/cities
will respond:
{
"cities": [{
"id": "1",
"name": Warszawa"
}, {
"id": "2",
"name": Wrocław"
}]
}
However, if you change the context:
// Backend
Context = "USA"
then, the same URL:
$ curl -X GET http://api.myapp.com/cities
should return the different set of data:
{
"cities": [{
"id": "3",
"name": New York City"
}, {
"id": "4",
"name": Boston"
}]
}
Question
As the context is just a global state on the backend side, it doesn't have an id. It doesn't belong to any collection either. Still, I want it to be accessible in the API. There are three possible solutions I see:
Solution #1 - existing
Set a context
$ curl -X POST http://api.myapp.com/context/set '{"id": "123"}'
Get a context
$ curl -X GET http://api.myapp.com/context/get
This one doesn't really feel like a RESTful API and still, on the frontend side, I have to mock the id (using ember-data). And the resource name is singular instead of plural.
Solution #2 - mocking the id
Set a context
$ curl -X POST http://api.myapp.com/context/1 '{"contextId": "123"}'
Get a context
$ curl -X GET http://api.myapp.com/context/1
Here I mock the id to always equal to one but I feel that it's super hacky and certainly not self-explanatory... Moreover, I've got a name conflict: id vs contextId. And the resource name is singular instead of plural.
Solution #3 - actions
Set a context
$ curl -X POST http://api.myapp.com/context/actions/set '{"id": "123"}'
Get a context
$ curl -X GET http://api.myapp.com/context/actions/get
This is very similar to the first one but using actions that could be a part of my whole API design (taken from e.g. gocardless. Still, I'll have a problem how to model it on the frontend side nicely. And the resource name is singular instead of plural again.
Is there any #4 option? How should I address this problem?
Thanks!
Your three solutions are RPC, not REST. Not only they are not stateless, but setting a resource to some other resource by setting an id is very RCP'ish.
A RESTful solution, if you really want to go that way, is to set the context in a header. The client should send a header like X-ContextId or something like that, and you determine the request context you need from that.
However, don't worry too much about being RESTful if that's not what your application requires. I recommend reading the answer here: SOAP vs REST (differences)
What's the recommended way of having this global, id-less state
accessible from RESTful API?
A RESTful API is by definition stateless, no client context should be stored on the server between requests.
If you want your API to be RESTful, you'll have to pass this id with each request.