Skip to content

Commit

Permalink
Make Redis an optional dependency. Handle URL resolution gracefully i…
Browse files Browse the repository at this point in the history
…f Redis is unavailable.
  • Loading branch information
stefansundin committed Feb 22, 2022
1 parent a122fb2 commit e6ee86f
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 10 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ To deploy to Kubernetes, see [kubernetes/README.md](kubernetes/README.md).

A Docker image is available on [Docker Hub](https://hub.docker.com/r/stefansundin/rssbox) and [Amazon ECR](https://gallery.ecr.aws/stefansundin/rssbox).

**Note:** Redis is now an optional dependency! It is only used for the URL resolution feature (turned off on the public Heroku instance).

#### Heroku

If you need to re-provision redis, or you didn't use the deploy button above to provision the app initially, then you need to make sure to set the maxmemory policy:
Expand Down
6 changes: 1 addition & 5 deletions app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1562,11 +1562,7 @@
end

get "/health" do
if $redis.ping != "PONG"
return [500, "Redis error"]
end
rescue Redis::CannotConnectError => e
return [500, "Redis connection error"]
return [200, ""]
end

if ENV["GOOGLE_VERIFICATION_TOKEN"]
Expand Down
4 changes: 3 additions & 1 deletion app/url.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module App
class URL
URL_RESOLUTION_DISABLED = (ENV["URL_RESOLUTION_DISABLED"] == "true")
URL_RESOLUTION_DISABLED = ($redis.nil? || ENV["URL_RESOLUTION_DISABLED"] == "true")

@@cache = {}

Expand Down Expand Up @@ -51,6 +51,8 @@ def self.resolve(urls, force=false)
end
threads.map(&:join)
return nil
rescue Redis::BaseConnectionError
return nil
end

private
Expand Down
47 changes: 43 additions & 4 deletions config/initializers/20-redis.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,46 @@
# frozen_string_literal: true

begin
$redis = Redis.new
rescue
puts "Failed to connect to redis!"
# Monkeypatch redis to throttle it from attempting to connect more often than once a second

class Redis
class ThrottledConnectError < BaseConnectionError
end

class Client
@@last_connect_error = nil

# https://github.com/redis/redis-rb/blob/v4.6.0/lib/redis/client.rb#L379-L399
def establish_connection
if @@last_connect_error && Time.now < @@last_connect_error + 1
raise ThrottledConnectError, "Throttled connection attempt to Redis on #{location}"
end

server = @connector.resolve.dup

@options[:host] = server[:host]
@options[:port] = Integer(server[:port]) if server.include?(:port)

@connection = @options[:driver].connect(@options)
@pending_reads = 0
rescue TimeoutError,
SocketError,
Errno::EADDRNOTAVAIL,
Errno::ECONNREFUSED,
Errno::EHOSTDOWN,
Errno::EHOSTUNREACH,
Errno::ENETUNREACH,
Errno::ENOENT,
Errno::ETIMEDOUT,
Errno::EINVAL => error

@@last_connect_error = Time.now
raise CannotConnectError, "Error connecting to Redis on #{location} (#{error.class})"
end
end
end

if ENV.has_key?("REDIS_URL")
$redis = Redis.new({
reconnect_attempts: 0,
})
end

0 comments on commit e6ee86f

Please sign in to comment.