Skip to content

Instantly share code, notes, and snippets.

@lujop
Created August 2, 2016 15:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lujop/ba480de9ad061a99758ff5cebcc10cec to your computer and use it in GitHub Desktop.
Save lujop/ba480de9ad061a99758ff5cebcc10cec to your computer and use it in GitHub Desktop.
package cat.joanpujol.firebase;
import com.google.firebase.database.FirebaseDatabase;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import timber.log.Timber;
/**
* Created by lujop on 26/07/16.
*/
public class FirebaseOnlineTracker {
private static FirebaseOnlineTracker INSTANCE;
private ScheduledThreadPoolExecutor threadPoolExecutor;
private Set<OnlineRequest> requests = new HashSet<>();
private ScheduledFuture<Void> goingOffline;
private boolean online;
private FirebaseOnlineTracker(ScheduledThreadPoolExecutor spe) {
this.threadPoolExecutor = spe;
}
public static void init(ScheduledThreadPoolExecutor spe) {
if(INSTANCE==null) {
INSTANCE = new FirebaseOnlineTracker(spe);
Timber.i("FirebaseOnlineTracker initialized");
} else {
throw new RuntimeException("FirebaseOnlineTracker already initialized");
}
}
public static FirebaseOnlineTracker get() {
return INSTANCE;
}
public synchronized OnlineRequest requestOnline(String reason) {
OnlineRequest request = new OnlineRequest(reason);
if(requests.isEmpty()) {
if(goingOffline!=null) {
goingOffline.cancel(true);
Timber.d("Cancelling going offline due t %s",reason);
goingOffline = null;
}
FirebaseDatabase.getInstance().goOnline();
boolean wasOnline = online;
online = true;
if(wasOnline)
Timber.i("Asking firebase to go online for %s",reason);
} else {
Timber.v("Increasing reference count due to %s. Already online",reason);
}
requests.add(request);
return request;
}
public synchronized void releaseOnline(OnlineRequest request) {
boolean removed = requests.remove(request);
if(!removed)
Timber.w("OnlineRequest not already present");
if(requests.isEmpty()) {
if(goingOffline==null) {
Timber.v("No active online requests. Will schedule go offline in 1 minute due to %s",request.reason);
goingOffline = threadPoolExecutor.schedule(goOfflineCallable, 1, TimeUnit.MINUTES);
} else {
Timber.v("No need to schedule offline. There is already a scheduled job. Request due to %s",request.reason);
}
}
}
public synchronized void logStatus() {
Timber.i("Online=%b. GoingOffline=%b Requests:",online, goingOffline!=null, requests.toString());
}
private final Callable<Void> goOfflineCallable = new Callable<Void>() {
@Override
public Void call() throws Exception {
synchronized (FirebaseOnlineTracker.this) {
Timber.i("Asking firebase to go offline");
FirebaseDatabase.getInstance().goOffline();
online = false;
goingOffline = null;
return null;
}
}
};
public static class OnlineRequest {
private String reason;
private StackTraceElement[] stackTrace;
public OnlineRequest(String reason) {
stackTrace = Thread.currentThread().getStackTrace();
this.reason = reason;
}
@Override
public String toString() {
return "OnlineRequest{" + "stackTrace=" + Arrays.toString(stackTrace) + " reason="+reason+'}';
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment