Skip to content

Commit

Permalink
fix: deep merge changes into resolution context and plug/private to a…
Browse files Browse the repository at this point in the history
…void overriding things
  • Loading branch information
MikaAK committed Sep 13, 2023
1 parent 30ab229 commit 7d98834
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 15 deletions.
3 changes: 2 additions & 1 deletion lib/request_cache/middleware.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ if absinthe_loaded? do
context: Map.update!(
resolution.context,
RequestCache.Config.conn_private_key(),
&Keyword.merge(&1, [request: opts, cache_request?: true])
&Util.deep_merge(&1, request: opts, cache_request?: true)
)
}
else
Expand All @@ -39,6 +39,7 @@ if absinthe_loaded? do

defp ensure_valid_ttl(opts) do
ttl = opts[:ttl] || RequestCache.Config.default_ttl()

Keyword.put(opts, :ttl, ttl)
end
end
Expand Down
36 changes: 23 additions & 13 deletions lib/request_cache/plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -186,24 +186,26 @@ defmodule RequestCache.Plug do
end

defp response_error_and_cached?(%Plug.Conn{status: 200, request_path: path} = conn) when path in @graphql_paths do
gql_resp_success_or_has_known_error?(request_cache_cached_errors(conn), conn.resp_body)
empty_errors? = String.contains?(conn.resp_body, :binary.compile_pattern("\"errors\": []"))
no_errors? = !String.contains?(conn.resp_body, :binary.compile_pattern("\"errors\":"))

empty_errors? or
no_errors? or
gql_resp_has_known_error?(request_cache_cached_errors(conn), conn.resp_body)
end

defp response_error_and_cached?(%Plug.Conn{status: status} = conn) do
conn.private |> IO.inspect
cached_error_codes = request_cache_cached_errors(conn) |> IO.inspect
cached_error_codes = request_cache_cached_errors(conn)

cached_error_codes !== [] and
(cached_error_codes === :all or Plug.Conn.Status.reason_atom(status) in cached_error_codes)
end

defp gql_resp_success_or_has_known_error?([], _resp_body), do: false
defp gql_resp_success_or_has_known_error?(:all, _resp_body), do: false

defp gql_resp_success_or_has_known_error?(cached_errors, resp_body) do
empty_errors? = String.contains?(resp_body, :binary.compile_pattern("\"errors\": []"))
defp gql_resp_has_known_error?([], _resp_body), do: false
defp gql_resp_has_known_error?(:all, _resp_body), do: false

empty_errors? or Enum.any?(cached_errors, &(resp_body =~ to_string(&1)))
defp gql_resp_has_known_error?(cached_errors, resp_body) do
Enum.any?(cached_errors, &(resp_body =~ to_string(&1)))
end

defp conn_request(%Plug.Conn{} = conn) do
Expand All @@ -220,20 +222,22 @@ defmodule RequestCache.Plug do
context = conn.private[:absinthe][:context] || %{}

conn
|> Plug.Conn.put_private(conn_private_key(), enabled?: true)
|> Absinthe.Plug.put_options(context: Map.put(context, conn_private_key(), enabled?: true))
|> deep_merge_to_private(enabled?: true)
|> Absinthe.Plug.put_options(
context: Util.deep_merge(context, %{conn_private_key() => [enabled?: true]})
)
end
else
defp enable_request_cache_for_conn(conn) do
Plug.Conn.put_private(conn, conn_private_key(), enabled?: true)
deep_merge_to_private(conn, enabled?: true)
end
end

def store_request(conn, opts) when is_list(opts) do
if conn.private[conn_private_key()][:enabled?] do
Util.verbose_log("[RequestCache.Plug] Storing REST request in #{conn_private_key()}")

Plug.Conn.put_private(conn, conn_private_key(),
deep_merge_to_private(conn,
cache_request?: true,
request: opts
)
Expand All @@ -252,6 +256,12 @@ defmodule RequestCache.Plug do
RequestCache.Config.conn_private_key()
end

defp deep_merge_to_private(conn, params) do
conn.private[conn_private_key()]
|> Util.deep_merge(params)
|> then(&Plug.Conn.put_private(conn, conn_private_key(), &1))
end

defp log_error(error, conn, opts) do
{:current_stacktrace, stacktrace} = Process.info(self(), :current_stacktrace)

Expand Down
2 changes: 1 addition & 1 deletion lib/request_cache/resolver_middleware.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ if absinthe_loaded? do
context: Map.update!(
resolution.context,
RequestCache.Config.conn_private_key(),
&Keyword.merge(&1, config)
&Util.deep_merge(&1, config)
)
}

Expand Down
21 changes: 21 additions & 0 deletions lib/request_cache/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ defmodule RequestCache.Util do

@moduledoc false

@whitelisted_modules [DateTime, NaiveDateTime, Date, Time, File.Stat, MapSet, Regex, URI, Version]


# def parse_gql_name(query_string) do
# case Regex.run(~r/^(?:query) ([^\({]+(?=\(|{))/, query_string, capture: :all_but_first) do
# [query_name] -> String.trim(query_name)
Expand All @@ -27,4 +30,22 @@ defmodule RequestCache.Util do
Logger.debug(message)
end
end

def deep_merge(list_a, list_b) when is_list(list_a) and is_list(list_b) do
Keyword.merge(list_a, list_b, fn
_k, _, %struct{} = right when struct in @whitelisted_modules -> right
_k, left, right when is_map(left) and is_map(right) -> deep_merge(left, right)
_k, left, right when is_list(left) and is_list(right) -> deep_merge(left, right)
_, _, right -> right
end)
end

def deep_merge(map_a, map_b) do
Map.merge(map_a, map_b, fn
_k, _, %struct{} = right when struct in @whitelisted_modules -> right
_k, left, right when is_map(left) and is_map(right) -> deep_merge(left, right)
_k, left, right when is_list(left) and is_list(right) -> deep_merge(left, right)
_, _, right -> right
end)
end
end

0 comments on commit 7d98834

Please sign in to comment.