Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
145832d6
Commit
145832d6
authored
Jun 15, 2018
by
blackst0ne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Rails5] Fix optimistic lock value
Update the monkey-patch to make it work in Rails 5.
parent
fb08183e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
64 additions
and
52 deletions
+64
-52
changelogs/unreleased/blackst0ne-rails5-fix-optimistic-lock-values.yml
...released/blackst0ne-rails5-fix-optimistic-lock-values.yml
+5
-0
config/initializers/active_record_locking.rb
config/initializers/active_record_locking.rb
+59
-52
No files found.
changelogs/unreleased/blackst0ne-rails5-fix-optimistic-lock-values.yml
0 → 100644
View file @
145832d6
---
title
:
"
[Rails5]
Fix
optimistic
lock
value"
merge_request
:
19878
author
:
"
@blackst0ne"
type
:
fixed
config/initializers/active_record_locking.rb
View file @
145832d6
# rubocop:disable Lint/RescueException
# rubocop:disable Lint/RescueException
# Remove this entire initializer when we are at rails 5.0.
# Remove this monkey-patch when all lock_version values are converted from NULLs to zeros.
# This file fixes the bug (see below) which has been fixed in the upstream.
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/25228
unless
Gitlab
.
rails5?
module
ActiveRecord
# This patch fixes https://github.com/rails/rails/issues/26024
module
Locking
# TODO: Remove it when it's no longer necessary
module
Optimistic
# We overwrite this method because we don't want to have default value
module
ActiveRecord
# for newly created records
module
Locking
def
_create_record
(
attribute_names
=
self
.
attribute_names
,
*
)
# :nodoc:
module
Optimistic
super
# We overwrite this method because we don't want to have default value
end
# for newly created records
def
_create_record
(
attribute_names
=
self
.
attribute_names
,
*
)
# :nodoc:
super
end
def
_update_record
(
attribute_names
=
self
.
attribute_names
)
#:nodoc:
def
_update_record
(
attribute_names
=
self
.
attribute_names
)
#:nodoc:
return
super
unless
locking_enabled?
return
super
unless
locking_enabled?
return
0
if
attribute_names
.
empty?
return
0
if
attribute_names
.
empty?
lock_col
=
self
.
class
.
locking_column
lock_col
=
self
.
class
.
locking_column
previous_lock_value
=
send
(
lock_col
).
to_i
# rubocop:disable GitlabSecurity/PublicSend
previous_lock_value
=
send
(
lock_col
).
to_i
# rubocop:disable GitlabSecurity/PublicSend
# This line is added as a patch
# This line is added as a patch
previous_lock_value
=
nil
if
previous_lock_value
==
'0'
||
previous_lock_value
==
0
previous_lock_value
=
nil
if
previous_lock_value
==
'0'
||
previous_lock_value
==
0
increment_lock
increment_lock
attribute_names
+=
[
lock_col
]
attribute_names
+=
[
lock_col
]
attribute_names
.
uniq!
attribute_names
.
uniq!
begin
begin
relation
=
self
.
class
.
unscoped
relation
=
self
.
class
.
unscoped
affected_rows
=
relation
.
where
(
affected_rows
=
relation
.
where
(
self
.
class
.
primary_key
=>
id
,
self
.
class
.
primary_key
=>
id
,
lock_col
=>
previous_lock_value
lock_col
=>
previous_lock_value
).
update_all
(
).
update_all
(
attributes_for_update
(
attribute_names
).
map
do
|
name
|
attributes_for_update
(
attribute_names
).
map
do
|
name
|
[
name
,
_read_attribute
(
name
)]
[
name
,
_read_attribute
(
name
)]
end
.
to_h
end
.
to_h
)
)
unless
affected_rows
==
1
unless
affected_rows
==
1
raise
ActiveRecord
::
StaleObjectError
.
new
(
self
,
"update"
)
raise
ActiveRecord
::
StaleObjectError
.
new
(
self
,
"update"
)
end
end
affected_rows
affected_rows
# If something went wrong, revert the version.
# If something went wrong, revert the version.
rescue
Exception
rescue
Exception
send
(
lock_col
+
'='
,
previous_lock_value
)
# rubocop:disable GitlabSecurity/PublicSend
send
(
lock_col
+
'='
,
previous_lock_value
)
# rubocop:disable GitlabSecurity/PublicSend
raise
raise
end
end
end
end
# This is patched because we need it to query `lock_version IS NULL`
# This is patched because we need it to query `lock_version IS NULL`
# rather than `lock_version = 0` whenever lock_version is NULL.
# rather than `lock_version = 0` whenever lock_version is NULL.
def
relation_for_destroy
def
relation_for_destroy
return
super
unless
locking_enabled?
return
super
unless
locking_enabled?
column_name
=
self
.
class
.
locking_column
column_name
=
self
.
class
.
locking_column
super
.
where
(
self
.
class
.
arel_table
[
column_name
].
eq
(
self
[
column_name
]))
super
.
where
(
self
.
class
.
arel_table
[
column_name
].
eq
(
self
[
column_name
]))
end
end
end
end
# This is patched because we want `lock_version` default to `NULL`
# rather than `0`
if
Gitlab
.
rails5?
class
LockingType
def
deserialize
(
value
)
super
end
# This is patched because we want `lock_version` default to `NULL`
def
serialize
(
value
)
# rather than `0`
super
end
end
else
class
LockingType
<
SimpleDelegator
class
LockingType
<
SimpleDelegator
def
type_cast_from_database
(
value
)
def
type_cast_from_database
(
value
)
super
super
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment