com.google.firebase.database.utilities.DefaultRunLoop Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of firebase-admin Show documentation
Show all versions of firebase-admin Show documentation
This is the official Firebase Admin Java SDK. Build extraordinary native JVM apps in
minutes with Firebase. The Firebase platform can power your app’s backend, user
authentication, static hosting, and more.
/*
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.firebase.database.utilities;
import com.google.firebase.database.DatabaseException;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.core.RunLoop;
import com.google.firebase.internal.FirebaseScheduledExecutor;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public abstract class DefaultRunLoop implements RunLoop {
private final ScheduledThreadPoolExecutor executor;
private UncaughtExceptionHandler exceptionHandler;
/**
* Creates a DefaultRunLoop that optionally restarts its threads periodically. If 'context' is
* provided, these restarts will automatically interrupt and resume all Repo connections.
*/
protected DefaultRunLoop(ThreadFactory threadFactory) {
executor = new FirebaseScheduledExecutor(threadFactory, "firebase-database-worker") {
@Override
protected void afterExecute(Runnable runnable, Throwable throwable) {
super.afterExecute(runnable, throwable);
if (throwable == null && runnable instanceof Future>) {
Future> future = (Future>) runnable;
try {
// Not all Futures will be done, e.g. when used with scheduledAtFixedRate
if (future.isDone()) {
future.get();
}
} catch (CancellationException ce) {
// Cancellation exceptions are okay, we expect them to happen sometimes
} catch (ExecutionException ee) {
throwable = ee.getCause();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
if (throwable != null) {
handleExceptionInternal(throwable);
}
}
};
// Core threads don't time out, this only takes effect when we drop the number of required
// core threads
executor.setKeepAliveTime(3, TimeUnit.SECONDS);
}
public static String messageForException(Throwable t) {
if (t instanceof OutOfMemoryError) {
return "Firebase Database encountered an OutOfMemoryError. You may need to reduce the"
+ " amount of data you are syncing to the client (e.g. by using queries or syncing"
+ " a deeper path). See "
+ "https://firebase.google"
+ ".com/docs/database/ios/structure-data#best_practices_for_data_structure"
+ " and "
+ "https://firebase.google.com/docs/database/android/retrieve-data#filtering_data";
} else if (t instanceof DatabaseException) {
// Exception should be self-explanatory and they shouldn't contact support.
return "";
} else {
return "Uncaught exception in Firebase Database runloop ("
+ FirebaseDatabase.getSdkVersion()
+ "). Please report to [email protected]";
}
}
private void handleExceptionInternal(Throwable e) {
UncaughtExceptionHandler exceptionHandler;
exceptionHandler = getExceptionHandler();
try {
if (exceptionHandler != null) {
exceptionHandler.uncaughtException(Thread.currentThread(), e);
}
} finally {
handleException(e);
}
}
public abstract void handleException(Throwable e);
public ScheduledExecutorService getExecutorService() {
return this.executor;
}
@Override
public void scheduleNow(final Runnable runnable) {
executor.execute(runnable);
}
@Override
@SuppressWarnings("rawtypes")
public ScheduledFuture schedule(final Runnable runnable, long milliseconds) {
return executor.schedule(runnable, milliseconds, TimeUnit.MILLISECONDS);
}
@Override
public void shutdown() {
executor.setCorePoolSize(0);
}
@Override
public void restart() {
executor.setCorePoolSize(1);
}
/**
* Returns the exception handler currently set on this run loop. This is to be
* used during integration testing.
*/
public synchronized UncaughtExceptionHandler getExceptionHandler() {
return exceptionHandler;
}
/**
* Sets the specified exception handler for intercepting run loop errors. This is to be
* used during integration testing for handling errors that may occur in the run loop's
* worker thread.
*/
public synchronized void setExceptionHandler(UncaughtExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
}