Unverified Commit 9daf0a31 authored by Leonardo Aramaki's avatar Leonardo Aramaki Committed by GitHub

Merge pull request #581 from RocketChat/fix/servers-logging-out

Fix servers logging out on app update
parents 975511e9 c20777bc
......@@ -20,8 +20,8 @@ android {
applicationId "chat.rocket.android"
minSdkVersion 16
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 50
versionName "1.0.27"
versionCode 52
versionName "1.0.29"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
multiDexEnabled true
......@@ -144,7 +144,7 @@ dependencies {
testCompile "org.jetbrains.kotlin:kotlin-test:$rootProject.ext.kotlinVersion"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$rootProject.ext.kotlinVersion"
testCompile "org.jetbrains.kotlin:kotlin-reflect:$rootProject.ext.kotlinVersion"
testCompile "com.nhaarman:mockito-kotlin:1.1.0"
testCompile "com.nhaarman:mockito-kotlin:1.5.0"
testCompile 'org.amshove.kluent:kluent:1.14'
}
apply plugin: 'com.google.gms.google-services'
package chat.rocket.android.service;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.ServiceConnection;
......@@ -68,6 +69,7 @@ import io.reactivex.subjects.PublishSubject;
}
}
@SuppressLint("RxLeakedSubscription")
@DebugLog
@Override
public void ensureConnections() {
......@@ -84,6 +86,7 @@ import io.reactivex.subjects.PublishSubject;
});
}
@SuppressLint("RxLeakedSubscription")
@Override
public void addOrUpdateServer(String hostname, @Nullable String name, boolean insecure) {
RealmBasedServerInfo.addOrUpdate(hostname, name, insecure);
......@@ -95,6 +98,7 @@ import io.reactivex.subjects.PublishSubject;
}, RCLog::e);
}
@SuppressLint("RxLeakedSubscription")
@Override
public void removeServer(String hostname) {
RealmBasedServerInfo.remove(hostname);
......@@ -166,7 +170,11 @@ import io.reactivex.subjects.PublishSubject;
@DebugLog
private Single<Boolean> connectToServerIfNeeded(String hostname, boolean forceConnect) {
return Single.defer(() -> {
final int connectivity = serverConnectivityList.get(hostname);
Integer state = serverConnectivityList.get(hostname);
if (state == null) {
state = ServerConnectivity.STATE_DISCONNECTED;
}
final int connectivity = state;
if (!forceConnect && connectivity == ServerConnectivity.STATE_CONNECTED) {
return Single.just(true);
}
......
......@@ -72,8 +72,8 @@ public class RocketChatWebSocketThread extends HandlerThread {
private final RealmHelper realmHelper;
private final ConnectivityManagerInternal connectivityManager;
private final ArrayList<Registrable> listeners = new ArrayList<>();
private final CompositeDisposable hearbeatDisposable = new CompositeDisposable();
private final CompositeDisposable reconnectSubscription = new CompositeDisposable();
private final CompositeDisposable heartbeatDisposable = new CompositeDisposable();
private final CompositeDisposable reconnectDisposable = new CompositeDisposable();
private boolean listenersRegistered;
private static class KeepAliveTimer {
......@@ -109,14 +109,13 @@ public class RocketChatWebSocketThread extends HandlerThread {
*/
@DebugLog
public static Single<RocketChatWebSocketThread> getStarted(Context appContext, String hostname) {
return Single.<RocketChatWebSocketThread>fromPublisher(objectSingleEmitter -> {
return Single.<RocketChatWebSocketThread>create(objectSingleEmitter -> {
new RocketChatWebSocketThread(appContext, hostname) {
@Override
protected void onLooperPrepared() {
try {
super.onLooperPrepared();
objectSingleEmitter.onNext(this);
objectSingleEmitter.onComplete();
objectSingleEmitter.onSuccess(this);
} catch (Exception exception) {
objectSingleEmitter.onError(exception);
}
......@@ -151,15 +150,14 @@ public class RocketChatWebSocketThread extends HandlerThread {
@DebugLog
public Single<Boolean> terminate() {
if (isAlive()) {
return Single.fromPublisher(emitter -> {
return Single.create(emitter -> {
new Handler(getLooper()).post(() -> {
RCLog.d("thread %s: terminated()", Thread.currentThread().getId());
unregisterListenersAndClose();
connectivityManager.notifyConnectionLost(hostname,
DDPClient.REASON_CLOSED_BY_USER);
RocketChatWebSocketThread.super.quit();
emitter.onNext(true);
emitter.onComplete();
emitter.onSuccess(true);
});
});
} else {
......@@ -199,7 +197,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
keepAliveTimer.update();
return Single.fromPublisher(emitter -> {
return Single.create(emitter -> {
new Thread() {
@Override
public void run() {
......@@ -212,8 +210,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
emitter.onError(error);
} else {
keepAliveTimer.update();
emitter.onNext(true);
emitter.onComplete();
emitter.onSuccess(true);
}
return null;
});
......@@ -240,24 +237,11 @@ public class RocketChatWebSocketThread extends HandlerThread {
});
}
private Single<Boolean> prepareDDPClient() {
// TODO: temporarily replaced checkIfConnectionAlive() call for this single checking if ddpClient is
// null or not. In case it is, build a new client, otherwise just keep connecting with existing one.
return Single.just(DDPClient.get() != null)
.doOnSuccess(alive -> {
if (!alive) {
RCLog.d("DDPClient#build");
}
});
}
private Single<Boolean> connectDDPClient() {
return prepareDDPClient()
.flatMap(_val -> Single.fromPublisher(emitter -> {
return Single.create(emitter -> {
ServerInfo info = connectivityManager.getServerInfoForHost(hostname);
if (info == null) {
emitter.onNext(false);
emitter.onComplete();
emitter.onSuccess(false);
return;
}
RCLog.d("DDPClient#connect");
......@@ -295,32 +279,29 @@ public class RocketChatWebSocketThread extends HandlerThread {
if (task.isFaulted()) {
emitter.onError(task.getError());
} else {
emitter.onNext(true);
emitter.onComplete();
emitter.onSuccess(true);
}
return null;
});
}));
});
}
private void reconnect() {
// if we are already trying to reconnect then return.
if (reconnectSubscription.size() > 0) {
if (reconnectDisposable.size() > 0) {
return;
}
forceInvalidateTokens();
connectivityManager.notifyConnecting(hostname);
reconnectSubscription.add(
reconnectDisposable.add(
connectWithExponentialBackoff()
.subscribe(
connected -> {
.subscribe(connected -> {
if (!connected) {
connectivityManager.notifyConnecting(hostname);
}
reconnectSubscription.clear();
},
error -> {
logErrorAndUnsubscribe(reconnectSubscription, error);
reconnectDisposable.clear();
}, error -> {
logErrorAndUnsubscribe(reconnectDisposable, error);
connectivityManager.notifyConnectionLost(hostname,
DDPClient.REASON_NETWORK_ERROR);
}
......@@ -340,12 +321,11 @@ public class RocketChatWebSocketThread extends HandlerThread {
@DebugLog
private Single<Boolean> connect() {
return connectDDPClient()
.flatMap(_val -> Single.fromPublisher(emitter -> {
.flatMap(_val -> Single.create(emitter -> {
fetchPublicSettings();
fetchPermissions();
registerListeners();
emitter.onNext(true);
emitter.onComplete();
emitter.onSuccess(true);
}));
}
......@@ -389,7 +369,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
} else {
return Completable.complete();
}
}).retryWhen(RxHelper.exponentialBackoff(Integer.MAX_VALUE, 500, TimeUnit.MILLISECONDS))
}).retryWhen(RxHelper.exponentialBackoff(3, 500, TimeUnit.MILLISECONDS))
.subscribe(
() -> {
createObserversAndRegister();
......@@ -425,8 +405,8 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
private void startHeartBeat() {
hearbeatDisposable.clear();
hearbeatDisposable.add(
heartbeatDisposable.clear();
heartbeatDisposable.add(
heartbeat(HEARTBEAT_PERIOD_MS)
.subscribe(
ponged -> {
......@@ -437,7 +417,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
error -> {
RCLog.e(error);
// Stop pinging
hearbeatDisposable.clear();
heartbeatDisposable.clear();
if (error instanceof DDPClientCallback.Closed || error instanceof TimeoutException) {
RCLog.d("Hearbeat failure: retrying connection...");
reconnect();
......@@ -461,7 +441,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
registrable.unregister();
iterator.remove();
}
hearbeatDisposable.clear();
heartbeatDisposable.clear();
listenersRegistered = false;
}
}
......@@ -15,9 +15,9 @@ buildscript {
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.51"
classpath 'io.realm:realm-gradle-plugin:4.2.0-SNAPSHOT'
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.60"
classpath 'io.realm:realm-gradle-plugin:4.2.0'
classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
classpath 'com.google.gms:google-services:3.0.0'
classpath 'com.github.triplet.gradle:play-publisher:1.1.5'
......
......@@ -6,6 +6,7 @@ import chat.rocket.persistence.realm.models.ddp.RealmRole;
import chat.rocket.persistence.realm.models.ddp.RealmRoomRole;
import chat.rocket.persistence.realm.models.ddp.RealmSpotlightRoom;
import chat.rocket.persistence.realm.models.ddp.RealmSpotlightUser;
import chat.rocket.persistence.realm.models.ddp.RealmUser;
import io.realm.DynamicRealm;
import io.realm.FieldAttribute;
import io.realm.RealmMigration;
......@@ -67,6 +68,13 @@ public class Migration implements RealmMigration {
if (oldVersion == 4) {
RealmObjectSchema messageSchema = schema.get("RealmMessage");
messageSchema.addField(RealmMessage.EDITED_AT, long.class);
oldVersion++;
}
if (oldVersion == 5) {
RealmObjectSchema userSchema = schema.get("RealmUser");
userSchema.addField(RealmUser.NAME, String.class);
}
}
......
......@@ -15,9 +15,7 @@ public class RealmStore {
.name(name + ".realm")
.modules(new RocketChatLibraryModule())
.migration(new Migration())
.schemaVersion(5)
// Just in case
.deleteRealmIfMigrationNeeded()
.schemaVersion(6)
.build();
}
......@@ -49,7 +47,7 @@ public class RealmStore {
sStore.put(name, new RealmConfiguration.Builder()
.name(name + ".realm")
.modules(new RocketChatServerModule())
.deleteRealmIfMigrationNeeded().build());
.build());
}
return new RealmHelper(sStore.get(name));
}
......
......@@ -41,8 +41,7 @@ public class RealmMessageRepository extends RealmRepository implements MessageRe
return Flowable.empty();
}
return
pair.first.where(RealmMessage.class)
return pair.first.where(RealmMessage.class)
.equalTo(RealmMessage.ID, messageId)
.findAll()
.<RealmResults<RealmMessage>>asFlowable();
......
......@@ -7,6 +7,7 @@ import com.hadisatrio.optional.Optional;
import chat.rocket.core.models.Session;
import chat.rocket.core.repositories.SessionRepository;
import chat.rocket.persistence.realm.RealmHelper;
import chat.rocket.persistence.realm.RealmStore;
import chat.rocket.persistence.realm.models.internal.RealmSession;
import io.reactivex.Flowable;
......@@ -73,14 +74,9 @@ public class RealmSessionRepository extends RealmRepository implements SessionRe
realmSession.setTokenVerified(session.isTokenVerified());
realmSession.setError(session.getError());
realm.beginTransaction();
return realm.copyToRealmOrUpdate(realmSession)
.asFlowable()
return RealmHelper.copyToRealmOrUpdate(realm, realmSession)
.filter(it -> it != null && it.isLoaded() && it.isValid())
.firstElement()
.doOnSuccess(it -> realm.commitTransaction())
.doOnError(throwable -> realm.cancelTransaction())
.doOnEvent((realmObject, throwable) -> close(realm, looper))
.toSingle()
.map(realmObject -> true);
......
......@@ -6,7 +6,7 @@ dependencies {
compile extraDependencies.rxJava
compile extraDependencies.optional
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.ext.kotlinVersion"
compile 'com.google.code.findbugs:jsr305:3.0.1'
compile 'com.google.code.findbugs:jsr305:3.0.2'
compileOnly 'com.google.auto.value:auto-value:1.3'
kapt 'com.google.auto.value:auto-value:1.3'
kapt 'com.gabrielittner.auto.value:auto-value-with:1.0.0'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment