sequel-activerecord_connection 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +19 -23
- data/lib/sequel/extensions/activerecord_connection.rb +43 -24
- data/sequel-activerecord_connection.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8e137f0937e4f17511d40529df10648276b7dae834cef50f4bc6615206c486b
|
4
|
+
data.tar.gz: e25287b365a78b34c55afb084b0ebad4a24c8c00944323c1a2b455505fd4a251
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '033781eeae71623aa992f2a882c04a1fd718109435b3aa428b0710df4322f1f267664abb4670a9909e3aefa570029a37c8a6a6947d54d2b38e119b80c938245b'
|
7
|
+
data.tar.gz: c013ca47766a5cfae058353094df8a88e74a992de924f7b2107c6e50a5f76af72c74fab0f957032666f7b3442b80af886ca56f5bd3635d67c141fa67ff7be5d8
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.4.0 (2020-09-28)
|
2
|
+
|
3
|
+
* Return correct result of `Database#in_transaction?` after ActiveRecord transaction exited (@janko)
|
4
|
+
|
5
|
+
* Make ActiveRecord create a savepoint inside a Sequel transaction with `auto_savepoint: true` (@janko)
|
6
|
+
|
7
|
+
* Make Sequel create a savepoint inside ActiveRecord transaction with `joinable: false` (@janko)
|
8
|
+
|
9
|
+
* Improve reliability of nested transactions when combining Sequel and ActiveRecord (@janko)
|
10
|
+
|
11
|
+
* Raise error when attempting to add an `after_commit`/`after_rollback` hook on ActiveRecord transaction (@janko)
|
12
|
+
|
13
|
+
* Fix infinite loop that could happen with transactional Rails tests (@janko)
|
14
|
+
|
1
15
|
## 0.3.0 (2020-07-24)
|
2
16
|
|
3
17
|
* Fully support Sequel transaction API (all transaction options, transaction/savepoint hooks etc.) (@janko)
|
data/README.md
CHANGED
@@ -42,8 +42,7 @@ appropriate Sequel adapter and load the `activerecord_connection` extension:
|
|
42
42
|
```rb
|
43
43
|
require "sequel"
|
44
44
|
|
45
|
-
DB = Sequel.postgres(
|
46
|
-
DB.extension :activerecord_connection
|
45
|
+
DB = Sequel.postgres(extensions: :activerecord_connection)
|
47
46
|
```
|
48
47
|
|
49
48
|
Now any Sequel operations that you make will internaly be done using the
|
@@ -75,13 +74,13 @@ ActiveRecord adapters, just make sure to initialize the corresponding Sequel
|
|
75
74
|
adapter before loading the extension.
|
76
75
|
|
77
76
|
```rb
|
78
|
-
DB = Sequel.postgres(
|
77
|
+
DB = Sequel.postgres(extensions: :activerecord_connection) # for "postgresql" adapter
|
79
78
|
# or
|
80
|
-
DB = Sequel.mysql2(
|
79
|
+
DB = Sequel.mysql2(extensions: :activerecord_connection) # for "mysql2" adapter
|
81
80
|
# or
|
82
|
-
DB = Sequel.sqlite(
|
81
|
+
DB = Sequel.sqlite(extensions: :activerecord_connection) # for "sqlite3" adapter
|
83
82
|
# or
|
84
|
-
DB = Sequel.jdbc(
|
83
|
+
DB = Sequel.jdbc(extensions: :activerecord_connection) # for JDBC adapter
|
85
84
|
```
|
86
85
|
|
87
86
|
### Transactions
|
@@ -101,39 +100,36 @@ Sequel's transaction API is fully supported:
|
|
101
100
|
|
102
101
|
```rb
|
103
102
|
DB.transaction(isolation: :serializable) do
|
104
|
-
DB.after_commit { ... } #
|
103
|
+
DB.after_commit { ... } # executed after transaction commits
|
105
104
|
DB.transaction(savepoint: true) do # creates a savepoint
|
106
|
-
#
|
105
|
+
DB.after_commit(savepoint: true) { ... } # executed if all enclosing savepoints have been released
|
107
106
|
end
|
108
107
|
end
|
109
108
|
```
|
110
109
|
|
111
|
-
One caveat to keep in mind is that Sequel's transaction hooks
|
112
|
-
|
113
|
-
|
110
|
+
One caveat to keep in mind is that using Sequel's transaction/savepoint hooks
|
111
|
+
currently don't work if ActiveRecord holds the corresponding
|
112
|
+
transaction/savepoint. This is because it's difficult to be notified when
|
113
|
+
ActiveRecord commits or rolls back the transaction/savepoint.
|
114
114
|
|
115
115
|
```rb
|
116
116
|
DB.transaction do
|
117
117
|
DB.after_commit { ... } # will get executed
|
118
118
|
end
|
119
119
|
|
120
|
-
|
121
|
-
DB.
|
120
|
+
DB.transaction do
|
121
|
+
DB.transaction(savepoint: true) do
|
122
|
+
DB.after_commit(savepoint: true) { ... } # will get executed
|
123
|
+
end
|
122
124
|
end
|
123
125
|
|
124
126
|
ActiveRecord::Base.transaction do
|
125
|
-
DB.
|
126
|
-
DB.after_commit { ... } # won't get executed
|
127
|
-
end
|
127
|
+
DB.after_commit { ... } # not allowed (will raise Sequel::ActiveRecordConnection::Error)
|
128
128
|
end
|
129
|
-
```
|
130
129
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
ActiveRecord::Base.transaction do
|
135
|
-
DB.transaction(savepoint: true) do
|
136
|
-
DB.after_commit { ... } # will get executed after savepoint is released
|
130
|
+
DB.transaction do
|
131
|
+
ActiveRecord::Base.transaction(requires_new: true) do
|
132
|
+
DB.after_commit(savepoint: true) { ... } # not allowed (will raise Sequel::ActiveRecordConnection::Error)
|
137
133
|
end
|
138
134
|
end
|
139
135
|
```
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sequel
|
2
4
|
module ActiveRecordConnection
|
3
5
|
Error = Class.new(Sequel::Error)
|
@@ -41,38 +43,43 @@ module Sequel
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
# when to run transaction/savepoint hooks etc.
|
46
|
+
# Synchronizes transaction state with ActiveRecord. Sequel uses this
|
47
|
+
# information to know whether we're in a transaction, whether to create a
|
48
|
+
# savepoint, when to run transaction/savepoint hooks etc.
|
48
49
|
def _trans(conn)
|
49
|
-
|
50
|
-
result = @transactions[conn]
|
51
|
-
|
52
|
-
if activerecord_connection.transaction_open?
|
53
|
-
result ||= { savepoints: [] }
|
54
|
-
while result[:savepoints].length < activerecord_connection.open_transactions
|
55
|
-
result[:savepoints].unshift({ activerecord: true })
|
56
|
-
end
|
57
|
-
end
|
50
|
+
hash = super || { savepoints: [], activerecord: true }
|
58
51
|
|
59
|
-
|
60
|
-
|
52
|
+
# add any ActiveRecord transactions/savepoints that have been opened
|
53
|
+
# directly via ActiveRecord::Base.transaction
|
54
|
+
while hash[:savepoints].length < activerecord_connection.open_transactions
|
55
|
+
hash[:savepoints] << { activerecord: true }
|
56
|
+
end
|
57
|
+
|
58
|
+
# remove any ActiveRecord transactions/savepoints that have been closed
|
59
|
+
# directly via ActiveRecord::Base.transaction
|
60
|
+
while hash[:savepoints].length > activerecord_connection.open_transactions && hash[:savepoints].last[:activerecord]
|
61
|
+
hash[:savepoints].pop
|
62
|
+
end
|
63
|
+
|
64
|
+
# sync knowledge about joinability of current ActiveRecord transaction/savepoint
|
65
|
+
if activerecord_connection.transaction_open? && !activerecord_connection.current_transaction.joinable?
|
66
|
+
hash[:savepoints].last[:auto_savepoint] = true
|
67
|
+
end
|
68
|
+
|
69
|
+
if hash[:savepoints].empty? && hash[:activerecord]
|
70
|
+
Sequel.synchronize { @transactions.delete(conn) }
|
71
|
+
else
|
72
|
+
Sequel.synchronize { @transactions[conn] = hash }
|
61
73
|
end
|
62
|
-
end
|
63
74
|
|
64
|
-
# First delete any transactions/savepoints opened directly via
|
65
|
-
# ActiveRecord::Base.transaction, so that Sequel can detect when the last
|
66
|
-
# Sequel transaction has been closed and clear transaction information.
|
67
|
-
def transaction_finished?(conn)
|
68
|
-
_trans(conn)[:savepoints].shift while _trans(conn)[:savepoints].first[:activerecord]
|
69
75
|
super
|
70
76
|
end
|
71
77
|
|
72
78
|
def begin_transaction(conn, opts = {})
|
73
79
|
isolation = TRANSACTION_ISOLATION_MAP.fetch(opts[:isolation]) if opts[:isolation]
|
80
|
+
joinable = !opts[:auto_savepoint]
|
74
81
|
|
75
|
-
activerecord_connection.begin_transaction(isolation: isolation)
|
82
|
+
activerecord_connection.begin_transaction(isolation: isolation, joinable: joinable)
|
76
83
|
end
|
77
84
|
|
78
85
|
def commit_transaction(conn, opts = {})
|
@@ -84,8 +91,20 @@ module Sequel
|
|
84
91
|
activerecord_connection.transaction_manager.send(:after_failure_actions, activerecord_connection.current_transaction, $!) if activerecord_connection.transaction_manager.respond_to?(:after_failure_actions)
|
85
92
|
end
|
86
93
|
|
87
|
-
def
|
88
|
-
|
94
|
+
def add_transaction_hook(conn, type, block)
|
95
|
+
if _trans(conn)[:activerecord]
|
96
|
+
fail Error, "cannot add transaction hook when ActiveRecord holds the outer transaction"
|
97
|
+
end
|
98
|
+
|
99
|
+
super
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_savepoint_hook(conn, type, block)
|
103
|
+
if _trans(conn)[:savepoints].last[:activerecord]
|
104
|
+
fail Error, "cannot add savepoint hook when ActiveRecord holds the current savepoint"
|
105
|
+
end
|
106
|
+
|
107
|
+
super
|
89
108
|
end
|
90
109
|
|
91
110
|
def activerecord_raw_connection
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel-activerecord_connection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|