Closed christiangroth closed 6 years ago
Hi @christiangroth,
all write requests in RESTHeart have upsert semantic. So the first PUT /db/collection
actually creates the collection (201 Created). The other ones update it (200 Ok).
Note that with RESTHeart db and collections have properties (see https://restheart.org/learn/representation-format/) so yes, you can update the properties of a collection with a PUT.
If you want to avoid updating them, you can use the ETag.
An example with httpie
$ http PUT :8080/db/test2?checkEtag
HTTP/1.1 201 Created
$ http PUT :8080/db/test2?checkEtag
HTTP/1.1 409 Conflict
Hi,
the ETag hint is a good one, we will think about it. Nevertheless I think the description I provided maybew was not clear enought. The issue we care about is restheart providing HTTP 500 responses in some cases. This does not happen every time, so it seems to be an synchronization issue.
Anything new on this one? Any suggestions?
Hi @christiangroth ,
does ?checkEtag
solve the problem?
If not, can you provide a reproducer?
Hey @ujibang,
I think we don't get each other right. The whole thing is not about checking the Etag at all, it's about getting HTTP 500 instead of HTTP 200 or HTTP 201. How shpould checking the Etag avoid the HTTP 500 response?
Checking the ETag forces RESTHart to look at the _etag property of the collection, before actually upserting it. I thought this might avoid the error that leads 500.
Since I'm not able how to reproduce the issue, I'm not sure if this is actually true. I think it is worth a try.
Besides this, can you please share a test case that reproduce the bug?
Ah ... now I got it, thanks!m I'll try it later and let you know if that helps. Unfortunately we do not have a testcase, we can just run our application pushing data to restheart and see it happen.
Hi @ujibang,
I've added ?checkEtag to the PUT requests creating db and collection, but this did not fix anything. I've attached the restheart logfile. As you can see there are exceptions like "collection ... already exists" and in additon also the HTTP 500 responses.
I would have expected HTTP 409 Conflict responses instead of exceptions or I am worng here?
yes this is a bug indeed and the ?checkEtag trick does not workaround it.
I extracted from the log file, the evidence of two concurrent requests (actually happening at exactly the same millisecond 09:08:01.623), one leading to error 500.
The problem is that RESTHeart checks if a collection exists, and the it creates or updates it. These are two different, not atomic operations that can lead to this exception.
I'm going to handle the exception accordingly.
09:08:01.622 [XNIO-1 task-4] ERROR org.restheart.handlers.ErrorHandler - Error handling the request
com.mongodb.MongoCommandException: Command failed with error 48: 'a collection 'xxx.products' already exists' on server xxx:27017. The full response is { "note" : "the autoIndexId option is deprecated and will be removed in a future release", "ok" : 0.0, "errmsg" : "a collection 'MithrasEnergy20.products' already exists", "code" : 48, "codeName" : "NamespaceExists" }
at com.mongodb.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:115)
at com.mongodb.connection.CommandProtocol.execute(CommandProtocol.java:107)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:159)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:289)
at com.mongodb.connection.DefaultServerConnection.command(DefaultServerConnection.java:176)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:216)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:207)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:146)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:139)
at com.mongodb.operation.CreateCollectionOperation$1.call(CreateCollectionOperation.java:380)
at com.mongodb.operation.CreateCollectionOperation$1.call(CreateCollectionOperation.java:376)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:424)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:415)
at com.mongodb.operation.CreateCollectionOperation.execute(CreateCollectionOperation.java:376)
at com.mongodb.operation.CreateCollectionOperation.execute(CreateCollectionOperation.java:53)
at com.mongodb.Mongo.execute(Mongo.java:819)
at com.mongodb.Mongo$2.execute(Mongo.java:802)
at com.mongodb.MongoDatabaseImpl.createCollection(MongoDatabaseImpl.java:198)
at com.mongodb.MongoDatabaseImpl.createCollection(MongoDatabaseImpl.java:169)
at org.restheart.db.CollectionDAO.upsertCollection(CollectionDAO.java:331)
at org.restheart.db.DbsDAO.upsertCollection(DbsDAO.java:460)
at org.restheart.handlers.collection.PutCollectionHandler.handleRequest(PutCollectionHandler.java:154)
at org.restheart.handlers.PipedHttpHandler.next(PipedHttpHandler.java:121)
at org.restheart.handlers.metadata.TransformersListHandler.handleRequest(TransformersListHandler.java:73)
at org.restheart.handlers.PipedHttpHandler.next(PipedHttpHandler.java:121)
at org.restheart.handlers.metadata.TransformerHandler.handleRequest(TransformerHandler.java:75)
at org.restheart.handlers.RequestDispatcherHandler.handleRequest(RequestDispatcherHandler.java:562)
at org.restheart.handlers.injectors.CollectionPropsInjectorHandler.handleRequest(CollectionPropsInjectorHandler.java:107)
at org.restheart.handlers.PipedHttpHandler.next(PipedHttpHandler.java:121)
at org.restheart.handlers.injectors.DbPropsInjectorHandler.handleRequest(DbPropsInjectorHandler.java:92)
09:08:01.623 [XNIO-1 task-8] INFO o.r.handlers.RequestLoggerHandler - PUT http://localhost:8080/xxx/products?checkEtag from /172.31.1.1:43774 => status=201 elapsed=23ms contentLength=0
09:08:01.623 [XNIO-1 task-4] INFO o.r.handlers.RequestLoggerHandler - PUT http://localhost:8080/xxx/products?checkEtag from /172.31.1.1:43782 => status=500 elapsed=23ms contentLength=309
In commit 71d192c6481311f6c0621b57911bbd707fa529d5, there is a possible fix.
can you please test it?
Hi @ujibang,
sorry for the late response, I was out of office for some days. The fix looks good, I will test it and get back to you!
I'm wondering if the same situation can happen when creating a database instead of a collection and if this should also be fixed??
Hi there, with 3.4.2 I was no longer able to reproduce the exception - thank you @ujibang
PS: would be great if you could comment on Christian's last question (whether it may still happen upon db creation even though I did not run into this (so far))
Hello again, unfortunately, we are now encountering 500 Responses when concurent requests for deleting files are sent. I am opening a new question for this....
I think this specific issue has been already solved so I'm closing this, if not please re-open.
We have a quite simple approach putting new content to mongo via restheart:
Expected Behavior
Current Behavior
Context / Environment
restheart 3.3.1