From 4eea5c493daca9b4905b559adb3e0afa7cc54423 Mon Sep 17 00:00:00 2001 From: Terry Sahaidak Date: Sun, 9 Oct 2016 19:14:39 +0300 Subject: [PATCH 1/2] Fix reconnecting to faye server after failed to create client --- app/api/gitter.js | 2 +- app/modules/app.js | 2 +- app/modules/messages.js | 16 +-- app/modules/realtime.js | 113 ++++++++++++++---- app/screens/RoomInfoScreen.js | 1 + app/screens/RoomScreen.js | 10 +- .../terrysahaidak/faye/FayeGitterModule.java | 75 +++++++----- 7 files changed, 154 insertions(+), 65 deletions(-) diff --git a/app/api/gitter.js b/app/api/gitter.js index 4fb7dc4..1e08699 100644 --- a/app/api/gitter.js +++ b/app/api/gitter.js @@ -179,7 +179,7 @@ function callApi(endpoint, token, options = {method: 'get'}) { } }) .then(res => { - console.log(res) + // console.log(res) return res.text() }) .then(text => { diff --git a/app/modules/app.js b/app/modules/app.js index f75f17e..f3c9cb6 100644 --- a/app/modules/app.js +++ b/app/modules/app.js @@ -61,7 +61,7 @@ export function init() { await dispatch(getSuggestedRooms()) // dispatch(Navigation.resetTo({name: 'roomUsers', roomId: '56a41e0fe610378809bde160'})) } catch (error) { - dispatch({ type: INITIALIZED, error }) + dispatch({ type: INITIALIZED, error: error.message }) dispatch(Navigation.goAndReplace({name: 'login'})) } } diff --git a/app/modules/messages.js b/app/modules/messages.js index 9853a4e..50a0769 100644 --- a/app/modules/messages.js +++ b/app/modules/messages.js @@ -306,14 +306,14 @@ export function readMessages(roomId, changedRows) { dispatch({type: READ_MESSAGES, roomId, visibleAndUnread}) - try { - await Api.readMessages( - token, id, roomId, visibleAndUnread.map(item => listView.data[item].id) - ) - dispatch({type: READ_MESSAGES_OK, roomId, visibleAndUnread}) - } catch (error) { - dispatch({type: READ_MESSAGES_ERROR, error: error.message, roomId, visibleAndUnread}) - } + // try { + // await Api.readMessages( + // token, id, roomId, visibleAndUnread.map(item => listView.data[item].id) + // ) + // dispatch({type: READ_MESSAGES_OK, roomId, visibleAndUnread}) + // } catch (error) { + // dispatch({type: READ_MESSAGES_ERROR, error: error.message, roomId, visibleAndUnread}) + // } } } diff --git a/app/modules/realtime.js b/app/modules/realtime.js index a697c21..2025798 100644 --- a/app/modules/realtime.js +++ b/app/modules/realtime.js @@ -18,6 +18,9 @@ export const SUBSCRIBE_TO_ROOM_EVENTS = 'realtime/SUBSCRIBE_TO_ROOM_EVENTS' export const UNSUBSCRIBE_TO_ROOM_EVENTS = 'realtime/UNSUBSCRIBE_TO_ROOM_EVENTS' export const SUBSCRIBE_TO_READ_BY = 'realtime/SUBSCRIBE_TO_READ_BY' export const UNSUBSCRIBE_FROM_READ_BY = 'realtime/UNSUBSCRIBE_FROM_READ_BY' +export const PUSH_SUBSCRIPTION = 'realtime/PUSH_SUBSCRIPTION' +export const DELETE_SUBSCRIPTION = 'realtime/DELETE_SUBSCRIPTION' +export const SUBSCRIBED_TO_CHANNELS = 'realtime/SUBSCRIBED_TO_CHANNELS' /** @@ -26,15 +29,14 @@ export const UNSUBSCRIBE_FROM_READ_BY = 'realtime/UNSUBSCRIBE_FROM_READ_BY' export function setupFaye() { return async (dispatch, getState) => { - console.warn('RECONNECT TO FAYE') + console.log('RECONNECT TO FAYE') FayeGitter.setAccessToken(getState().auth.token) FayeGitter.create() FayeGitter.logger() try { const result = await FayeGitter.connect() dispatch({type: FAYE_CONNECT, payload: result}) - console.warn('CONNECTED') - dispatch(subscribeToRooms()) + // dispatch(subscribeToChannels()) } catch (err) { console.log(err) // eslint-disable-line no-console } @@ -44,8 +46,9 @@ export function setupFaye() { export function checkFayeConnection() { return async (dispatch, getState) => { try { - const {fayeConnected} = getState().realtime - if (!fayeConnected) { + const connectionStatus = await FayeGitter.checkConnectionStatus() + console.log('CONNECTION_STATUS', connectionStatus) + if (!connectionStatus) { await dispatch(setupFaye()) } } catch (error) { @@ -61,11 +64,12 @@ export function checkFayeConnection() { export function onNetStatusChangeFaye(status) { return async (dispatch, getState) => { const {fayeConnected} = getState().app - if (!status && fayeConnected) { + const connectionStatus = await FayeGitter.checkConnectionStatus() + if (!status && connectionStatus) { dispatch({type: FAYE_CONNECT, payload: status}) } try { - if (status && !fayeConnected) { + if (status && !connectionStatus) { await dispatch(setupFaye()) } } catch (error) { @@ -80,17 +84,22 @@ export function onNetStatusChangeFaye(status) { export function setupFayeEvents() { return (dispatch, getState) => { + DeviceEventEmitter + .addListener('FayeGitter:Connected', log => { + console.log('CONNECTED') + dispatch(subscribeToChannels()) + }) DeviceEventEmitter .addListener('FayeGitter:onDisconnected', log => { - console.warn(log) // eslint-disable-line no-console + console.log(log) // eslint-disable-line no-console dispatch(setupFaye()) }) DeviceEventEmitter .addListener('FayeGitter:onFailedToCreate', log => { - console.warn(log) // eslint-disable-line no-console - const {netStatus} = getState().app - if (netStatus === true) { + console.log(log) // eslint-disable-line no-console + const {online} = getState().app + if (online === true) { dispatch(setupFaye()) } }) @@ -103,16 +112,17 @@ export function setupFayeEvents() { dispatch(parseSnapshotEvent(event)) }) DeviceEventEmitter - .addListener('FayeGitter:SubscribtionFailed', log => console.warn(log)) // eslint-disable-line no-console + .addListener('FayeGitter:SubscribtionFailed', log => console.log(log)) // eslint-disable-line no-console DeviceEventEmitter - .addListener('FayeGitter:Subscribed', log => console.warn('SUBSCRIBED', log)) // eslint-disable-line no-console + .addListener('FayeGitter:Subscribed', log => console.log('SUBSCRIBED', log)) // eslint-disable-line no-console DeviceEventEmitter - .addListener('FayeGitter:Unsubscribed', log => console.warn('UNSUBSCRIBED', log)) // eslint-disable-line no-console + .addListener('FayeGitter:Unsubscribed', log => console.log('UNSUBSCRIBED', log)) // eslint-disable-line no-console } } export function removeFayeEvents() { return (dispatch) => { + DeviceEventEmitter.removeEventListener('FayeGitter:Connected') DeviceEventEmitter.removeEventListener('FayeGitter:onDisconnected') DeviceEventEmitter.removeEventListener('FayeGitter:onFailedToCreate') DeviceEventEmitter.removeEventListener('FayeGitter:Message') @@ -204,8 +214,10 @@ export function subscribeToRooms() { return async (dispatch, getState) => { await checkFayeConnection() const {id} = getState().viewer.user - FayeGitter.subscribe(`/api/v1/user/${id}/rooms`) + const subscription = `/api/v1/user/${id}/rooms` + FayeGitter.subscribe(subscription) dispatch({type: ROOMS_SUBSCRIBED}) + dispatch(pushSubscription(subscription)) } } @@ -216,8 +228,10 @@ export function subscribeToRooms() { export function subscribeToChatMessages(roomId) { return async dispatch => { await checkFayeConnection() - FayeGitter.subscribe(`/api/v1/rooms/${roomId}/chatMessages`) + const subscription = `/api/v1/rooms/${roomId}/chatMessages` + FayeGitter.subscribe(subscription) dispatch({type: SUBSCRIBE_TO_CHAT_MESSAGES, roomId}) + dispatch(pushSubscription(subscription)) } } @@ -228,8 +242,10 @@ export function subscribeToChatMessages(roomId) { export function unsubscribeToChatMessages(roomId) { return async (dispatch) => { await checkFayeConnection() - FayeGitter.unsubscribe(`/api/v1/rooms/${roomId}/chatMessages`) + const subscription = `/api/v1/rooms/${roomId}/chatMessages` + FayeGitter.unsubscribe(subscription) dispatch({type: UNSUBSCRIBE_TO_CHAT_MESSAGES, roomId}) + dispatch(deleteSubscription(subscription)) } } @@ -237,8 +253,10 @@ export function unsubscribeToChatMessages(roomId) { export function subscribeToRoomEvents(roomId) { return async dispatch => { await checkFayeConnection() - FayeGitter.subscribe(`/api/v1/rooms/${roomId}/events`) + const subscription = `/api/v1/rooms/${roomId}/events` + FayeGitter.subscribe(subscription) dispatch({type: SUBSCRIBE_TO_ROOM_EVENTS, roomId}) + dispatch(pushSubscription(subscription)) } } @@ -248,17 +266,21 @@ export function subscribeToRoomEvents(roomId) { export function unsubscribeToRoomEvents(roomId) { return async (dispatch) => { - await checkFayeConnection - FayeGitter.unsubscribe(`/api/v1/rooms/${roomId}/events`) + await checkFayeConnection() + const subscription = `/api/v1/rooms/${roomId}/events` + FayeGitter.unsubscribe(subscription) dispatch({type: UNSUBSCRIBE_TO_ROOM_EVENTS, roomId}) + dispatch(deleteSubscription(subscription)) } } export function subscribeToReadBy(roomId, messageId) { return async dispatch => { await checkFayeConnection() - FayeGitter.subscribe(`/api/v1/rooms/${roomId}/chatMessages/${messageId}/readBy`) + const subscription = `/api/v1/rooms/${roomId}/chatMessages/${messageId}/readBy` + FayeGitter.subscribe(subscription) dispatch({type: SUBSCRIBE_TO_READ_BY, roomId}) + dispatch(pushSubscription(subscription)) } } @@ -269,8 +291,42 @@ export function subscribeToReadBy(roomId, messageId) { export function unsubscribeFromReadBy(roomId, messageId) { return async (dispatch) => { await checkFayeConnection() - FayeGitter.unsubscribe(`/api/v1/rooms/${roomId}/chatMessages/${messageId}/readBy`) + const subscription = `/api/v1/rooms/${roomId}/chatMessages/${messageId}/readBy` + FayeGitter.unsubscribe(subscription) dispatch({type: UNSUBSCRIBE_FROM_READ_BY, roomId}) + dispatch(deleteSubscription(subscription)) + } +} + +export function pushSubscription(subscription) { + return (dispatch, getState) => { + const {subscriptions} = getState().realtime + if (!subscriptions.find(item => item === subscription)) { + dispatch({type: PUSH_SUBSCRIPTION, subscription}) + console.log('PUSH_SUBSCRIPTION', subscription) + } + } +} + +export function deleteSubscription(subscription) { + return (dispatch, getState) => { + const {subscriptions} = getState().realtime + if (!!subscriptions.find(item => item === subscription)) { + dispatch({type: DELETE_SUBSCRIPTION, subscription}) + console.log('DELETE_SUBSCRIPTION', subscription) + } + } +} + +export function subscribeToChannels() { + return (dispatch, getState) => { + const {subscriptions} = getState().realtime + if (subscriptions.length === 0) { + dispatch(subscribeToRooms()) + } else { + subscriptions.forEach(subscription => FayeGitter.subscribe(subscription)) + dispatch({type: SUBSCRIBED_TO_CHANNELS, subscriptions}) + } } } @@ -281,7 +337,8 @@ export function unsubscribeFromReadBy(roomId, messageId) { const initialState = { fayeConnected: false, roomsSubscribed: false, - roomMessagesSubscription: '' + roomMessagesSubscription: '', + subscriptions: [] } export default function realtime(state = initialState, action) { @@ -302,6 +359,16 @@ export default function realtime(state = initialState, action) { roomMessagesSubscription: action.payload } + case PUSH_SUBSCRIPTION: + return {...state, + subscriptions: state.subscriptions.concat(action.subscription) + } + + case DELETE_SUBSCRIPTION: + return {...state, + subscriptions: state.subscriptions.filter(subscription => action.subscription !== subscription) + } + default: return state } diff --git a/app/screens/RoomInfoScreen.js b/app/screens/RoomInfoScreen.js index 10571ce..6a7dcb3 100644 --- a/app/screens/RoomInfoScreen.js +++ b/app/screens/RoomInfoScreen.js @@ -56,6 +56,7 @@ class RoomInfoScreen extends Component { componentWillUnmount() { const {dispatch, route: {roomId}} = this.props dispatch(unsubscribeToRoomEvents(roomId)) + console.warn('UNMOUNTED') } handleUserPress(userId, username) { diff --git a/app/screens/RoomScreen.js b/app/screens/RoomScreen.js index e7d47af..325e124 100644 --- a/app/screens/RoomScreen.js +++ b/app/screens/RoomScreen.js @@ -32,6 +32,9 @@ import { clearError as clearMessagesError, readMessages } from '../modules/messages' +import { + unsubscribeToChatMessages +} from '../modules/realtime' import {changeRoomInfoDrawerState} from '../modules/ui' import * as Navigation from '../modules/navigation' @@ -102,6 +105,11 @@ class Room extends Component { }) } + componentWillUnmount() { + const {dispatch, route: {roomId}} = this.props + // dispatch(unsubscribeToChatMessages(roomId)) + } + onEndReached() { const {dispatch, route: {roomId}, hasNoMore, isLoadingMore, isLoadingMessages, listViewData} = this.props if (hasNoMore[roomId] !== true && isLoadingMore === false @@ -359,8 +367,6 @@ class Room extends Component { handleChangeVisibleRows(visibleRows, changedRows) { const {dispatch, route: {roomId}} = this.props - console.log('VISIBLE', visibleRows) - console.log('CHANGED', changedRows) this.readMessages = Object.assign({}, this.readMessages, changedRows.s1) diff --git a/libs/react-native-gitter-faye/src/main/java/com/terrysahaidak/faye/FayeGitterModule.java b/libs/react-native-gitter-faye/src/main/java/com/terrysahaidak/faye/FayeGitterModule.java index c28877b..57462a9 100644 --- a/libs/react-native-gitter-faye/src/main/java/com/terrysahaidak/faye/FayeGitterModule.java +++ b/libs/react-native-gitter-faye/src/main/java/com/terrysahaidak/faye/FayeGitterModule.java @@ -18,6 +18,7 @@ public class FayeGitterModule extends ReactContextBaseJavaModule { private static String accessToken; private static AsyncGitterFayeClient client; + private static Boolean connectStatus = false; public FayeGitterModule(ReactApplicationContext reactContext) { super(reactContext); @@ -57,12 +58,14 @@ public void create() { @Override public void onDisconnected() { sendEvent("FayeGitter:onDisconnected", "Disconected"); + connectStatus = false; } }, new FailListener() { @Override public void onFailed(Exception ex) { sendEvent("FayeGitter:onFailedToCreate", "Failed to create client: " + ex.getMessage()); + connectStatus = false; } } ); @@ -74,53 +77,60 @@ public void connect(final Promise promise) { @Override public void onConnected() { promise.resolve(true); + connectStatus = true; + sendEvent("FayeGitter:Connected", "CONNECTED"); } }); } @ReactMethod public void subscribe(String channelName) { - this.client.subscribe(channelName, new ChannelListener() { - @Override - public void onMessage(String channel, JsonObject message) { - System.out.println(message); - WritableMap params = new WritableNativeMap(); - params.putString("channel", channel); - params.putString("json", message.toString()); - sendEvent("FayeGitter:Message", params); - } + if (connectStatus) { + this.client.subscribe(channelName, new ChannelListener() { + @Override + public void onMessage(String channel, JsonObject message) { + System.out.println(message); + WritableMap params = new WritableNativeMap(); + params.putString("channel", channel); + params.putString("json", message.toString()); + sendEvent("FayeGitter:Message", params); + } - @Override - public void onFailed(String channel, Exception ex) { - WritableMap params = new WritableNativeMap(); - params.putString("channel", channel); - params.putString("Exception", ex.getMessage()); - sendEvent("FayeGitter:SubscribtionFailed", params); - } - @Override - public void onSubscribed(String channel) { - WritableMap params = new WritableNativeMap(); - params.putString("channel", channel); - sendEvent("FayeGitter:Subscribed", params); - } + @Override + public void onFailed(String channel, Exception ex) { + WritableMap params = new WritableNativeMap(); + params.putString("channel", channel); + params.putString("Exception", ex.getMessage()); + sendEvent("FayeGitter:SubscribtionFailed", params); + } + @Override + public void onSubscribed(String channel) { + WritableMap params = new WritableNativeMap(); + params.putString("channel", channel); + sendEvent("FayeGitter:Subscribed", params); + } - @Override - public void onUnSubscribed(String channel) { - WritableMap params = new WritableNativeMap(); - params.putString("channel", channel); - sendEvent("FayeGitter:Unsubscribed", params); - } - }); + @Override + public void onUnSubscribed(String channel) { + WritableMap params = new WritableNativeMap(); + params.putString("channel", channel); + sendEvent("FayeGitter:Unsubscribed", params); + } + }); + } } @ReactMethod public void unsubscribe(String channel) { - this.client.unSubscribe(channel); + if (connectStatus) { + this.client.unSubscribe(channel); + } } @ReactMethod public void disconnect() { this.client.disconnect(); + connectStatus = false; } @ReactMethod @@ -135,4 +145,9 @@ public void log(String message) { } }); } + + @ReactMethod + public void checkConnectionStatus(Promise promise) { + promise.resolve(connectStatus); + } } From cadcf197a69f39b1a655ac532d2e1536a255a7e3 Mon Sep 17 00:00:00 2001 From: Terry Sahaidak Date: Sun, 9 Oct 2016 19:16:27 +0300 Subject: [PATCH 2/2] Fix reading messages --- app/modules/messages.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/app/modules/messages.js b/app/modules/messages.js index 50a0769..3f59b08 100644 --- a/app/modules/messages.js +++ b/app/modules/messages.js @@ -298,22 +298,20 @@ export function readMessages(roomId, changedRows) { .filter(rowId => (changedRows[rowId] === true)) .filter(rowId => (listView.data[rowId].unread === true)) - console.log('UNREAD', visibleAndUnread) - if (!visibleAndUnread.length) { return } dispatch({type: READ_MESSAGES, roomId, visibleAndUnread}) - // try { - // await Api.readMessages( - // token, id, roomId, visibleAndUnread.map(item => listView.data[item].id) - // ) - // dispatch({type: READ_MESSAGES_OK, roomId, visibleAndUnread}) - // } catch (error) { - // dispatch({type: READ_MESSAGES_ERROR, error: error.message, roomId, visibleAndUnread}) - // } + try { + await Api.readMessages( + token, id, roomId, visibleAndUnread.map(item => listView.data[item].id) + ) + dispatch({type: READ_MESSAGES_OK, roomId, visibleAndUnread}) + } catch (error) { + dispatch({type: READ_MESSAGES_ERROR, error: error.message, roomId, visibleAndUnread}) + } } }