Module: Wurk::Preflight::RedisGuard
- Defined in:
- lib/wurk/preflight/redis_guard.rb
Overview
What keeps app code off Redis while wurk boot-check or wurk preflight --app boots the app. Their initializers run, configure_server blocks
included, and some of those write Redis at boot (a dev-only flushdb, a
seed). Installed before the app loads, it rides every pool Wurk builds
(RedisPool.guard) as a redis-client middleware, so Sidekiq.redis,
Wurk.redis and every Wurk data view are covered whichever method or
pipeline sends the command. A client the app opens itself (Redis.new,
Rails.cache) is not Wurk's and is not covered.
Defined Under Namespace
Modules: Closed, ReadOnly Classes: Refused
Constant Summary collapse
- HANDSHAKE =
Sent by redis-client itself while it dials; none of them changes data.
%w[HELLO AUTH SELECT ROLE PING].freeze
- CLIENT_HANDSHAKE =
%w[SETINFO SETNAME].freeze
- LIB =
::File.('../..', __dir__)
- GEM_FRAMES =
%r{/(?:redis-client|hiredis-client|connection_pool)-[^/]+/}- STDLIB =
::RbConfig::CONFIG['rubylibdir']
Class Attribute Summary collapse
-
.label ⇒ Object
readonly
Returns the value of attribute label.
Class Method Summary collapse
- .allowed?(command) ⇒ Boolean
- .check!(command) ⇒ Object
-
.culprit(locations = caller_locations) ⇒ Object
The first frame outside Wurk, the Redis client and the pool: the app file (an initializer, a gem's railtie) that asked for Redis.
-
.install(mode, label:) ⇒ Object
modeis :closed or :read_only. - .message(what, policy) ⇒ Object
- .uninstall ⇒ Object
Class Attribute Details
.label ⇒ Object (readonly)
Returns the value of attribute label.
49 50 51 |
# File 'lib/wurk/preflight/redis_guard.rb', line 49 def label @label end |
Class Method Details
.allowed?(command) ⇒ Boolean
68 69 70 71 72 73 |
# File 'lib/wurk/preflight/redis_guard.rb', line 68 def allowed?(command) name = command.first.to_s.upcase return CLIENT_HANDSHAKE.include?(command[1].to_s.upcase) if name == 'CLIENT' Reader::ALLOWED.include?(name) || HANDSHAKE.include?(name) end |
.check!(command) ⇒ Object
62 63 64 65 66 |
# File 'lib/wurk/preflight/redis_guard.rb', line 62 def check!(command) return if allowed?(command) raise Refused, ("sent #{command.first.to_s.upcase}", 'sends only reads') end |
.culprit(locations = caller_locations) ⇒ Object
The first frame outside Wurk, the Redis client and the pool: the app file (an initializer, a gem's railtie) that asked for Redis.
83 84 85 86 |
# File 'lib/wurk/preflight/redis_guard.rb', line 83 def culprit(locations = caller_locations) frame = locations.find { |loc| app_frame?(loc.absolute_path || loc.path) } frame ? "#{frame.path}:#{frame.lineno}" : 'app code' end |
.install(mode, label:) ⇒ Object
mode is :closed or :read_only. Process-wide, as the boot it guards is.
52 53 54 55 |
# File 'lib/wurk/preflight/redis_guard.rb', line 52 def install(mode, label:) @label = label RedisPool.guard = mode == :closed ? Closed : ReadOnly end |
.message(what, policy) ⇒ Object
75 76 77 78 79 |
# File 'lib/wurk/preflight/redis_guard.rb', line 75 def (what, policy) "#{label}: #{culprit} #{what} while the app booted, and #{label} #{policy}. App code that touches Redis " \ 'at boot (a flushdb, a seed) would reach a real server here. Move it into `config.on(:startup)`, which ' \ "only a running worker fires#{', or pass --redis to allow reads' if policy.start_with?('runs')}." end |