-
Notifications
You must be signed in to change notification settings - Fork 10
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
Conversation
0baff95
to
837a13a
Compare
this._callbacks[messageId] = (error, sessionId) => { | ||
if (!error) { | ||
if (login && password) { | ||
this.username = login; |
There was a problem hiding this comment.
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)?
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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?
lib/transport-common.js
Outdated
@@ -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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe sessionsProvider
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about sessionsStorage
?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
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.
lib/connection.js
Outdated
@@ -200,7 +230,9 @@ class Connection extends EventEmitter { | |||
} | |||
}; | |||
|
|||
this._send(message); | |||
const preparedMessage = this._prepareMessage(message); |
There was a problem hiding this comment.
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') { |
There was a problem hiding this comment.
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.
@belochub please rebase on master. |
5553934
to
38eb903
Compare
@nechaido, done. |
There was a problem hiding this 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.
lib/applications.js
Outdated
@@ -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 |
There was a problem hiding this comment.
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..."?
lib/applications.js
Outdated
// | ||
class Application { | ||
constructor(name, api, eventHandlers = {}, version) { | ||
constructor(name, api, eventHandlers = {}, version, sessionStorageProvider) { | ||
if (typeof version === 'object') { |
There was a problem hiding this comment.
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 ¯\_(ツ)_/¯
lib/connection.js
Outdated
@@ -145,32 +143,56 @@ class Connection extends EventEmitter { | |||
} | |||
|
|||
let message; | |||
let isNewSession = true; | |||
const handshakePayload = new Array(2); |
There was a problem hiding this comment.
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
).
lib/connection.js
Outdated
|
||
if (process.env.NODE_ENV !== 'production') { | ||
this.emit('outgoingMessage', message); | ||
this.emit('outgoingMessage', message || serde.parse(preparedMessage)); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) => { |
There was a problem hiding this comment.
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.
lib/connection.js
Outdated
this.username = login; | ||
} | ||
this.session = new Session(this, sessionId); | ||
this.session.username = this.username; |
There was a problem hiding this comment.
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?
60cad7f
to
1652fe5
Compare
@aqrln ping. |
1652fe5
to
141bede
Compare
PR-URL: #289 Reviewed-By: Dmytro Nechai <nechaido@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
PR-URL: #289 Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
PR-URL: #289 Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
PR-URL: #289 Reviewed-By: Dmytro Nechai <nechaido@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
PR-URL: #289 Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
PR-URL: #289 Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
PR-URL: #289 Reviewed-By: Dmytro Nechai <nechaido@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
PR-URL: #289 Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
PR-URL: #289 Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Mykola Bilochub <nbelochub@gmail.com>
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\]**
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\]**
PR-URL: metarhia/jstp#289 Reviewed-By: Dmytro Nechai <nechaido@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
PR-URL: metarhia/jstp#289 Reviewed-By: Dmytro Nechai <nechaido@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Refs: #35