-
Notifications
You must be signed in to change notification settings - Fork 53
Introduce "shared" sessions #139
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
Introduce "shared" sessions #139
Conversation
9b89fe4
to
1d8f708
Compare
The benchmark was run before and after adding "shared" sessions. Master:
With "shared" sessions:
In most cases, we have a loss of performance ~ 5 - 20%. |
1d8f708
to
d0b2b21
Compare
After refactoring. Master:
With "shared" sessions:
|
d0b2b21
to
c94c30b
Compare
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.
Thanks for your patch. Consider several comments below. I'll give more detailed review a bit later.
Also I think we could push d8de8b9 out of order to simplify patchset and reduce diff.
9c8bf69
to
bf1faf5
Compare
@@ -7,7 +7,7 @@ local qc = require('queue.compat') | |||
local num_type = qc.num_type | |||
local str_type = qc.str_type | |||
|
|||
local session = box.session | |||
local connection = box.session |
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 looks as a 'connection' module that is a bit strange: we have no such server-side entity. How about defining a function to obtain a connection id, like so: local connection_id = box.session.id
? Not sure here.
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.
Additionally I use connection.on_disconnect()
queue/abstract/queue_session.lua
Outdated
|
||
-- methods | ||
local method = { | ||
get_uuid = get_uuid, |
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.
We usually omit get_
for getters. How about connection_uuid()
? It'll also more descriptive and more uniform if we'll rename remove_connection()
to connection_remove()
(so the connection_
will become a prefix).
What also disquets me a bit: there is no add_connection()
or connection_add()
, but there are get_uuid()
and identify()
. Maybe I'm too tired, but it looks hard to understand the difference between the two latter functions.
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.
Not connection
, session
.
I think this question will be best to discussed by voice.
queue/abstract/queue_session.lua
Outdated
on_session_remove = on_session_remove, | ||
remove_connection = remove_connection, | ||
set_settings = set_settings, | ||
session_grant = session_grant, |
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 gives the ability to magane sessions from given user, right? How about just grant()
?
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.
Accepted.
queue/abstract.lua
Outdated
@@ -640,6 +664,13 @@ local function build_stats(space) | |||
return stats | |||
end | |||
|
|||
--- identify the session. |
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 description is a bit confusing for me. I would say something like 'Associate a current connection with given session'.
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.
Accepted.
-- wakeup all waiters | ||
while true do | ||
waiter = box.space._queue_consumers.index.pk:min{id} | ||
local waiter = box.space._queue_consumers.index.pk:min{conn_id} |
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 to understand the idea: consumers are still identified by a connection id rather than queue session id? Can you explain, why it is different from identifying a task ownership?
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.
Several consumers can work in the same session with the same tasks. For example, one consumer can take
a task and another consumer (in the same session) can ack
this task.
README.md
Outdated
In the queue the session has a unique UUID and one session can have many | ||
connections. Also, the consumer can reconnect to the existing session during the |
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.
one session can have many connections
I would say 'many connections may share one logical session' or kinda. It is a thing of taste, feel free to ignore.
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.
Accepted.
README.md
Outdated
without parameters. | ||
To connect to the existing session, call the `queue.identify(session_uuid)` | ||
with the UUID of the session. | ||
In case of failure, an error will be thrown. |
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 curious: what kinds of failures may appear here?
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.
For example: Trying to use invalid format UUID, expired UUID.
README.md
Outdated
without parameters. | ||
To connect to the existing session, call the `queue.identify(session_uuid)` | ||
with the UUID of the session. | ||
In case of failure, an error will be thrown. |
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 would add an example for net.box to better describe the idea. I guess we can use on_connect net.box trigger to transparently overcome a reconnect.
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.
As I said earlier, the examples will be added after the feature will be pushed to master.
@@ -372,6 +373,20 @@ Available `options`: | |||
* `ttr` - time to release in seconds. The time after which, if there is no active | |||
connection in the session, it will be released with all its tasks. | |||
|
|||
## Session identify | |||
|
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 would highlight the ability we want to provide with this function somewhere at the start of the section, For example:
Sometimes we need an ability to acknowledge a task after reconnect (because retrying it is undesirable) or even acknowlegde using another connection.
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.
Accepted.
local queue_session_ids = box.space._queue_session_ids | ||
local session_uuid = queue_session.get_uuid(conn_id) | ||
|
||
queue_session_ids:delete{conn_id} |
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.
Jusr raw idea (maybe for further PRs): it may be helpful to have ability to trace connections and sessions and issue a log entry (on verbose or even debug level) when a connection is added or removed from a session or moved to another session.
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.
Sounds good.
@@ -372,6 +373,20 @@ Available `options`: | |||
* `ttr` - time to release in seconds. The time after which, if there is no active | |||
connection in the session, it will be released with all its tasks. | |||
|
|||
## Session identify |
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'm not sure, but maybe it worth to name the section 'Overcome a reconnect'. That is what a user will actually find.
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.
'Overcome a reconnect' is just one of the variants what for the sessions can be used.
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 didn't verified the implementation thoroughly, but the idea looks okay for me.
I left some comments: mostly regarding API and presenting the feature in the readme. Some are just to better understand the idea.
In the future, we will refuse to use the "pk" index of the "_queue_taken" space to improve performance (the conclusion about the improvement in performance is based on the benchmarks that will be added in one of the next commits). So, let's minimize its use. Needed for #85
The same time functions are used in several files, so move them to a separate file. Needed for #85
The patch adds the ability to set the queue settings(by calling "queue.cfg(opts)"). Now only one setting is available - "ttr"(time to release). "ttr" in seconds - the time after which, if there is no active connection in the session, it will be released with all its tasks. Part of #85
ac664e5
to
373139c
Compare
Before the patch a connection to server was synonym of the queue session. Now the session has a unique UUID (returned by the "queue.identify()" method), and one session can have many connections. The session will be deleted (all session tasks will be released) after "ttr" seconds have passed since the last connection was disconnected. To connect to an existing session, call "queue.identificate(uuid)" with the previously obtained UUID. "ttr" in seconds - the time after which, if there is no active connection in the session, it will be released with all its tasks. Also, the "_queue_taken" internal space has been replaced with the "_queue_taken_2" with a change format and used indexes (for better performance). The downgrade to previous version works correctly. Closes of #85
373139c
to
00365d6
Compare
Before the patchset a connection to server was synonym of the queue session. Now the session has a unique UUID (returned by the "queue.identify()" method), and one session can have many connections. To connect to an existing session, call "queue.identify(uuid)" with the previously obtained UUID.
Also, for the queue the
ttr
option has been added.ttr
in seconds - the time after which, if there is no active connection in the session, it will be released with all its tasks.Closes #85
@ChangeLog:
The "shared" sessions was added to the queue. Previously, a connection to server was synonym of the queue session. Now the session has a unique UUID (returned by the "queue.identify()" method), and one session can have many connections. To connect to an existing session, call "queue.identify(uuid)" with the previously obtained UUID.
Also, for the queue the
ttr
option has been added.ttr
in seconds - the time after which, if there is no active connection in the session, it will be released with all its tasks.