Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ These services may need to be configured in order to enable mu-cache support. Ch
## Debugging
Debugging of cache keys is helped by following environment variables:

- `LOG_CACHE_CLEAR_EVENT`: Store cache clear events in the database
- `LOG_CACHE_KEYS`: Logs received cache key to a response
- `LOG_CLEAR_KEYS`: Logs received clear keys either as a response, or explicitly received through ./mu/delta.
1 change: 1 addition & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ end
# 3rd-party users, it should be done in your "mix.exs" file.

config :mu_cache,
log_cache_clear_event: CH.system_boolean("LOG_CACHE_CLEAR_EVENT"),
log_cache_keys: CH.system_boolean("LOG_CACHE_KEYS"),
log_clear_keys: CH.system_boolean("LOG_CLEAR_KEYS")

Expand Down
32 changes: 32 additions & 0 deletions lib/cache/cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,18 @@ defmodule Cache.Registry do
# We have multiple clear_keys and need to update the state for it.
%{cache: cache, caches_by_key: caches_by_key} = state

# IO.inspect(clear_keys, label: "Clearing these keys")
# IO.inspect(cache, label: "Cache before clearing the keys")

cache =
Enum.reduce(clear_keys, cache, fn clear_key, cache ->
keys_to_remove = Map.get(caches_by_key, clear_key, [])
maybe_send_cleared_key_to_database!(keys_to_remove)
cache = Map.drop(cache, keys_to_remove)
cache
end)

# IO.inspect(cache, label: "Cache after clearing the keys")
caches_by_key = Map.drop(caches_by_key, clear_keys)

%{state | cache: cache, caches_by_key: caches_by_key}
Expand Down Expand Up @@ -135,4 +140,31 @@ defmodule Cache.Registry do

%{state | cache: cache}
end

defp maybe_send_cleared_key_to_database!(request_key_to_remove) do
# Write to the database when a cache for a url is cleared
if Application.get_env(:mu_cache, :log_cache_clear_event) do
Enum.map(request_key_to_remove, fn req_key ->
{method, path, query, auth} = req_key
uuid = Support.generate_uuid()
auth_escaped = Support.sparql_escape(auth)
query = """
PREFIX mu: <http://mu.semte.ch/vocabularies/core/>
PREFIX mucache: <http://mu.semte.ch/vocabularies/cache/>
INSERT DATA {
GRAPH<http://mu.semte.ch/application> {
<http://semte.baert.jp.net/cache-clear/v0.1/#{uuid}> a mucache:CacheClear ;
mu:uuid "#{uuid}";
mucache:path "#{path}";
mucache:method "#{method}";
mucache:query "#{query}";
mucache:muAuthAllowedGroups \"\"\"#{auth_escaped}\"\"\";
mucache:muAuthUsedGroups \"\"\"#{auth_escaped}\"\"\".
}
}
"""
Support.update(query)
end)
end
end
end
4 changes: 3 additions & 1 deletion lib/manipulators/cache_key_logger.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ defmodule Manipulators.CacheKeyLogger do
end

defp header_value(headers, header_name) do
header = Enum.find(headers, header_name)
header =
headers
|> Enum.find({nil, "[]"}, &match?({header_name, _}, &1))

if header do
elem(header, 1)
Expand Down
63 changes: 63 additions & 0 deletions lib/support.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Note: this is copied from https://github.com/mu-semtech/mu-elixir-template should be replaced by integrating the template
defmodule Support do
# environment variables
def sparql_endpoint() do
System.get_env("MU_SPARQL_ENDPOINT")
end
def application_graph() do
System.get_env("MU_APPLICATION_GRAPH")
end
def sparql_timeout() do
System.get_env("MU_SPARQL_TIMEOUT")
end
def log_level() do
System.get_env("LOG_LEVEL")
end

# uuid helper
def generate_uuid() do
UUID.uuid4()
end

# graph helper
def graph() do
application_graph()
end

# query helper
def _query_get_URL(escaped_query_string) do
if sparql_timeout() > 0 do
"#{sparql_endpoint()}?query=#{escaped_query_string}&timeout=#{sparql_timeout()}"
else
"#{sparql_endpoint()}?query=#{escaped_query_string}"
end
end

def query(query_string) do
query_string
|> URI.encode
|> _query_get_URL
|> HTTPoison.get!([{"Accept", "application/json"}])
|> ( &( &1.body ) ).()
|> Poison.decode!
end

def update(query_string) do
HTTPoison.post!(
sparql_endpoint(),
[
"query=" <>
URI.encode_www_form(query_string) <>
"&format=" <> URI.encode_www_form("application/sparql-results+json")
],
["Content-Type": "application/x-www-form-urlencoded"],
[]
)
|> ( &( &1.body ) ).()
|> Poison.decode!
end

def sparql_escape(value) do
String.replace(value, "\"", "\\\"")
end
end
4 changes: 3 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ defmodule UsePlugProxy.Mixfile do
{:plug_cowboy, "~> 2.4.1"},
{:dialyxir, "~> 1.0", only: [:dev], runtime: false},
{:credo, "~> 1.5", only: [:dev, :test], runtime: false},
{:poison, "~> 2.0"}
{:poison, "~> 2.0"},
{:uuid, "~> 1.1"},
{:httpoison, "~> 1.5"}
]
end
end