I made mistake to use redis to store my user api JWT token, after deploying on server .
unfortunately, I have no time to replace redis with other thing and am forced to fix this on redis.
it is my redis benchmark info:
# Clients
connected_clients:28223
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
I just store my Token on redis ad after user request on 1 day my redis has this error: Redix the connection to Redis is closed, then system is down .
How can I fix this?
this is my code to use Redis:
defmodule BankError.Extera.Redis do
def connect_to_redis do
case Redix.start_link() do
{:ok, conn} ->
Redix.pipeline(conn, [["AUTH","PASSWORD"]]) # will be changed
{:ok, conn, :connect_to_redis}
_ -> {:error, :connect_to_redis}
end
end
def insert_or_update_into_redis(table_name, record_id, params, expire_time) do
with {:ok, conn, :connect_to_redis} <- connect_to_redis() do
conn |>
Redix.pipeline([
List.flatten(
[
"HMSET",
# String.to_charlist(table_name <> record_id)
"#{table_name}#{record_id}"
], BankError.map_to_single_list_with_string_key(params)
),
[
"EXPIRE",
table_name <> record_id,
expire_time
]
])
{:ok, :insert_or_update_into_redis}
end
end
@doc """
show all fields of redis record
"""
def get_all_fields_of_record_redis(table_name, record_id) do
with {:ok, conn, :connect_to_redis} <- connect_to_redis() do
conn
|> Redix.pipeline!([["HGETALL",table_name <> record_id]])
else
n ->
{:error, :get_all_fields_of_record_redis, n}
end
end
@doc """
show singel fields of redis record
"""
def get_singel_field_record_of_redis(table_name, record_id, field_name) do
with {:ok, conn, :connect_to_redis} <- connect_to_redis() do
conn
|> Redix.pipeline!([["HGET","#{table_name}#{record_id}", field_name]])
else
n ->
{:error, :get_singel_field_record_of_redis, n}
end
end
@doc """
delete redis record
"""
def delete_record_of_redis(table_name, record_id) do
with {:ok, conn, :connect_to_redis} <- connect_to_redis(),
{:ok, :get_all_fields_of_record_redis, record} <- convert_output_of_get_all_fields_of_record_redis(get_all_fields_of_record_redis(table_name, record_id)) do
conn
|> Redix.pipeline([["HDEL", table_name <> record_id] ++ record])
{:ok, :delete_record_of_redis, "The record is deleted"}
else
n -> n
end
end
def convert_output_of_get_all_fields_of_record_redis(params) do
case params do
[[]] -> {:error, :get_all_fields_of_record_redis, "The data concerned doesn't exist"}
[] -> {:error, :get_all_fields_of_record_redis, "The data concerned doesn't exist"}
[nil] -> {:error, :get_all_fields_of_record_redis, "The data concerned doesn't exist"}
n ->
[record | _] = n
{:ok, :get_all_fields_of_record_redis, record}
end
end
@doc """
delete singel field of redis record
"""
def delete_field_of_record_redis(table_name, record_id, field_name) do
with {:ok, conn, :connect_to_redis} <- connect_to_redis(),
{:ok, :get_all_fields_of_record_redis, _record} <- convert_output_of_get_all_fields_of_record_redis(get_all_fields_of_record_redis(table_name, record_id)),
{:ok, [1]} <- Redix.pipeline(conn, [["HDEL", table_name <> record_id, field_name]]) do
{:ok, :delete_field_of_record_redis}
else
{:ok, [0]} -> {:error, :delete_field_of_record_redis, "The field you need doesn't exist"}
n -> n
end
end
@doc """
get expire time of singel record
"""
def get_expire_time_of_redis(table_name, record_id) do
with {:ok, conn, :connect_to_redis} <- connect_to_redis(),
{:ok, :get_expire_time_error_handler, expire_time} <- get_expire_time_error_handler(conn, table_name, record_id) do
{:ok, :get_expire_time, expire_time}
else
n -> n
end
end
defp get_expire_time_error_handler(conn, table_name, record_id) do
case Redix.pipeline(conn, [["TTL",table_name <> record_id]]) do
{:ok, [-2]} ->
{:error, :get_expire_time_error_handler, "The data concerned doesn't exist"}
{:ok, [expire_time]} ->
{:ok, :get_expire_time_error_handler, expire_time}
_ ->
{:error, :get_expire_time_error_handler, "The data concerned doesn't exist"}
end
end
@doc """
get expire time of singel record
"""
def update_expire_time_of_redis(table_name, record_id, expire_time) do
with {:ok, conn, :connect_to_redis} <- connect_to_redis(),
{:ok, :update_expire_time_of_error_handler, msg} <- update_expire_time_of_error_handler(conn, table_name, record_id, expire_time) do
{:ok, :update_expire_time_of_redis, msg}
else
n -> n
end
end
defp update_expire_time_of_error_handler(conn, table_name, record_id, expire_time) do
case Redix.pipeline(conn, [["EXPIRE",table_name <> record_id, expire_time]]) do
{:ok, [0]} ->
{:error, :update_expire_time_of_error_handler, "The data concerned doesn't exist"}
{:ok, [1]} ->
{:ok, :update_expire_time_of_error_handler, "The data concerned was updated"}
_ ->
{:error, :update_expire_time_of_error_handler, "The data concerned doesn't exist"}
end
end
end
and my Supervisor on redis
defmodule BankError.Extera.RedisSup do
@pool_size 1000
def child_spec(_args) do
# Specs for the Redix connections.
children =
for i <- 0..(@pool_size - 1) do
Supervisor.child_spec({Redix, name: :"redix_#{i}"}, id: {Redix, i})
end
# Spec for the supervisor that will supervise the Redix connections.
%{
id: RedixSupervisor,
type: :supervisor,
start: {Supervisor, :start_link, [children, [strategy: :one_for_one]]}
}
end
for example I use Redis like this:
in my controller:
def brands(conn, %{"category_id" => category_id, "token" => token}) do
with {:ok, :is_token_validated?, id} <- UserQuery.is_token_validated?(token),
{:ok, :api_user_check_mobile_and_subscribe, _user_info, _subscriber_info} <- UserQuery.api_user_check_mobile_and_subscribe(id) do
conn
|> put_status(200)
|> json(%{brands: Error.show_error_brands(category_id)})
end
end
and Redix code:
def is_token_validated?(token) do
with {:ok, claims} <- verify_token(token),
{:ok, %{id: id}} <- get_id_from_jwt_climes(claims),
{:ok, :get_all_fields_of_record_redis, record_of_user_token} <- BankError.Extera.Redis.convert_output_of_get_all_fields_of_record_redis(BankError.Extera.Redis.get_all_fields_of_record_redis("user_token", id)),
%{"token" => redis_token} <- BankError.list_to_map(record_of_user_token),
{:ok, :change_password_token_on_check} <- change_password_token_on_check(token, redis_token) do
{:ok, :is_token_validated?, id}
else
_ ->
{:error, :is_token_validated?}
end
end
Thanks