Closed thbar closed 1 year ago
Une idée est d'aller faire du "fuzzing" en local, en enlevant le correctif, pour essayer de reproduire le souci.
Je ne sais pas si j'ai fait n'importe quoi dans ce code, et c'est bien possible, mais quelque chose m'interpelle ici (version plus réduite de ce qu'avait fait @AntoineAugusti sur https://github.com/whitfin/cachex/issues/304).
J'ai la sensation que l'appel à "expire" va attendre que les autres fetchs soient terminés avant de s'exécuter, ce qui me paraît au final un peu normal.
Mais ça semble un peu un autre problème que ce qu'on a constaté au final : le TTL serait temporairement remonté comme étant à nil, mais uniquement le temps que l'autre transaction se termine ???
Output:
❯ elixir other-repro.exs
Round...
#PID<0.203.0> - ~T[10:53:21.024554] calling fetch...
#PID<0.204.0> - ~T[10:53:21.024621] calling fetch...
#PID<0.205.0> - ~T[10:53:21.024641] calling fetch...
#PID<0.206.0> I'm computing...
#PID<0.203.0> - ~T[10:53:26.037074] commit - setting expire
#PID<0.203.0> - ~T[10:53:26.039463] commit - expire set
#PID<0.204.0> - ~T[10:53:26.038401] we have nil TTL (return is {:ok, 42})
#PID<0.205.0> - ~T[10:53:26.038444] we have nil TTL (return is {:ok, 42})
#PID<0.203.0> - ~T[10:53:26.039543] we have TTL 100000 (return is {:commit, 42})
Round...
#PID<0.208.0> - ~T[10:53:27.046076] calling fetch...
#PID<0.208.0> - ~T[10:53:27.046262] we have TTL 98993 (return is {:ok, 42})
#PID<0.209.0> - ~T[10:53:27.046323] calling fetch...
#PID<0.210.0> - ~T[10:53:27.046380] calling fetch...
#PID<0.209.0> - ~T[10:53:27.046418] we have TTL 98993 (return is {:ok, 42})
#PID<0.210.0> - ~T[10:53:27.046468] we have TTL 98993 (return is {:ok, 42})
Mix.install([{:cachex, github: "whitfin/cachex", branch: "main"}])
defmodule Test do
require Logger
def cache_name, do: :cache
def func(_x) do
:timer.sleep(5_000)
{:commit, 42}
end
end
Cachex.start_link(Test.cache_name(), [])
cache_key = "hello-world"
1..2
|> Enum.each(fn _ ->
IO.puts("\nRound...\n")
:timer.sleep(1_000)
1..3
|> Task.async_stream(
fn _ ->
IO.puts("#{self() |> inspect()} - #{Time.utc_now() |> inspect()} calling fetch...")
result =
with {:commit, val} <- Cachex.fetch(Test.cache_name(), cache_key, &Test.func/1) do
IO.puts(
"#{self() |> inspect()} - #{Time.utc_now() |> inspect()} commit - setting expire"
)
{:ok, true} = Cachex.expire(Test.cache_name(), cache_key, :timer.seconds(100))
IO.puts("#{self() |> inspect()} - #{Time.utc_now() |> inspect()} commit - expire set")
{:commit, val}
else
{:ok, val} ->
{:ok, val}
x ->
IO.inspect(x)
[]
end
{:ok, ttl} = Cachex.ttl(Test.cache_name(), cache_key)
if is_nil(ttl) do
IO.puts(
"#{self() |> inspect()} - #{Time.utc_now() |> inspect()} we have nil TTL (return is #{result |> inspect})"
)
else
IO.puts(
"#{self() |> inspect()} - #{Time.utc_now() |> inspect()} we have TTL #{ttl} (return is #{result |> inspect})"
)
end
end,
max_concurrency: 100,
timeout: :infinity
)
|> Enum.each(fn _ -> :ok end)
end)
Petite tentative de reproduction en local avec le code de l'application, mais pour l'instant je n'aboutis pas à une situation où le TTL serait de façon permanente à nil. Je conserve toutefois le code (à démarrer avec mix run scripts/repro.exs
ça servira sûrement !
# scripts/repro.exs
Logger.configure(level: :info)
defmodule Report do
def test do
{:ok, ttl} = Cachex.ttl(:transport, "home-index-stats")
if is_nil(ttl) do
IO.inspect("#{self() |> inspect} TTL=#{ttl |> inspect}")
else
IO.puts("TTL=#{ttl |> inspect}")
end
end
end
1..2_000_000
|> Task.async_stream(
fn _ ->
Transport.Cache.API.fetch(
"home-index-stats",
fn ->
TransportWeb.PageController.compute_home_index_stats()
end,
:timer.seconds(1)
)
Report.test()
end,
max_concurrency: 1_0_000,
timeout: :infinity
)
|> Enum.each(fn _ -> :ok end)
En ayant travaillé sur #2960, je retrouve bien le souci via iex, ce qui est "rassurant":
❯ clever ssh --alias prod-site
# SNIP
iex(node@XYZ)1> Cachex.keys(:transport)
{:ok,
["unavailabilities_dataset_12", "home-index-stats",
"unavailabilities_dataset_347"]}
iex(node@XYZ)2> Cachex.ttl(
ttl(cache, key, options \\ [])
iex(node@XYZ)2> Cachex.ttl(:transport, "home-index-stats")
{:ok, nil}
Pour le déclencher en pratique il m'a "suffit" de faire un refresh de la home page plusieurs fois.
Devrait être résolu par https://github.com/etalab/transport-site/pull/2961
Je re-crée une méta-issue car le problème pourra nous affecter non seulement sur le proxy mais ailleurs.
Éléments relatifs directement sur le proxy
Eléments qui pourraient nous impacter ailleurs
Solutions alternatives