Sessions
On this page
Version 3.6 of the MongoDB server introduces the concept of logical sessions for clients.
A session is an abstract concept that represents a set of sequential operations executed
by an application that are related in some way. A session object can be created via a Mongo::Client
and passed to operation methods that should be executed in the context of that session.
Please note that session objects are not thread safe. They must only be used by one thread at a time.
Creating a session from a Mongo::Client
A session can be created by calling the start_session
method on a client and passing it a block:
client.start_session do |session| # work with the session end
When using the block form, the session will be automatically ended by the driver after the block finishes executing.
It is valid to call start_session
with no options set. This will result in a
session that has no effect on the operations performed in the context of that session,
other than to include a session ID in commands sent to the server. Please see the API docs for all supported
session options.
An error will be thrown if the driver is connected to a deployment that does not support sessions and the
start_session
method is called.
Note that server sessions are discarded server-side if not used for a certain period of time.
Be aware that if the application calls #start_session
on a client and waits more than 1 minute to use
the session, it risks getting errors due to the session going stale before it is used.
Using a session
A session object can be passed to most driver methods so that the operation can be executed in the context of that session. Please see the API docs for which methods support a session argument.
Create a session and execute an insert, then a find using that session:
client.start_session do |session| client[:artists].insert_one({ :name => 'FKA Twigs' }, session: session) client[:artists].find({ :name => 'FKA Twigs' }, limit: 1, session: session).first end
If you like to call methods on a Mongo::Collection::View
in the context of a particular session, you can create the
Mongo::Collection::View
with the session and then call methods on it:
client.start_session(causal_consistency: true) do |session| view = client[:artists].find({ :name => 'FKA Twigs' }, session: session) view.count # will use the session end
You can also pass the session option to the methods directly. This session will override any session associated with
the Mongo::Collection::View
:
client.start_session do |session| client.start_session do |second_session| view = client[:artists].find({ :name => 'FKA Twigs' }, session: session) view.count(session: second_session) # will use the second_session end end
Alternative way to create a session
A session can be created by calling the start_session
method on a client:
session = client.start_session
When start_session
is used without passing a block to it, the driver does not automatically clean up the session which can result in an accumulation of sessions on the server. Use end_session to manually end the session created. The server will automatically clean up old sessions after a timeout but the application should end sessions when the sessions are no longer needed.
Unacknowledged Writes
Unacknowledged writes are only allowed outside the session mechanism; if an explicit session is supplied for an unacknowledged write, the driver will not send the session id with the operation. Similarly, the driver will not use an implicit session for an unacknowledged write.
Causal Consistency
A causally consistent session will let you read your writes and guarantee monotonically increasing
reads from secondaries.
To create a causally consistent session, set the causal_consistency
option to true:
session = client.start_session(causal_consistency: true) # The update message goes to the primary. collection = client[:artists] collection.update_one({ '_id' => 1 }, { '$set' => { 'x' => 0 } }, session: session) # Read your write, even when reading from a secondary! collection.find({ '_id' => 1 }, session: session).first # This query returns data at least as new as the previous query, # even if it chooses a different secondary. collection.find({ '_id' => 2 }, session: session).first
Since unacknowledged writes don't receive a response from the server (or don't wait for a response), the driver has no way of keeping track of where the unacknowledged write is in logical time. Therefore, causally consistent reads are not causally consistent with unacknowledged writes.
Note that if you set the causal_consistency option to nil as in (causal_consistency: nil)
, it will be interpreted
as false.
End a session
To end a session, call the end_session
method:
session.end_session
The Ruby driver will then add the id for the corresponding server session to a pool for reuse. When a client is closed, the driver will send a command to the server to end all sessions it has cached in its server session pool. You may see this command in your logs when a client is closed.
Note that when using the block syntax for start_session
the session is automatically ended after
the block finishes executing.