I have a use case that involves dealing with a file upload in 3 steps:
- Create entry in DB
- Extract metadata from the file and store in DB using previous id
- Store file in cloud folder
I want Step 2 to happen in a fire and forget manner but it requires the id from step 1. I want steps 1 and 3 to happen synchronously and return as fast as possible. My code looks like:
def storeFile(): Future[Long]
def extractAndSaveMetadata(id:Long, content:Bytestring) : Future[Unit]
def storeFile(id, Long, content:ByteString): Future[Unit]
for {
id <- createEntryInDB()
_ <- extractAndSaveMetadata(id, content)
_ <- storeFile(id, content)
} yield ()
The problem with this approach is that step 2 is very slow and there is no problem with making it eventually consistent. At the same time it requires the value from step 1 so I don't know how to un-thread the fire and forget call in this monadic sequence of calls.
Is there a way to "fork" a future execution within a Future for-comprehension?
CodePudding user response:
Yeah, the solution was pointed by @SwiftMango. The code translates into:
for {
id <- createEntryInDB()
_ = extractAndSaveMetadata(id, content)
_ <- storeFile(id, content)
} yield ()
Other suggested approaches in the comments don't work because:
- I don't want to return after either
extractAndSaveMetadata
orstoreField
returns. There is only 1 main path that iscreateEntry andThen storeFile
- It is indeed a sequence of tasks, without the id in the first task you cannot run 2 and 3.
- Using
Future.sequence
would block the whole thread upstream until all futures are completed. I want to return control ASAP.