Docs Menu

Docs HomeDevelop ApplicationsMongoDB DriversRuby MongoDB Driver

Sessions

On this page

  • Creating a session from a Mongo::Client
  • Using a session
  • Alternative way to create a session
  • Unacknowledged Writes
  • Causal Consistency
  • End a session

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.

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.

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

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 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.

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.

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.

←  Change StreamsTransactions →