bigrails-redis 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a759e01aab33407d58cedf4e5920130bc302fb72bdf1f31d9946a6315bade497
4
+ data.tar.gz: bce916691075cb892b279bc14aa152ffd4dd436470d4204199f19f0b9d0c18ba
5
+ SHA512:
6
+ metadata.gz: 5f9d4a1d5c7d237ecd5ef4dfafc4dcb60a000a417992fc133097b96858b0c092e8707584757c5f6d42b7d204431b2dace0857013e9e19299d7e56da8b72d5916
7
+ data.tar.gz: 67b9273fbbcc1f4ccbcd1883499c6acf841ef02aa477b742cbc03e4ac19e358f9859c61e5cfcf7bf4a0cb356ce20b4209bf26799759dea11eef44829d8fd5d1f
data/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # BigRails::Redis [![Ruby](https://github.com/BigRails/bigrails-redis/actions/workflows/main.yml/badge.svg)](https://github.com/BigRails/bigrails-redis/actions/workflows/main.yml)
2
+
3
+ A simple Redis connection manager for Rails applications with distributed and [ConnectionPool](https://github.com/mperham/connection_pool) support.
4
+
5
+ ## Installation
6
+
7
+ Add to your Gemfile:
8
+
9
+ $ bundle add bigrails-redis
10
+
11
+ Create a redis configuration file:
12
+
13
+ $ touch config/redis.rb
14
+
15
+ ## Usage
16
+
17
+ ### Configuring Connections
18
+
19
+ The configuration file (`config/redis.rb`) is just a plain Ruby file that will be evaluated when a connection is requested. Use the `connection` DSL method to declare your connections. The method will yield a block and you're expected to return a configuration hash.
20
+
21
+ A configuration hash, by default, is passed to `ActiveSupport::Cache::RedisCacheStore.build_redis(...)`. This is a Rails supplied helper which allows for more options than demostrated above. You'll want to [check out its source](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/cache/redis_cache_store.rb#L77-L100) to get a better idea of what it supports.
22
+
23
+ ```ruby
24
+ # Simple hardcoded example.
25
+ connection(:default) do
26
+ {
27
+ url: "redis://localhost"
28
+ }
29
+ end
30
+
31
+ # Do something more dynamic.
32
+ %w(
33
+ cache
34
+ foobar
35
+ ).each do |name|
36
+ connection(name) do
37
+ {
38
+ url: Rails.application.credentials.fetch("#{name}_redis")
39
+ }.tap do |options|
40
+ # Maybe in CI, you need to change the host.
41
+ if ENV['CI']
42
+ options[:host] = "redishost"
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # Connection pool support.
49
+ connection(:sidekiq) do
50
+ {
51
+ url: "redis://localhost/2"
52
+ pool_timeout: 5,
53
+ pool_size: 5
54
+ }
55
+ end
56
+
57
+ # Distributed Redis support.
58
+ connection(:baz) do
59
+ {
60
+ url: [
61
+ "redis://host1",
62
+ "redis://host2",
63
+ "redis://host3"
64
+ ]
65
+ }
66
+ end
67
+ ```
68
+
69
+ ### Accessing Connections
70
+
71
+ To access connections inside the application, you can do the following:
72
+
73
+ ```ruby
74
+ Rails.application.redis #=> Redis Registry
75
+
76
+ Rails.application.redis.for(:default) #=> Redis
77
+ Rails.application.redis.for(:cache) #=> Redis
78
+ Rails.application.redis.for(:foobar) #=> Redis
79
+ Rails.application.redis.for(:sidekiq) #=> ConnectionPool
80
+ ```
81
+
82
+ If needed, you can request a [wrapped connection pool](https://github.com/mperham/connection_pool#migrating-to-a-connection-pool):
83
+
84
+ ```ruby
85
+ Rails.application.redis.for(:pooled_connection, wrapped: true)
86
+ ```
87
+
88
+ If you request a wrapped connection for a non-pooled connection, it'll just return the original, plain `Redis` connection object. Rails already modifies `Redis` to add `ConnectionPool`-like behavior by adding a `with` method that yields the connection itself.
89
+
90
+ ### Verifying Connections
91
+
92
+ This library also allows you to verify connections on demand. If you want, perform the verification in a startup health check to make sure all your connections are valid. It will perform a simple [`PING` command](https://redis.io/commands/PING). An error will be raised if the connection bad.
93
+
94
+ ```ruby
95
+ # Verify all connections:
96
+ Rails.application.redis.verify!
97
+
98
+ # Verify a single connection:
99
+ Rails.application.redis.verify!(:foobar)
100
+ ```
101
+
102
+ ## Development
103
+
104
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
105
+
106
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
107
+
108
+ ## Contributing
109
+
110
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ngan/bigrails-redis. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/ngan/bigrails-redis/blob/master/CODE_OF_CONDUCT.md).
111
+
112
+ ## License
113
+
114
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
115
+
116
+ ## Code of Conduct
117
+
118
+ Everyone interacting in the BigRails::Redis project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ngan/bigrails-redis/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,9 @@
1
+ module BigRails
2
+ module Redis
3
+ module ApplicationExtension
4
+ def redis
5
+ @redis ||= Registry.new
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ require "active_support/cache/redis_cache_store"
2
+
3
+ module BigRails
4
+ module Redis
5
+ class Configuration
6
+ attr_reader :redis_options
7
+ attr_reader :pool_options
8
+
9
+ def initialize(redis_options)
10
+ @redis_options = redis_options
11
+ @pool_options ||= {}.tap do |pool_options|
12
+ pool_options[:size] = redis_options.delete(:pool_size) if redis_options[:pool_size]
13
+ pool_options[:timeout] = redis_options.delete(:pool_timeout) if redis_options[:pool_timeout]
14
+ end
15
+
16
+ ensure_connection_pool_added! if pool_options.any?
17
+ end
18
+
19
+ private
20
+
21
+ def ensure_connection_pool_added!
22
+ require "connection_pool"
23
+ rescue LoadError => e
24
+ warn "You don't have connection_pool installed in your application. Please add it to your Gemfile and run bundle install"
25
+ raise e
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BigRails
4
+ module Redis
5
+ class ConfigurationDsl
6
+ FILENAME = "redis.rb"
7
+
8
+ attr_reader :__configurations
9
+
10
+ def self.resolve
11
+ new.__configurations
12
+ end
13
+
14
+ def initialize
15
+ @__configurations = {}
16
+
17
+ file = File.join(Rails.application.paths["config"].first, FILENAME)
18
+ instance_eval(File.read(file), file, 1)
19
+
20
+ @__configurations.freeze
21
+ end
22
+
23
+ # DSL Methods
24
+
25
+ def connection(name)
26
+ name = name.to_s
27
+ if @__configurations.key?(name)
28
+ raise ArgumentError, "connection named '#{name}' already registered"
29
+ end
30
+
31
+ @__configurations[name.to_s] = Configuration.new(yield)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ require "rails"
2
+
3
+ module BigRails
4
+ module Redis
5
+ class Railtie < Rails::Railtie
6
+ config.before_configuration do |app|
7
+ app.include(ApplicationExtension)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BigRails
4
+ module Redis
5
+ class Registry
6
+ class UnknownConnection < StandardError
7
+ end
8
+
9
+ attr_accessor :builder
10
+
11
+ def initialize
12
+ @connections = {}
13
+ @wrapped_connections = {}
14
+
15
+ # Default redis builder.
16
+ @builder = ->(config) {
17
+ ActiveSupport::Cache::RedisCacheStore.build_redis(**config.redis_options)
18
+ }
19
+ end
20
+
21
+ def for(name, wrapped: false)
22
+ name = validate_name(name)
23
+
24
+ if wrapped
25
+ @wrapped_connections[name] ||= build_wrapped_connection(self.for(name))
26
+ else
27
+ @connections[name] ||= build_connection(name)
28
+ end
29
+ end
30
+
31
+ def config_for(name)
32
+ configurations[validate_name(name)]
33
+ end
34
+
35
+ def each(&block)
36
+ configurations.keys.map { self.for(name) }.each(&block)
37
+ end
38
+
39
+ def verify!(name = nil)
40
+ if name
41
+ verify_connection(self.for(name))
42
+ else
43
+ each { |connection| verify_connection(connection) }
44
+ end
45
+
46
+ true
47
+ end
48
+
49
+ private
50
+
51
+ def build_connection(name)
52
+ config = configurations.fetch(name)
53
+
54
+ if config.pool_options.any?
55
+ ::ConnectionPool.new(config.pool_options) { builder.call(config) }
56
+ else
57
+ builder.call(config)
58
+ end
59
+ end
60
+
61
+ def build_wrapped_connection(connection)
62
+ if connection.is_a?(::Redis)
63
+ connection
64
+ else
65
+ ::ConnectionPool.wrap(pool: connection)
66
+ end
67
+ end
68
+
69
+ def verify_connection(connection)
70
+ connection.with do |redis|
71
+ redis.ping == "PONG"
72
+ end
73
+ end
74
+
75
+ def validate_name(name)
76
+ name = name.to_s
77
+ unless configurations.key?(name)
78
+ raise UnknownConnection, "connection for '#{name}' is not registered"
79
+ end
80
+ name
81
+ end
82
+
83
+ def configurations
84
+ @configurations ||= ConfigurationDsl.resolve
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BigRails
4
+ module Redis
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "redis/version"
4
+ require "active_support"
5
+
6
+ module BigRails
7
+ module Redis
8
+ extend ActiveSupport::Autoload
9
+
10
+ autoload :ApplicationExtension
11
+ autoload :ConfigurationDsl
12
+ autoload :Configuration
13
+ autoload :Registry
14
+ end
15
+ end
16
+
17
+ require "big_rails/redis/railtie"
@@ -0,0 +1 @@
1
+ require "big_rails/redis"
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bigrails-redis
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ngan Pham
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-03-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6'
27
+ description:
28
+ email:
29
+ - ngan@users.noreply.github.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.md
35
+ - lib/big_rails/redis.rb
36
+ - lib/big_rails/redis/application_extension.rb
37
+ - lib/big_rails/redis/configuration.rb
38
+ - lib/big_rails/redis/configuration_dsl.rb
39
+ - lib/big_rails/redis/railtie.rb
40
+ - lib/big_rails/redis/registry.rb
41
+ - lib/big_rails/redis/version.rb
42
+ - lib/bigrails-redis.rb
43
+ homepage: https://github.com/bigrails/bigrails-redis
44
+ licenses:
45
+ - MIT
46
+ metadata:
47
+ homepage_uri: https://github.com/bigrails/bigrails-redis
48
+ source_code_uri: https://github.com/BigRails/bigrails-redis
49
+ changelog_uri: https://github.com/bigrails/bigrails-redis/releases
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 2.6.0
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 3.2.32
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Redis connection manager for Rails applications.
69
+ test_files: []