Skip to content

Commit fa13bb8

Browse files
MONGOID-4901 Add sandbox mode (#5523)
1 parent 26be63a commit fa13bb8

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

lib/mongoid/railtie.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ module Mongoid
99
# Hooks Mongoid into Rails 3 and higher.
1010
class Railtie < Rails::Railtie
1111

12+
console do |app|
13+
if app.sandbox?
14+
require "mongoid/railties/console_sandbox"
15+
start_sandbox
16+
end
17+
end
18+
1219
# Mapping of rescued exceptions to HTTP responses
1320
#
1421
# @example
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
require "mongoid/threaded"
2+
require "mongoid/errors/transactions_not_supported"
3+
4+
# This method raises an error if the cluster the client is connected to
5+
# does not support transactions in any case. At the moment this is the case
6+
# of the standalone topology.
7+
#
8+
# Please note that if this method did not raise, it does not guarantee that
9+
# transactions are available for the cluster.
10+
#
11+
# @param [ Mongo::Client ] client Client connected to a cluster to be tested.
12+
#
13+
# @raise [ Mongoid::Errors::TransactionsNotSupported ] If the cluster
14+
# definitely does not support transactions.
15+
def check_if_transactions_might_be_available!(client)
16+
if client.cluster.single?
17+
raise Mongoid::Errors::TransactionsNotSupported
18+
end
19+
end
20+
21+
# Starts a transaction that should include all the operations inside
22+
# the sandboxed console session. This transaction should not be ever committed.
23+
# When a user end the console session, the client will disconnect, and
24+
# the transaction will be automatically aborted therefore.
25+
#
26+
# @param [ Mongo::Client ] client Client to start the transaction.
27+
def start_sandbox_transaction(client)
28+
session = client.start_session
29+
::Mongoid::Threaded.set_session(session, client: client)
30+
session.start_transaction
31+
end
32+
33+
# Prepares console sandbox mode. This method should be called when
34+
# a user starts rails console with '--sandbox' flag.
35+
def start_sandbox
36+
Mongoid.persistence_context.client.tap do |client|
37+
check_if_transactions_might_be_available!(client)
38+
start_sandbox_transaction(client)
39+
end
40+
end
41+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
require 'spec_helper'
2+
require 'mongoid/railties/console_sandbox'
3+
4+
describe 'console_sandbox' do
5+
describe '#check_if_transactions_might_be_available!' do
6+
context 'cluster may support transactions' do
7+
require_topology :replica_set, :sharded, :load_balanced
8+
9+
it 'does not raise' do
10+
expect do
11+
check_if_transactions_might_be_available!(Mongoid.default_client)
12+
end.not_to raise_error
13+
end
14+
end
15+
16+
context 'cluster does not support transactions' do
17+
require_topology :single
18+
19+
it 'raises an error' do
20+
expect do
21+
check_if_transactions_might_be_available!(Mongoid.default_client)
22+
end.to raise_error(Mongoid::Errors::TransactionsNotSupported)
23+
end
24+
end
25+
end
26+
27+
describe '#start_sandbox_transaction' do
28+
require_transaction_support
29+
30+
before do
31+
start_sandbox_transaction(Mongoid.default_client)
32+
end
33+
34+
after do
35+
Mongoid.send(:_session).abort_transaction
36+
Mongoid::Threaded.clear_session(client: Mongoid.default_client)
37+
end
38+
39+
it 'starts transaction' do
40+
expect(Mongoid.send(:_session)).to be_in_transaction
41+
end
42+
end
43+
end

0 commit comments

Comments
 (0)