artemeff / redis

Redis commands for Elixir
MIT License
358 stars 63 forks source link

exredis - ssl and tls support #84

Open zoltan-nz opened 1 year ago

zoltan-nz commented 1 year ago

Hi There,

Thanks for the great work and maintaining the redis library.

We are using exredis and just wondering how it can be configured to support tls/ssl connection. Heroku is using tls/ssl on Redis, and exredis previous configuration cannot connect to the secure Redis instance using the rediss protocol.

Could you please suggest a solution?

tcocca commented 1 year ago

@zoltan-nz Did you find a solution for this?

artemeff commented 1 year ago

exredis is just a wrapper around eredis, you can safely migrate to eredis and use ssl. or even better - start using redix

tcocca commented 1 year ago

Can you share some examples of how to switch from Exredis to eredis?

Currently we set this up like so:

children = [
  worker(Mailservice.RedisRepo, [:redis])
]

defmodule Mailservice.RedisRepo do
  def start_link(name) do
    connection = Application.get_env(:exredis, :url)
    client = Exredis.start_using_connection_string(connection)
    true = Process.register(client, name)
    {:ok, client}
  end
end

And use it like this in different places

case Exredis.query_pipe(:redis, query) do
      ["OK", "1"] -> {:ok, "MISS", data, id}
      _    -> {:error, Mailservice.CacheService.StorageError}
    end

defp get_from_cache(id) do
    {:ok, "HIT", Exredis.query(:redis, ["GET", id]), id}
  end
artemeff commented 1 year ago

they have a lot of documentation

zoltan-nz commented 1 year ago

Thank you, folks. I had never used Elixir before, so I invested a few days to be able to run the project, upgrade a few packages and also migrated to redix. Still using an older Elixir (v1.11). My naive upgrade from the old code to the new:

Old code:

# The code is using the env variable to switch from the library to a mocked version in the test
@redis Application.get_env(:cipher, :redis_client)

...
  defp redis_client do
    conn_string = System.get_env("REDIS_URL") || "redis://root:@0.0.0.0:6379/10"
    @redis.start_using_connection_string(conn_string)
  end

  defp get_cached_item(key) do
    client = redis_client
    item = @redis.Api.get(client, key)
    @redis.stop(client)

    item
  end

  defp set_cached_item(key, item) do
    client = redis_client
    @redis.Api.set(client, key, item)
    @redis.stop(client)

    item
  end

Using redix:

defp get_redis_connection() do
    {:ok, conn} =
      case System.get_env("REDIS_URL") do
        nil ->
          # REDIS_URL is not defined, use localhost in development
          @redis.start_link("redis://localhost:6370")

        url ->
          # REDIS_URL is defined, use ssh options
          @redis.start_link(url,
            timeout: :infinity,
            ssl: true,
            socket_opts: [verify: :verify_none]
          )
      end

    conn
  end

  defp get_cached_item(key) do
    conn = get_redis_connection()
    {:ok, item} = @redis.command(conn, ["GET", key])
    @redis.stop(conn)

    item
  end

  defp set_cached_item(key, item) do
    conn = get_redis_connection()
    @redis.command(conn, ["SET", key, item, "EX", 1_000_000])
    @redis.stop(conn)

    item
  end