[JAVA-1282] Create new async GridFS API Created: 17/Jun/14 Updated: 19/Oct/16 Resolved: 28/Apr/16 |
|
| Status: | Closed |
| Project: | Java Driver |
| Component/s: | Async, GridFS |
| Affects Version/s: | None |
| Fix Version/s: | 3.3.0 |
| Type: | New Feature | Priority: | Major - P3 |
| Reporter: | Jeffrey Yemin | Assignee: | Ross Lawley |
| Resolution: | Done | Votes: | 2 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||
| Description |
|
Currently there is no async support for GridFS. We need to design a new GridFS API that works properly with async. |
| Comments |
| Comment by Githook User [ 03/May/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Author: {u'username': u'rozza', u'name': u'Ross Lawley', u'email': u'ross.lawley@gmail.com'}Message: Increased the timeouts for the slow GridFS tests Added runSlow method to Async GridFS test helper
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Steve Hummingbird [ 28/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Awesome. Thanks Ross. The GridFSFile codec now seems to work great with my Instant Codec. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ross Lawley [ 28/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thanks again Steve Hummingbird for testing and reporting the issues back. The codec and the small chunk issues have now been fixed and a new snapshot has just been released. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Githook User [ 28/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Author: {u'username': u'rozza', u'name': u'Ross Lawley', u'email': u'ross.lawley@gmail.com'}Message: Improved how small chunksizes are handled in Async GridFS Added minimum bufferSize when downloading to AsyncOutputStream
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Githook User [ 27/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Author: {u'username': u'rozza', u'name': u'Ross Lawley', u'email': u'ross.lawley@gmail.com'}Message: Added Codec for GridFSFile GridFSFile requires certain types eg. Date, but takes a users Codec which may
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ross Lawley [ 20/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Reopening this ticket, pending fixes for the above issues. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jeffrey Yemin [ 20/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Given what I'm seeing, a larger file size won't cause a problem, only a small chunk size. The issue is triggered when a lot of small chunks fit in a single response to a getMore command. With the way the code is implemented now, it ends up triggering a whole series of callbacks back and forth, all on the same thread. Eventually the stack overflows. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Steve Hummingbird [ 20/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi Jeff, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jeffrey Yemin [ 19/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi Steve, I'm able to reproduce the second problem you're seeing. It looks like a bug, but you'll likely only encounter it with a low value for chunkSizeBytes, like 1024 as in your example. So you can work around the issue by using a larger value: for instance, I can't reproduce the issue when I leave it as the default of (255 * 1024). Is there a particular reason you were testing with such a small batch size? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jeffrey Yemin [ 19/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi Steve, First of all, we really appreciate the advanced testing you are doing for async GridFS. The custom codec issue should be considered a bug. While we investigate a solution, you can work around it by passing a MongoDatabase instance to GridFSBuckets.create that is configured with the default codec registry, e.g.
This will be more resource-efficient that using a different MongoClient just for GridFS. As for the modified GridFSTour throwing an error, that also looks to be a bug, so we'll investigate that as well. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Steve Hummingbird [ 19/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There has been another issue I have been running into. In case there is huge number of chunks created (in this case 500), downloading the chunks leads to an Exception which also gets swallowed by the same error handler. Right now I am not sure if I am running into another (or even to be expected) limitation. This is a modified version of the GridFSTour which leads to the error on my machine:
And this is the stack trace that gets swallowed:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Steve Hummingbird [ 19/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I have been running into issues with the new GridFS implementation when using custom codecs. I have implemented a Codec and a Provider which make use of the java 8 Instant instead of the old java.util.Date class. The GridFSFileHelper however expects the uploadDate to always be returned as java.util.Date:
In the end this leads to an exception as an Instant can not be cast to a date, which does not seem to be handed back to the client. The only behaviour that is visible to the client is that the callback never gets called and the driver seems to be stuck. As the GridFSFile is composed programmatically, I guess there isn't any way to tell my custom codec to not to be used for the GridFSFile, or is it? The exception gets caught in that block in ErrorHandlingResultCallback.java
where the logger is null, so the exception just gets swallowed. I don't know the implementation of the driver that well to judge if there might be any side effects, but it kind of seems to make sense to report any occurring exception back to the client instead of just swallowing and/or logging them. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Steve Hummingbird [ 18/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi Jeff, thank you. that made things clearer. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jeffrey Yemin [ 10/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi Steve, You're describing a producer-consumer problem where fileUpload is the producer and uploadStream is the consumer. The GridFSUploadStream API, like the Java AsynchronousSocketChannel API on which it is modelled, does not include any support for buffering, so your application will have to. To avoid this buffer growing unbounded, you may have to find a way to apply back pressure to the file uploader. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Steve Hummingbird [ 10/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Great I was trying to use the new api, however I was having some trouble when working with data that is available asynchronously, but I might just be missing something obvious. I am using vertx 2, where I have to register a handler when new data is available. Apparently I can not do something like that, where I would just call the write() method when data is available, as this leads to an exception: com.mongodb.MongoGridFSException: The AsyncOutputStream does not support concurrent writing.
This would lead the conclusion that I have to buffer all the data programmatically until the GridFS driver is calling the callback, where I then am able to add another slice of data, where I can add another callback to handle the next slice that has been available in the meantime, or maybe that slice isn't available yet, which will complicate things further. In case I implement my own AsyncInputStream, the same thing applies. I would need to somehow buffer the data until the read method is called by the driver where I can provide a slice of data, which in turn seems quite cumbersome to me. And just in case, if the next slice of data is not yet available when the read method is called, and I provide 0 bytes, does the driver periodically poll if the data is available yet? So the only option that appears to me is to buffer all data until everything is available and then call the GridFS driver, but that does not seem very efficient to me. I guess there must be a better way to do this, which I am just missing. Could you please add some detail on how the driver should be used in such case? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Githook User [ 06/Apr/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Author: {u'username': u'rozza', u'name': u'Ross Lawley', u'email': u'ross.lawley@gmail.com'}Message: Asynchronous GridFS Implementation Uses a custom AsyncInputStream and AsyncOutputStream for easy adaptability to custom async byte I/O.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ross Lawley [ 30/Mar/16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||