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
7e778e8f
Commit
7e778e8f
authored
Nov 01, 2021
by
nmilojevic1
Committed by
Nikola Milojevic
Nov 12, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement multi store
parent
aa8bd302
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
110 additions
and
0 deletions
+110
-0
lib/gitlab/redis/multi_store.rb
lib/gitlab/redis/multi_store.rb
+110
-0
No files found.
lib/gitlab/redis/multi_store.rb
0 → 100644
View file @
7e778e8f
# frozen_string_literal: true
module
Gitlab
module
Redis
class
MultiStore
attr_reader
:primary_store
,
:secondary_store
READ_COMMANDS
=
%i(
get
mget
smembers
)
.
freeze
WRITE_COMMANDS
=
%i(
setnx
setex
sadd
srem
del
pipelined
flushdb
)
.
freeze
def
initialize
(
primary_store_options
,
secondary_store_options
)
@primary_store
=
::
Redis
::
Store
.
new
(
primary_store_options
)
@secondary_store
=
::
Redis
::
Store
.
new
(
secondary_store_options
)
end
# This is needed because of Redis::Rack::Connection is requiring Redis::Store
# https://github.com/redis-store/redis-rack/blob/a833086ba494083b6a384a1a4e58b36573a9165d/lib/redis/rack/connection.rb#L15
# Done similarly in https://github.com/lsegal/yard/blob/main/lib/yard/templates/template.rb#L122
def
is_a?
(
klass
)
return
true
if
klass
==
::
Redis
::
Store
super
(
klass
)
end
# TODO: Add Feature flags, by default read only from the secondary store,
# by enabling the FF, read from the primary, and fallback to read from the secondary.
READ_COMMANDS
.
each
do
|
name
|
define_method
(
name
)
do
|*
args
,
**
kwargs
,
&
block
|
if
@instance
send_command
(
@instance
,
name
,
*
args
,
**
kwargs
,
&
block
)
else
value
=
send_command
(
primary_store
,
name
,
*
args
,
**
kwargs
,
&
block
)
# TODO: Add logger to detect for which key we fallback to shared_steate_store
value
||=
send_command
(
secondary_store
,
name
,
*
args
,
**
kwargs
,
&
block
)
value
end
end
end
# TODO: Add proper error handling if primary store fails, ensuring that we execute at least on secondary store
# TODO: Add Feature flags, by default write only on the secondary store (SharedState), by enabling the FF, write to the primary as well.
WRITE_COMMANDS
.
each
do
|
name
|
define_method
(
name
)
do
|*
args
,
**
kwargs
,
&
block
|
if
@instance
send_command
(
@instance
,
name
,
*
args
,
**
kwargs
,
&
block
)
else
send_command
(
primary_store
,
name
,
*
args
,
**
kwargs
,
&
block
)
send_command
(
secondary_store
,
name
,
*
args
,
**
kwargs
,
&
block
)
end
end
end
# TEST: try to avoid Deprecation Toolkit issues
# See the pipelines of the POC for the example
# We call set there https://github.com/redis-store/redis-rack/blob/v2.1.3/lib/rack/session/redis.rb#L49
# With the meta-definition like there, we have hash <-> kwargs Ruby 2.7 issues as the downstream is defined like:
# https://github.com/redis/redis-rb/blob/master/lib/redis.rb#L846
def
set
(
...
)
if
@instance
send_command
(
@instance
,
:set
,
...
)
else
send_command
(
primary_store
,
:set
,
...
)
send_command
(
secondary_store
,
:set
,
...
)
end
end
private
def
send_command
(
redis_instance
,
name
,
*
args
,
**
kwargs
,
&
block
)
if
block_given?
redis_instance
.
send
(
name
,
*
args
,
**
kwargs
)
do
|*
args
|
# rubocop:disable GitlabSecurity/PublicSend
with_instance
(
redis_instance
,
*
args
,
&
block
)
end
else
redis_instance
.
send
(
name
,
*
args
,
**
kwargs
)
# rubocop:disable GitlabSecurity/PublicSend
end
end
def
with_instance
(
instance
,
*
args
)
@instance
=
instance
yield
(
*
args
)
ensure
@instance
=
nil
end
def
method_missing
(
...
)
# TODO: Add logger here to log for which key and command we did fallback to the shared_state_store
secondary_store
.
send
(
...
)
# rubocop:disable GitlabSecurity/PublicSend
end
def
respond_to_missing?
(
method_name
,
include_private
=
false
)
true
end
end
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