Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: implement sessions #289

Closed
wants to merge 4 commits into from
Closed

lib: implement sessions #289

wants to merge 4 commits into from

Conversation

belochub
Copy link
Member

@belochub belochub commented Aug 1, 2017

Refs: #35

@belochub belochub added this to the 1.0.0 milestone Aug 1, 2017
@belochub belochub self-assigned this Aug 1, 2017
@belochub belochub force-pushed the session-implementation branch 5 times, most recently from 0baff95 to 837a13a Compare August 4, 2017 21:22
this._callbacks[messageId] = (error, sessionId) => {
if (!error) {
if (login && password) {
this.username = login;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any need in this field (I think it's enough to have it inside Session object)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, it's better to duplicate it because it doesn't use much more memory but at the same time helps to avoid long access to it, like connection.session.username.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though it indeed has virtually no cost, but I think that's overkill to copy it for that, you can always cache it before or use sort of accessor function to get it if you want to avoid long access.

_send(message) {
const data = serde.stringify(message);
this.transport.send(data);
_send(preparedMessage, message) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we make 2 send methods _send(message) and _sendPrepared(preparedMessage) and always parse prepared message for debug mode events in the latter method with the former method only calling the latter one after preparing a message? This will avoid a lot of boilerplate code and only affect debug mode performance which is negligible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the idea of creating the function just for stringifying messages, the output of which will always be parsed just again while sending the message, that doesn't make sense to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'll only be parsed for debug messages which will not affect the production code. Also, it'll avoid passing both parsed and not parsed arguments to the _send function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will avoid passing both parsed and not parsed arguments to the _send method by parsing the stringified message every time, which, as I've already said, makes no sense to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's debug mode so it's fine for me, @metarhia/jstp-core?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am ok with both versions.

_send(message) {
const data = serde.stringify(message);
this.transport.send(data);
_send(preparedMessage, message) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I propose to avoid manual calling of session._bufferMessage method and instead add a boolean flag into the proposed above _sendPrepared method which will also remove some of the boilerplate code?

@@ -47,22 +49,25 @@ const newConnectFn = (
client.application = new Application('jstp', {});
}
if (!client.connectPolicy) {
client.connectPolicy = new SimpleConnectPolicy().connect;
client.connectPolicy = new SimpleConnectPolicy(client.session).connect;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the use of the client.session parameter in SimpleConnectPolicy, ain't it better to just omit the parameters?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to change this line, thanks.

lib/session.js Outdated
constructor(connection, sessionId) {
super();

this._isServer = !sessionId;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just use Math.abs below? IMO it'll be cleaner.

lib/server.js Outdated

this.clients = new Map();

this.sessions = sessionStorageProvider || new SimpleSessionStorageProvider();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe sessionsProvider?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about sessionsStorage?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

lib/server.js Outdated
connection, application, strategy, credentials,
(error, username) => {
if (error || !username) {
callback(errors.ERR_AUTH_FAILED);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe allow user to pass their own error codes? (like check if error.code and if it doesn't exist only then pass default errors.ERR_AUTH_FAILED?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this has nothing to do with this PR, I didn't change this behavior.
But if you want, you can open another PR with this functionality after this one will be landed.

@@ -200,7 +230,9 @@ class Connection extends EventEmitter {
}
};

this._send(message);
const preparedMessage = this._prepareMessage(message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern seems to repeat a lot. Is it worth to decouple these three lines into a method?

lib/server.js Outdated
callback(null, username, session);
};

if (strategy !== 'anonymous') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, you could invert this condition like so:

if (strategy === 'anonymous') {
  createSession();
  return;
}

and then reduce the level of indentation for all the rest of the function.

Not a nit though, I don't feel strongly for either way.

@nechaido nechaido closed this Nov 24, 2017
@nechaido nechaido reopened this Nov 24, 2017
@nechaido
Copy link
Member

@belochub please rebase on master.

@belochub belochub force-pushed the session-implementation branch 2 times, most recently from 5553934 to 38eb903 Compare November 27, 2017 18:34
@belochub
Copy link
Member Author

@nechaido, done.

Copy link
Member

@aqrln aqrln left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a final review, I'll look through the rest of the code today.

@@ -18,16 +18,24 @@ const errors = require('./errors');
// has the following signature
// (connection, <0 or more event arguments>)
// version - application version of 'name' application (optional)
// sessionStorageProvider - provider for session storage (optional).
// If provided will be used to store sessions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like the subject is missing in this sentence. How about "If provided, it will..."?

//
class Application {
constructor(name, api, eventHandlers = {}, version) {
constructor(name, api, eventHandlers = {}, version, sessionStorageProvider) {
if (typeof version === 'object') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say something like if (sessionStorageProvider === undefined && typeof version === 'object') would be more robust.

FWIW, I'm not entirely happy with the very idea of omitting some arguments in the middle of the signature, but we already have such APIs in the library which I introduced myself in the past anyway, so ¯\_(ツ)_/¯

@@ -145,32 +143,56 @@ class Connection extends EventEmitter {
}

let message;
let isNewSession = true;
const handshakePayload = new Array(2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the whole purpose of this array is to eventually unpack it using spread operator, I'd actually find it more readable to use just two named variables (e.g., handshakeStrategy and handshakeCredentials).


if (process.env.NODE_ENV !== 'production') {
this.emit('outgoingMessage', message);
this.emit('outgoingMessage', message || serde.parse(preparedMessage));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serde.parse() is used directly here, but serde.stringify() is abstracted away into _prepareMessage(), which is a bit inconsistent.

lib/server.js Outdated
const createSession = (username) => {
const session = new Session(connection);
if (username) {
session.username = username;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd move it to the constructor.

lib/server.js Outdated
@@ -80,6 +81,78 @@ class Server {
});
}

startSession(connection, application, strategy, credentials, callback) {
const createSession = (username) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd extract it to a private function that takes (connection, application, strategy, callback) as arguments.

this.username = login;
}
this.session = new Session(this, sessionId);
this.session.username = this.username;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but maybe it'll be better to make Session's constructor get username from the connection parameter instead of assigning it here manually?

@nechaido
Copy link
Member

@aqrln ping.

@belochub belochub removed the request for review from aqrln January 19, 2018 14:47
belochub and others added 4 commits January 19, 2018 17:20
* Send Ping-Pong instead of Heartbeat messages.
* Use setInterval() instead of timers.enroll().
* Rewrite tests.

Fixes: #217
PR-URL: #303
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
belochub added a commit that referenced this pull request Jan 20, 2018
PR-URL: #289
Reviewed-By: Dmytro Nechai <nechaido@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
belochub pushed a commit that referenced this pull request Jan 20, 2018
PR-URL: #289
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
belochub pushed a commit that referenced this pull request Jan 20, 2018
PR-URL: #289
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
@belochub
Copy link
Member Author

belochub commented Jan 20, 2018

Landed in 4d600f4, fb8915c, f9b888c, and
8a0bc8b. 🎉.

@belochub belochub closed this Jan 20, 2018
belochub added a commit that referenced this pull request Jan 22, 2018
PR-URL: #289
Reviewed-By: Dmytro Nechai <nechaido@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
belochub pushed a commit that referenced this pull request Jan 22, 2018
PR-URL: #289
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
belochub pushed a commit that referenced this pull request Jan 22, 2018
PR-URL: #289
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
belochub added a commit that referenced this pull request Jan 22, 2018
PR-URL: #289
Reviewed-By: Dmytro Nechai <nechaido@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
belochub pushed a commit that referenced this pull request Jan 22, 2018
PR-URL: #289
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
belochub pushed a commit that referenced this pull request Jan 22, 2018
PR-URL: #289
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
belochub added a commit that referenced this pull request Jan 22, 2018
This is a new and shiny first major release for `metarhia-jstp`.
Changes include API refactoring and improvements, implementations of
CLI, sessions, and application versions, native addon build optimizations,
lots of bug fixes, test coverage increase, and other, less notable changes.

This release also denotes the bump of the protocol version to v1.0.
The only difference from the previous version of the protocol is that
"old" heartbeat messages (`{}`) are now deprecated and `ping`/`pong`
messages must be used for this purpose instead.

Notable changes:

 * **src,build:** improve the native module subsystem
   *(Alexey Orlenko)*
   [#36](#36)
   **\[semver-minor\]**
 * **build:** compile in ISO C++11 mode
   *(Alexey Orlenko)*
   [#37](#37)
   **\[semver-minor\]**
 * **build:** improve error handling
   *(Alexey Orlenko)*
   [#40](#40)
   **\[semver-minor\]**
 * **lib:** refactor record-serialization.js
   *(Alexey Orlenko)*
   [#41](#41)
   **\[semver-minor\]**
 * **protocol:** change the format of handshake packets
   *(Alexey Orlenko)*
   [#54](#54)
   **\[semver-major\]**
 * **parser:** remove special case for '\0' literal
   *(Mykola Bilochub)*
   [#68](#68)
   **\[semver-major\]**
 * **client:** drop redundant callback argument
   *(Alexey Orlenko)*
   [#104](#104)
   **\[semver-major\]**
 * **client:** handle errors in connectAndInspect
   *(Alexey Orlenko)*
   [#105](#105)
   **\[semver-major\]**
 * **socket,ws:** use socket.destroy() properly
   *(Alexey Orlenko)*
   [#84](#84)
   **\[semver-major\]**
 * **cli:** add basic implementation
   *(Mykola Bilochub)*
   [#107](#107)
   **\[semver-minor\]**
 * **connection:** fix error handling in optional cbs
   *(Alexey Orlenko)*
   [#147](#147)
   **\[semver-major\]**
 * **lib:** change event signature
   *(Denys Otrishko)*
   [#187](#187)
   **\[semver-major\]**
 * **lib:** add address method to Server
   *(Denys Otrishko)*
   [#190](#190)
   **\[semver-minor\]**
 * **lib:** optimize connection events
   *(Denys Otrishko)*
   [#222](#222)
   **\[semver-major\]**
 * **lib:** refactor server and client API
   *(Denys Otrishko)*
   [#209](#209)
   **\[semver-major\]**
 * **lib,src:** rename term packet usages to message
   *(Denys Otrishko)*
   [#270](#270)
   **\[semver-major\]**
 * **lib:** emit events about connection messages
   *(Denys Otrishko)*
   [#252](#252)
   **\[semver-minor\]**
 * **connection:** make callback method private
   *(Alexey Orlenko)*
   [#306](#306)
   **\[semver-major\]**
 * **lib:** implement sessions
   *(Mykola Bilochub)*
   [#289](#289)
   **\[semver-major\]**
 * **connection:** use ping-pong instead of heartbeat
   *(Dmytro Nechai)*
   [#303](#303)
   **\[semver-major\]**
@belochub belochub mentioned this pull request Jan 22, 2018
belochub added a commit that referenced this pull request Jan 23, 2018
This is a new and shiny first major release for `metarhia-jstp`.
Changes include API refactoring and improvements, implementations of
CLI, sessions, and application versions, native addon build optimizations,
lots of bug fixes, test coverage increase, and other, less notable changes.

This release also denotes the bump of the protocol version to v1.0.
The only difference from the previous version of the protocol is that
"old" heartbeat messages (`{}`) are now deprecated and `ping`/`pong`
messages must be used for this purpose instead.

Notable changes:

 * **src,build:** improve the native module subsystem
   *(Alexey Orlenko)*
   [#36](#36)
   **\[semver-minor\]**
 * **build:** compile in ISO C++11 mode
   *(Alexey Orlenko)*
   [#37](#37)
   **\[semver-minor\]**
 * **build:** improve error handling
   *(Alexey Orlenko)*
   [#40](#40)
   **\[semver-minor\]**
 * **lib:** refactor record-serialization.js
   *(Alexey Orlenko)*
   [#41](#41)
 * **parser:** fix a possible memory leak
   *(Alexey Orlenko)*
   [#44](#44)
   **\[semver-minor\]**
 * **protocol:** change the format of handshake packets
   *(Alexey Orlenko)*
   [#54](#54)
   **\[semver-major\]**
 * **parser:** make parser single-pass
   *(Mykola Bilochub)*
   [#61](#61)
 * **parser:** remove special case for '\0' literal
   *(Mykola Bilochub)*
   [#68](#68)
   **\[semver-major\]**
 * **parser:** fix bug causing node to crash
   *(Mykola Bilochub)*
   [#75](#75)
 * **client:** drop redundant callback argument
   *(Alexey Orlenko)*
   [#104](#104)
   **\[semver-major\]**
 * **client:** handle errors in connectAndInspect
   *(Alexey Orlenko)*
   [#105](#105)
   **\[semver-major\]**
 * **socket,ws:** use socket.destroy() properly
   *(Alexey Orlenko)*
   [#84](#84)
   **\[semver-major\]**
 * **cli:** add basic implementation
   *(Mykola Bilochub)*
   [#107](#107)
   **\[semver-minor\]**
 * **connection:** fix error handling in optional cbs
   *(Alexey Orlenko)*
   [#147](#147)
   **\[semver-major\]**
 * **test:** add JSON5 specs test suite
   *(Alexey Orlenko)*
   [#158](#158)
 * **lib:** change event signature
   *(Denys Otrishko)*
   [#187](#187)
   **\[semver-major\]**
 * **lib:** add address method to Server
   *(Denys Otrishko)*
   [#190](#190)
   **\[semver-minor\]**
 * **parser:** implement NaN and Infinity parsing
   *(Mykola Bilochub)*
   [#201](#201)
 * **parser:** improve string parsing performance
   *(Mykola Bilochub)*
   [#220](#220)
 * **lib:** optimize connection events
   *(Denys Otrishko)*
   [#222](#222)
   **\[semver-major\]**
 * **lib:** refactor server and client API
   *(Denys Otrishko)*
   [#209](#209)
   **\[semver-major\]**
 * **lib,src:** rename term packet usages to message
   *(Denys Otrishko)*
   [#270](#270)
   **\[semver-major\]**
 * **lib:** emit events about connection messages
   *(Denys Otrishko)*
   [#252](#252)
   **\[semver-minor\]**
 * **lib:** implement API versioning
   *(Denys Otrishko)*
   [#231](#231)
   **\[semver-minor\]**
 * **lib:** allow to set event handlers in application
   *(Denys Otrishko)*
   [#286](#286)
   **\[semver-minor\]**
 * **lib:** allow to broadcast events from server
   *(Denys Otrishko)*
   [#287](#287)
   **\[semver-minor\]**
 * **connection:** make callback method private
   *(Alexey Orlenko)*
   [#306](#306)
   **\[semver-major\]**
 * **lib:** implement sessions
   *(Mykola Bilochub)*
   [#289](#289)
   **\[semver-major\]**
 * **connection:** use ping-pong instead of heartbeat
   *(Dmytro Nechai)*
   [#303](#303)
   **\[semver-major\]**
@belochub belochub deleted the session-implementation branch January 24, 2018 16:44
belochub added a commit to metarhia/mdsf that referenced this pull request Jul 19, 2018
PR-URL: metarhia/jstp#289
Reviewed-By: Dmytro Nechai <nechaido@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
belochub added a commit to metarhia/mdsf that referenced this pull request Jul 19, 2018
PR-URL: metarhia/jstp#289
Reviewed-By: Dmytro Nechai <nechaido@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants