Commit 9b1ba0df authored by Yusuke Iwaki's avatar Yusuke Iwaki

FIX #75 Merge branch 'fix_infinite_error_looping' into develop

parents 9c00b01c bd6f84e5
......@@ -36,6 +36,12 @@ public class DDPClientCallback {
this.version = version;
}
}
public static class Timeout extends BaseException {
public Timeout(DDPClient client) {
super(client);
}
}
}
public static class Ping extends Base {
......
......@@ -67,6 +67,7 @@ public class DDPClientImpl {
observable.filter(callback -> callback instanceof RxWebSocketCallback.Message)
.map(callback -> ((RxWebSocketCallback.Message) callback).responseBodyString)
.map(DDPClientImpl::toJson)
.timeout(7, TimeUnit.SECONDS)
.subscribe(response -> {
String msg = extractMsg(response);
if ("connected".equals(msg) && !response.isNull("session")) {
......@@ -83,6 +84,7 @@ public class DDPClientImpl {
subscriptions.unsubscribe();
}
}, err -> {
task.setError(new DDPClientCallback.Connect.Timeout(client));
}));
addErrorCallback(subscriptions, task);
......@@ -336,7 +338,7 @@ public class DDPClientImpl {
private void addErrorCallback(CompositeSubscription subscriptions, TaskCompletionSource<?> task) {
subscriptions.add(observable.subscribe(base -> {
}, err -> {
task.setError(new Exception(err));
task.trySetError(new Exception(err));
subscriptions.unsubscribe();
}));
}
......
......@@ -26,6 +26,7 @@ import hugo.weaving.DebugLog;
public class MainActivity extends AbstractAuthedActivity {
private RealmObjectObserver<Session> sessionObserver;
private boolean isForeground;
@Override
protected int getLayoutContainerForFragment() {
......@@ -50,6 +51,18 @@ public class MainActivity extends AbstractAuthedActivity {
setUserOnlineIfServerAvailable();
}
@Override
protected void onResume() {
super.onResume();
isForeground = true;
}
@Override
protected void onPause() {
isForeground = false;
super.onPause();
}
@Override
protected void onStop() {
setUserAwayIfServerAvailable();
......@@ -134,7 +147,7 @@ public class MainActivity extends AbstractAuthedActivity {
.equalTo("tokenVerified", true)
.isNull("error"))
.setOnUpdateListener(session -> {
if (session == null) {
if (session == null && isForeground) {
LaunchUtil.showServerConfigActivity(this, serverConfigId);
}
});
......
......@@ -7,9 +7,11 @@ import android.support.v4.app.Fragment;
import chat.rocket.android.R;
import chat.rocket.android.fragment.server_config.LoginFragment;
import chat.rocket.android.fragment.server_config.RetryConnectFragment;
import chat.rocket.android.fragment.server_config.RetryLoginFragment;
import chat.rocket.android.fragment.server_config.WaitingFragment;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.internal.Session;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
......@@ -21,6 +23,7 @@ import chat.rocket.android.service.RocketChatService;
public class ServerConfigActivity extends AbstractFragmentActivity {
private String serverConfigId;
private RealmObjectObserver<ServerConfig> serverConfigErrorObserver;
private RealmObjectObserver<Session> sessionObserver;
@Override
......@@ -44,6 +47,13 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
return;
}
serverConfigErrorObserver = RealmStore.getDefault()
.createObjectObserver(realm ->
realm.where(ServerConfig.class)
.equalTo("serverConfigId", serverConfigId)
.equalTo("state", ServerConfig.STATE_CONNECTION_ERROR))
.setOnUpdateListener(this::onRenderServerConfigError);
sessionObserver = RealmStore.get(serverConfigId)
.createObjectObserver(Session::queryDefaultSession)
.setOnUpdateListener(this::onRenderServerConfigSession);
......@@ -56,15 +66,25 @@ public class ServerConfigActivity extends AbstractFragmentActivity {
protected void onResume() {
super.onResume();
RocketChatService.keepalive(this);
sessionObserver.sub();
serverConfigErrorObserver.sub();
}
@Override
protected void onPause() {
sessionObserver.unsub();
serverConfigErrorObserver.unsub();
super.onPause();
}
private void onRenderServerConfigError(ServerConfig config) {
if (config != null) {
sessionObserver.unsub();
showFragment(new RetryConnectFragment());
} else {
sessionObserver.sub();
}
}
private void onRenderServerConfigSession(Session session) {
if (session == null) {
showFragment(new LoginFragment());
......
package chat.rocket.android.fragment.server_config;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.TextView;
import chat.rocket.android.R;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
/**
* Login screen.
*/
public class RetryConnectFragment extends AbstractServerConfigFragment {
private RealmObjectObserver<ServerConfig> serverConfigObserver;
@Override
protected int getLayout() {
return R.layout.fragment_retry_login;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
serverConfigObserver = RealmStore.getDefault()
.createObjectObserver(realm ->
realm.where(ServerConfig.class).equalTo("serverConfigId", serverConfigId))
.setOnUpdateListener(this::onRenderServerConfig);
}
@Override
protected void onSetupView() {
rootView.findViewById(R.id.waiting).setVisibility(View.GONE);
final View btnRetry = rootView.findViewById(R.id.btn_retry_login);
btnRetry.setOnClickListener(view -> {
RealmStore.getDefault()
.executeTransaction(realm -> {
ServerConfig config = realm.where(ServerConfig.class)
.equalTo("serverConfigId", serverConfigId).findFirst();
if (config != null && config.getState() == ServerConfig.STATE_CONNECTION_ERROR) {
config.setState(ServerConfig.STATE_READY);
}
return null;
}).continueWith(new LogcatIfError());
});
}
private void onRenderServerConfig(ServerConfig config) {
if (config == null) {
return;
}
final String error = config.getError();
final TextView txtError = (TextView) rootView.findViewById(R.id.txt_error_description);
if (!TextUtils.isEmpty(error)) {
txtError.setText(error);
}
final int state = config.getState();
if (state == ServerConfig.STATE_CONNECTED) {
finish();
}
rootView.findViewById(R.id.btn_retry_login)
.setEnabled(state == ServerConfig.STATE_CONNECTION_ERROR);
}
@Override
public void onResume() {
super.onResume();
serverConfigObserver.sub();
}
@Override
public void onPause() {
serverConfigObserver.unsub();
super.onPause();
}
}
......@@ -183,10 +183,10 @@ public class RocketChatWebSocketThread extends HandlerThread {
return null;
})).continueWith(new LogcatIfError());
return task;
}).onSuccess(new Continuation<DDPClientCallback.Connect, Object>() {
}).onSuccess(new Continuation<DDPClientCallback.Connect, Void>() {
// TODO type detection doesn't work due to retrolambda's bug...
@Override
public Object then(Task<DDPClientCallback.Connect> task)
public Void then(Task<DDPClientCallback.Connect> task)
throws Exception {
registerListeners();
......@@ -194,20 +194,25 @@ public class RocketChatWebSocketThread extends HandlerThread {
task.getResult().client.getOnCloseCallback().onSuccess(_task -> {
quit();
return null;
}).continueWith(_task -> {
}).continueWithTask(_task -> {
if (_task.isFaulted()) {
ServerConfig.logConnectionError(serverConfigId, _task.getError());
}
return null;
return _task;
});
return null;
}
}).continueWith(task -> {
}).continueWithTask(task -> {
if (task.isFaulted()) {
ServerConfig.logConnectionError(serverConfigId, task.getError());
Exception error = task.getError();
if (error instanceof DDPClientCallback.Connect.Timeout) {
ServerConfig.logConnectionError(serverConfigId, new Exception("Connection Timeout"));
} else {
ServerConfig.logConnectionError(serverConfigId, task.getError());
}
}
return null;
return task;
});
}
......
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