Skip to content

Commit

Permalink
Update logic so that hereNow sets enough state for each user (pubnub#347
Browse files Browse the repository at this point in the history
)

* update logic so that hereNow sets enough state for each user

* state tests

* test of offline sender state

* linting

* patch for tests

* prevent test success from multiple dones

* fix linting

* don't connect until my own state is set

* more reliable state setting

* reorder bootstrap to satisfy module order

* linting
  • Loading branch information
ianjennings committed Apr 12, 2018
1 parent b9c1d76 commit 4305410
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 45 deletions.
52 changes: 31 additions & 21 deletions src/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const RootEmitter = require('./modules/root_emitter');
const Chat = require('./components/chat');
const Me = require('./components/me');
const User = require('./components/user');
const series = require('async/series');
const waterfall = require('async/waterfall');

/**
@class ChatEngine
Expand Down Expand Up @@ -199,7 +199,7 @@ module.exports = (ceConfig = {}, pnConfig = {}) => {
*/
ChatEngine.handshake = (complete) => {

series([
waterfall([
(next) => {
ChatEngine.request('post', 'bootstrap').then(() => {
next(null);
Expand All @@ -216,12 +216,18 @@ module.exports = (ceConfig = {}, pnConfig = {}) => {
}).catch(next);
},
(next) => {
ChatEngine.request('post', 'group').then(complete).catch(next);
ChatEngine.request('post', 'group').then(() => {
next();
}).catch(next);
}
], (error) => {

if (error) {
ChatEngine.throwError(ChatEngine, '_emit', 'auth', new Error('There was a problem logging into the auth server (' + ceConfig.endpoint + ').' + error && error.response && error.response.data), { error });
} else {
complete();
}

});

};
Expand Down Expand Up @@ -373,30 +379,34 @@ module.exports = (ceConfig = {}, pnConfig = {}) => {

if (ChatEngine.ceConfig.enableSync) {
ChatEngine.me.session.subscribe();
ChatEngine.me.session.restore();
}

ChatEngine.me.update(state);
ChatEngine.me.update(state, () => {

/**
* Fired when ChatEngine is connected to the internet and ready to go!
* @event ChatEngine#$"."ready
* @example
* ChatEngine.on('$.ready', (data) => {
* let me = data.me;
* })
*/

ChatEngine._emit('$.ready', {
me: ChatEngine.me
});
/**
* Fired when ChatEngine is connected to the internet and ready to go!
* @event ChatEngine#$"."ready
* @example
* ChatEngine.on('$.ready', (data) => {
* let me = data.me;
* })
*/
ChatEngine._emit('$.ready', {
me: ChatEngine.me
});

ChatEngine.ready = true;
ChatEngine.ready = true;

ChatEngine.listenToPubNub();
ChatEngine.subscribeToPubNub();
ChatEngine.listenToPubNub();
ChatEngine.subscribeToPubNub();

ChatEngine.global.getUserUpdates();

ChatEngine.global.getUserUpdates();
if (ChatEngine.ceConfig.enableSync) {
ChatEngine.me.session.restore();
}

});

});

Expand Down
19 changes: 11 additions & 8 deletions src/components/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -567,10 +567,8 @@ class Chat extends Emitter {
@private
@param {Object} state The new state {@link Me} will have within this {@link User}
*/
setState(state) {
this.chatEngine.pubnub.setState({ state, channels: [this.chatEngine.global.channel] }, () => {
// handle status, response
});
setState(state, callback) {
this.chatEngine.pubnub.setState({ state, channels: [this.chatEngine.global.channel] }, callback);
}

/**
Expand Down Expand Up @@ -696,7 +694,7 @@ class Chat extends Emitter {
* // connect to the chat when we feel like it
* chat.connect();
*/
handshake(callback) {
handshake(complete) {

waterfall([
(next) => {
Expand Down Expand Up @@ -739,18 +737,23 @@ class Chat extends Emitter {
this.update(this.meta);
}

callback();
next();

})
.catch(next);

} else {
callback();
next();
}

}
], (error) => {
this.chatEngine.throwError(this, 'trigger', 'auth', new Error('Something went wrong while making a request to authentication server.'), { error });

if (error) {
this.chatEngine.throwError(this, 'trigger', 'auth', new Error('Something went wrong while making a request to authentication server.'), { error });
} else {
complete();
}
});

}
Expand Down
4 changes: 2 additions & 2 deletions src/components/me.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ class Me extends User {
* // update state
* me.update({value: true});
*/
update(state) {
update(state, callback = () => {}) {

// run the root update function
super.update(state);

// publish the update over the global channel
this.chatEngine.global.setState(state);
this.chatEngine.global.setState(state, callback);

}

Expand Down
23 changes: 12 additions & 11 deletions src/components/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,9 @@ class User extends Emitter {
* // State
* let state = user.state;
*/
this.state = {};
this.state = state;

this._stateFetched = false;

this._stateInProgress = false;
this._stateSet = false;

/**
* Feed is a Chat that only streams things a User does, like
Expand Down Expand Up @@ -88,8 +86,10 @@ class User extends Emitter {
chatEngine.users[uuid] = this;
}

// update this user's state in it's created context
this.assign(state);
if (Object.keys(state).length) {
// update this user's state in it's created context
this.assign(state);
}

return this;

Expand All @@ -98,11 +98,14 @@ class User extends Emitter {
/**
* @private
* @param {Object} state The new state for the user
* @param {Chat} chat Chatroom to retrieve state from
*/
update(state) {

let oldState = this.state || {};
this.state = Object.assign(oldState, state);

this._stateSet = true;

}

/**
Expand All @@ -118,17 +121,15 @@ class User extends Emitter {
Get stored user state from remote server.
@private
*/
_getState(callback) {
_getStoredState(callback) {

if (!this._stateFetched) {
if (!this._stateSet) {

this.chatEngine.request('get', 'user_state', {
user: this.uuid
}).then((res) => {

this.assign(res.data);
this._stateFetched = true;

callback(this.state);

}).catch((err) => {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/emitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class Emitter extends RootEmitter {
// the user doesn't exist, create it
payload.sender = new this.chatEngine.User(payload.sender);

payload.sender._getState(() => {
payload.sender._getStoredState(() => {
complete();
});

Expand Down
54 changes: 52 additions & 2 deletions test/integration/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ function createChatEngineHistory(done) {
publishKey: pubkey,
subscribeKey: subkey
}, {
globalChannel: 'global',
globalChannel: 'g',
throwErrors: true
});
ChatEngineHistory.connect(yousername, { works: true }, yousername);
Expand Down Expand Up @@ -407,6 +407,7 @@ describe('history', () => {
limit: 50
}).on('tester', (a) => {

assert.equal(a.sender.state.works, true);
assert(a.timetoken);
assert.equal(a.event, 'tester');

Expand Down Expand Up @@ -585,7 +586,7 @@ describe('remote chat list', () => {
beforeEach(createChatEngineClone);
beforeEach(createChatEngineSync);

it('should be get notified of new chats', function getNotifiedOfNewChats(done) {
it('should be notified of new chats', function getNotifiedOfNewChats(done) {

let newChannel = 'sync-chat' + new Date().getTime();

Expand Down Expand Up @@ -705,6 +706,55 @@ describe('invite', () => {

});

describe('state', () => {

beforeEach(reset);
beforeEach(createChatEngine);
beforeEach(createChatEngineYou);

it('should get previously set state', function shouldGetState(done) {

this.timeout(20000);

let doneCalled = false;

ChatEngine.on('$.online.*', (payload) => {

if (payload.user.uuid === ChatEngineYou.me.uuid && !doneCalled) {

assert.equal(payload.user.state.works, true);
doneCalled = true;
done();
}

});

});

it('should get state update', function shouldGetStateUpdate(done) {

this.timeout(20000);

let doneCalled = false;

ChatEngine.on('$.state', (payload) => {

if (payload.user.uuid === ChatEngineYou.me.uuid && !doneCalled) {

if (payload.user.state.newParam && payload.user.state.newParam === true && !doneCalled) {
doneCalled = true;
done();
}
}

});

ChatEngineYou.me.update({ newParam: true });

});

});

describe('memory', () => {

beforeEach(reset);
Expand Down

0 comments on commit 4305410

Please sign in to comment.