Closed vasumur closed 9 months ago
Do you have a reproduction case? I can't do much here without.
I can put together one, but this seems to be the same as https://github.com/whitfin/cachex/issues/318, which is closed.
In that case should i be waiting for a new version of Cachex etc to use?
There is a pending Cachex release in the next few weeks, so I have some time to fix anything here if it needs it!
@whitfin Appreciate you help in looking in this.
I am having trouble putting together the exact condition that raises this error. In the application many of these key refreshes are running database queries etc. I suspect something to do with the timing and/or order in which the caches are created.
The scenario as in the code is here in this sample code
https://github.com/vasumur/cachex_warmer_test
The error happens while putting the key into :cache1 (that is the scenario in my app), it says that cache1 is not available yet thought that was the first one in the list of caches.
@vasumur I've glanced through that project, I can sit down more later if needed.
I'm not sure if this is something else; you mentioned that the issue is with :cache1
but there are no warmers registered with that cache. Are you sure it's not that your web app is trying to access that cache before it's created? If this is the case, you need to place your caches earlier in the Supervision tree than whatever it is that's calling :cache1
(I noticed they're at the end).
Yes it is the cache1 that gets the no cache error. And the place where it gets the error is in that "initialize_app" in application.ex file.
Apologies for getting back late.
@whitfin
I was able to simulate this and the changes are posted in the git repository
https://github.com/vasumur/cachex_warmer_test
If you run the code with the below MIX_ENV value, you will get the error I was referring to.
MIX_ENV=vn_dev iex -S mix phx.server
Where as running with the below command (even skipping the MIX_ENV as well) works fine.
MIX_ENV=dev iex -S mix phx.server
The Erland and Elixir versions I used are as below (and also in the .tool-versions file in the repository).
erlang 26.0.2 elixir 1.15.2-otp-26
Hi @vasumur!
I took a look at your example:
** (Mix) Could not start application cachex_warmer_test: CachexWarmerTest.Application.start(:normal, []) returned an error: shutdown: failed to start child: CachexWarmerTestWeb.Endpoint
** (EXIT) an exception was raised:
** (UndefinedFunctionError) function Phoenix.LiveReloader.Socket.child_spec/1 is undefined (module Phoenix.LiveReloader.Socket is not available)
Phoenix.LiveReloader.Socket.child_spec([endpoint: CachexWarmerTestWeb.Endpoint])
(phoenix 1.7.10) lib/phoenix/endpoint/supervisor.ex:117: anonymous fn/4 in Phoenix.Endpoint.Supervisor.socket_children/2
(elixir 1.14.5) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix 1.7.10) lib/phoenix/endpoint/supervisor.ex:116: Phoenix.Endpoint.Supervisor.socket_children/2
(phoenix 1.7.10) lib/phoenix/endpoint/supervisor.ex:81: Phoenix.Endpoint.Supervisor.init/1
(stdlib 5.1) supervisor.erl:330: :supervisor.init/1
(stdlib 5.1) gen_server.erl:962: :gen_server.init_it/2
(stdlib 5.1) gen_server.erl:917: :gen_server.init_it/6
(stdlib 5.1) proc_lib.erl:241: :proc_lib.init_p_do_apply/3
This happens if I comment out the called to initialize_app/1
, however this crash is being masked by the assertion crashing after calling Cachex:
{:ok, true} = Cachex.put(:cache1, "some", "value")
The cache is being terminated because your application tree is failing to start properly, so when you try call it it's unavailable (which is why you get :no_cache
). So I think maybe this is a misdirected error and there's nothing wrong with your cache?
Of course I know this is just a sample project so if it's not the case in your real use case I'm happy to look further!
Hi @vasumur!
I took a look at your example:
** (Mix) Could not start application cachex_warmer_test: CachexWarmerTest.Application.start(:normal, []) returned an error: shutdown: failed to start child: CachexWarmerTestWeb.Endpoint ** (EXIT) an exception was raised: ** (UndefinedFunctionError) function Phoenix.LiveReloader.Socket.child_spec/1 is undefined (module Phoenix.LiveReloader.Socket is not available) Phoenix.LiveReloader.Socket.child_spec([endpoint: CachexWarmerTestWeb.Endpoint]) (phoenix 1.7.10) lib/phoenix/endpoint/supervisor.ex:117: anonymous fn/4 in Phoenix.Endpoint.Supervisor.socket_children/2 (elixir 1.14.5) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3 (phoenix 1.7.10) lib/phoenix/endpoint/supervisor.ex:116: Phoenix.Endpoint.Supervisor.socket_children/2 (phoenix 1.7.10) lib/phoenix/endpoint/supervisor.ex:81: Phoenix.Endpoint.Supervisor.init/1 (stdlib 5.1) supervisor.erl:330: :supervisor.init/1 (stdlib 5.1) gen_server.erl:962: :gen_server.init_it/2 (stdlib 5.1) gen_server.erl:917: :gen_server.init_it/6 (stdlib 5.1) proc_lib.erl:241: :proc_lib.init_p_do_apply/3
This happens if I comment out the called to
initialize_app/1
, however this crash is being masked by the assertion crashing after calling Cachex:{:ok, true} = Cachex.put(:cache1, "some", "value")
The cache is being terminated because your application tree is failing to start properly, so when you try call it it's unavailable (which is why you get
:no_cache
). So I think maybe this is a misdirected error and there's nothing wrong with your cache?Of course I know this is just a sample project so if it's not the case in your real use case I'm happy to look further!
My mistake, I was too happy to see that no_cache error and submitted this. Should have checked further.
Regardless the issue with the warmers are present in my application. Still trying to find out why the :cache1 (though it doesn't have warmers) is still not initialized.
When the below statement in Application.ex returns, can i assume that all the caches (which are in the children list) are initialized?
ret = Supervisor.start_link(children, opts)
I'm a little confused by this issue. If :cache1
has no warmers, then what is allowing you to say that warmers are the thing breaking the cache?
Are you adding warmers to some other cache? Are you sure your warmers actually function correctly and aren't crashing on startup (thus stopping your supervision tree)?
The fact that :cache1
is not starting means that your supervision tree is being unwound, the same as your sample project - I can't really say why without seeing it. If you're saying that adding a warmer to another cache is causing it, then it's almost guaranteed to be some crash in your warming code (because it runs for the first time on cache startup). There's simply no case that :cache1
would randomly die because you added a cache warmer to another cache; there's zero interaction between them other than the supervision tree.
When the below statement in Application.ex returns, can i assume that all the caches (which are in the children list) are initialized?
Yes, linking a cache does not return until all tables are initialized, all services are initialized, all hooks started, all necessary warmers are run, etc.
Thanks @whitfin. I found the issue with the warmer where at times it is not providing the list of tuples and fixed it. That corrected the problem. Appreciate your help with this.
I got distracted with the error on a cache which is not even related to warmer. Will close this ticket
Using Cachex 3.6 version and here is the runtime environment details for the application