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
1
Merge Requests
1
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
nexedi
gitlab-ce
Commits
73c57fd3
Commit
73c57fd3
authored
Mar 24, 2017
by
Rémy Coutable
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a post-deploy migration to migrate from former Redis activity to DB
Signed-off-by:
Rémy Coutable
<
remy@rymai.me
>
parent
81421262
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
136 additions
and
0 deletions
+136
-0
db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb
...0416_migrate_user_activities_to_users_last_activity_on.rb
+87
-0
spec/migrations/migrate_user_activities_to_users_last_activity_on_spec.rb
...migrate_user_activities_to_users_last_activity_on_spec.rb
+49
-0
No files found.
db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb
0 → 100644
View file @
73c57fd3
class
MigrateUserActivitiesToUsersLastActivityOn
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
disable_ddl_transaction!
DOWNTIME
=
false
USER_ACTIVITY_SET_KEY
=
'user/activities'
.
freeze
ACTIVITIES_PER_PAGE
=
100
TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED
=
Time
.
utc
(
2016
,
12
,
1
)
def
up
return
if
activities_count
(
TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED
,
Time
.
now
).
zero?
day
=
Time
.
at
(
activities
(
TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED
,
Time
.
now
).
first
.
second
)
transaction
do
while
day
<=
Time
.
now
.
utc
.
tomorrow
persist_last_activity_on
(
day:
day
)
day
=
day
.
tomorrow
end
end
end
def
down
# This ensures we don't lock all users for the duration of the migration.
update_column_in_batches
(
:users
,
:last_activity_on
,
nil
)
do
|
table
,
query
|
query
.
where
(
table
[
:last_activity_on
].
not_eq
(
nil
))
end
end
private
def
persist_last_activity_on
(
day
:,
page:
1
)
activities_count
=
activities_count
(
day
.
at_beginning_of_day
,
day
.
at_end_of_day
)
return
if
activities_count
.
zero?
activities
=
activities
(
day
.
at_beginning_of_day
,
day
.
at_end_of_day
,
page:
page
)
update_sql
=
Arel
::
UpdateManager
.
new
(
ActiveRecord
::
Base
).
table
(
users_table
).
set
(
users_table
[
:last_activity_on
]
=>
day
.
to_date
).
where
(
users_table
[
:username
].
in
(
activities
.
map
(
&
:first
))).
to_sql
connection
.
exec_update
(
update_sql
,
self
.
class
.
name
,
[])
unless
last_page?
(
page
,
activities_count
)
persist_last_activity_on
(
day:
day
,
page:
page
+
1
)
end
end
def
users_table
@users_table
||=
Arel
::
Table
.
new
(
:users
)
end
def
activities
(
from
,
to
,
page:
1
)
Gitlab
::
Redis
.
with
do
|
redis
|
redis
.
zrangebyscore
(
USER_ACTIVITY_SET_KEY
,
from
.
to_i
,
to
.
to_i
,
with_scores:
true
,
limit:
limit
(
page
))
end
end
def
activities_count
(
from
,
to
)
Gitlab
::
Redis
.
with
do
|
redis
|
redis
.
zcount
(
USER_ACTIVITY_SET_KEY
,
from
.
to_i
,
to
.
to_i
)
end
end
def
limit
(
page
)
[
offset
(
page
),
ACTIVITIES_PER_PAGE
]
end
def
total_pages
(
count
)
(
count
.
to_f
/
ACTIVITIES_PER_PAGE
).
ceil
end
def
last_page?
(
page
,
count
)
page
>=
total_pages
(
count
)
end
def
offset
(
page
)
(
page
-
1
)
*
ACTIVITIES_PER_PAGE
end
end
spec/migrations/migrate_user_activities_to_users_last_activity_on_spec.rb
0 → 100644
View file @
73c57fd3
# encoding: utf-8
require
'spec_helper'
require
Rails
.
root
.
join
(
'db'
,
'post_migrate'
,
'20170324160416_migrate_user_activities_to_users_last_activity_on.rb'
)
describe
MigrateUserActivitiesToUsersLastActivityOn
,
:redis
do
let
(
:migration
)
{
described_class
.
new
}
let!
(
:user_active_1
)
{
create
(
:user
)
}
let!
(
:user_active_2
)
{
create
(
:user
)
}
def
record_activity
(
user
,
time
)
Gitlab
::
Redis
.
with
do
|
redis
|
redis
.
zadd
(
described_class
::
USER_ACTIVITY_SET_KEY
,
time
.
to_i
,
user
.
username
)
end
end
around
do
|
example
|
Timecop
.
freeze
{
example
.
run
}
end
before
do
record_activity
(
user_active_1
,
described_class
::
TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED
+
2
.
months
)
record_activity
(
user_active_2
,
described_class
::
TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED
+
3
.
months
)
mute_stdout
{
migration
.
up
}
end
describe
'#up'
do
it
'fills last_activity_on from the legacy Redis Sorted Set'
do
expect
(
user_active_1
.
reload
.
last_activity_on
).
to
eq
((
described_class
::
TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED
+
2
.
months
).
to_date
)
expect
(
user_active_2
.
reload
.
last_activity_on
).
to
eq
((
described_class
::
TIME_WHEN_ACTIVITY_SET_WAS_INTRODUCED
+
3
.
months
).
to_date
)
end
end
describe
'#down'
do
it
'sets last_activity_on to NULL for all users'
do
mute_stdout
{
migration
.
down
}
expect
(
user_active_1
.
reload
.
last_activity_on
).
to
be_nil
expect
(
user_active_2
.
reload
.
last_activity_on
).
to
be_nil
end
end
def
mute_stdout
orig_stdout
=
$stdout
$stdout
=
StringIO
.
new
yield
$stdout
=
orig_stdout
end
end
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