Binev
Binev

Reputation: 276

Firebase Storage RejectedExecutionException exception

In my project I am using Firebase Storage to download some image files - 154 images to be exact. For some unknown reason to me I only manage to download only around 130 files and then I get an exception stating:

java.util.concurrent.RejectedExecutionException: Task com.google.firebase.storage.zzs@15c1d59d rejected from java.util.concurrent.ThreadPoolExecutor@270bfa12[Running, pool size = 3, active threads = 3, queued tasks = 128, completed tasks = 5]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2011)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:793)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1339)
    at com.google.firebase.storage.zzu.zzv(Unknown Source)
    at com.google.firebase.storage.FileDownloadTask.schedule(Unknown Source)
    at com.google.firebase.storage.StorageTask.zzcny(Unknown Source)
    at com.google.firebase.storage.StorageReference.getFile(Unknown Source)
    at com.google.firebase.storage.StorageReference.getFile(Unknown Source)

I am using for loop to call StorageReference.getFile() and download the file in specific location like this:

        for (int i = 0; i < filesToDownload.size(); i++) {
            String image = filesToDownload.get(i);

            final File localFile = new 
               File(DeviceStorage.getExternalStorageDir(dirPath)
               + File.separator + fileName);
            StorageReference downloadPhotoRef = 
               getReference().child(folderName + File.separator + fileName);

            downloadPhotoRef.getFile(localFile);
            downloadFile(context, image);
        }

I am really puzzled why does this happen. I couldn't find any solutions and other people having the same problem. I run this code in a Service. The only way I don't get the error is if I'm downloading less than 130 files, but this is no good to me.

Please help.

Upvotes: 1

Views: 424

Answers (1)

Gazihan Alankus
Gazihan Alankus

Reputation: 11984

You are starting too many parallel download tasks. The threading system gives up as a result. More about that here: https://stackoverflow.com/a/8183463/679553

You should try to serialize parts of this process, maybe download them 10 by 10? .continueWith() here is a good start: https://firebase.googleblog.com/2016/09/become-a-firebase-taskmaster-part-3_29.html

At the moment your getFile() call spawns a new download task and returns without blocking. Instead of starting the next download with the next iteration of the for loop, you can start it after the previous download is done using .continueWith().

One way to implement this is to create a function that returns a task and calling itself back in the last continueWith block. Kind of like the C# example form here: https://stackoverflow.com/a/49043177/679553

I modified an example from that link to make it closer to your case. I'm on mobile so this is the best I can do at the moment:) You can make the ref be a field in your class and update it inside the continueWith blocks.

Task DoStuff()
{
    return ref.getFile(() => DoWork1())
        .ContinueWith((t1) => DoWork2())
        .ContinueWith(t2 => DoWork3())
        .ContinueWith(t3=> DoStuff());
}

Upvotes: 2

Related Questions