sezaru
Hello,
I have some GenServers that will do some loading during init function using Task.async (so they will not block init and then get the result via handle_info function).
Recently I noticed that for the period that this task is running, the :observer Applications tab, with the app tab in which the caller server is supervised, will freeze and not respond until the task finishes its job. I have other GenServers that start Tasks for other stuff and they don’t show the same behavior.
I also get some errors from appmon during that period:
12:48:14.862 [error] #PID<0.741.0> :gen_server "error_info/7" "gen_server.erl" 889
GenServer :appmon_info terminating
** (MatchError) no match of right hand side value: {:error, {:EXIT, {:badarg, [{:erlang, :element, [2, :undefined], []}, {:appmon_info, :check_sasl_ancestor, 2, [file: 'appmon_info.erl', line: 618]}, {:appmon_info, :maybe_add_child_sasl, 4, [file: 'appmon_info.erl', line: 590]}, {:lists, :foldr, 3, [file: 'lists.erl', line: 1276]}, {:appmon_info, :do_find_proc2, 5, [file: 'appmon_info.erl', line: 497]}, {:appmon_info, :calc_app_tree, 2, [file: 'appmon_info.erl', line: 450]}, {:appmon_info, :do_work, 2, [file: 'appmon_info.erl', line: 308]}, {:appmon_info, :handle_info, 2, [file: 'appmon_info.erl', line: 276]}]}}}
appmon_info.erl:308: :appmon_info.do_work/2
appmon_info.erl:276: :appmon_info.handle_info/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:do_it, {:app, :pipeline, #PID<0.729.0>}}
State: {:state, #PID<0.729.0>, [], #Reference<0.3006373769.2547122179.177556>, [#PID<0.729.0>]}
12:48:14.863 [error] #PID<0.741.0> :proc_lib "crash_report/4" "proc_lib.erl" 508
Process :appmon_info (#PID<0.741.0>) terminating
** (MatchError) no match of right hand side value: {:error, {:EXIT, {:badarg, [{:erlang, :element, [2, :undefined], []}, {:appmon_info, :check_sasl_ancestor, 2, [file: 'appmon_info.erl', line: 618]}, {:appmon_info, :maybe_add_child_sasl, 4, [file: 'appmon_info.erl', line: 590]}, {:lists, :foldr, 3, [file: 'lists.erl', line: 1276]}, {:appmon_info, :do_find_proc2, 5, [file: 'appmon_info.erl', line: 497]}, {:appmon_info, :calc_app_tree, 2, [file: 'appmon_info.erl', line: 450]}, {:appmon_info, :do_work, 2, [file: 'appmon_info.erl', line: 308]}, {:appmon_info, :handle_info, 2, [file: 'appmon_info.erl', line: 276]}]}}}
appmon_info.erl:308: :appmon_info.do_work/2
appmon_info.erl:276: :appmon_info.handle_info/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Initial Call: :appmon_info.init/1
Ancestors: [#PID<0.729.0>, :observer, #PID<0.711.0>, #PID<0.82.0>]
Message Queue Length: 0
Messages: []
Links: [#PID<0.729.0>]
Dictionary: []
Trapping Exits: true
Status: :running
Heap Size: 10958
Stack Size: 27
Reductions: 115365
For completeness, this is more or less what I have:
defmodule Server do
...
@impl GenServer
def init(args),
do: {:ok, State.new(args), {:continue, :load_pipeline}}
@impl GenServer
def handle_continue(:load_pipeline, state) do
Task.async(fn ->
repo = Application.get_env(:database, :bla) |> Keyword.fetch!(:repo)
repo.transaction(
fn repo ->
# Do some work with streams that can take some time
end,
timeout: :infinity
)
end)
{:noreply, state}
end
...
end
Can I do something to help fix this issue?
Thanks.
Trending in Questions
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 9- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
ityonemo
Why not remove the Task.async? Since it’s in a handle_continue, it won’t block the init.
sezaru
Because I need to be able to handle external calls during the work I’m doing inside the Task.
I do other work inside the
handle_continuethat I didn’t show in the code above because it would not be related to the issue. I did try moving the Task to theinitcall and it still shows the same issue.I never had it before, so I’m not sure if I’m doing something wrong or this is a bug with
:observer.ityonemo
I don’t know enough about the observer internals to know for sure, but:
instead of Task.async use Task.start or Task.start_link, async returns a future which it seems like you don’t need (there’s no corresponding Task.await).
instead of Task, i would spawn inside an otp supervisor tree, so Task.Supervised.start or Task.Supervised.start_link
Doing these two things will make your architecture more otp-compliant and possibly help observer out? But again, I am not an expert on observer, so maybe someone else more experienced can comment.
dimitarvp
As @ityonemo said, you are not doing
Task.awaitto correspond with your earlierTask.async. You’re better off just doing one action then send yourself (i.e. the current process) a message that does the next, etc. until your initialisation is completed.sezaru
Thanks for the replies @ityonemo and @dimitarvp.
I’m not doing a
Task.awaitbecause this is running inside a GenServer, and as the documentation says in Task — Elixir v1.20.2 I don’t need aTask.await(the documentation goes as far as saying it is not recommended), it will trigger my matchinghandle_infocall.dimitarvp
I think you are doing it wrong. Let OTP handle itself.
Just don’t use
Task.asyncinsidehandle_continueat all. It will simplify your code and the app should behave properly. However, I have no background in your challenges – or how many other initialisation activities you need.sezaru
Basically I need to load somethings for that process in parallel to receiving call messages, I cannot block the server and wait it to load because of some constrains of my project.
I created a small project just to test this issue in isolation, and I cannot reproduce the issue, basically I just created an empty project (with --sup option), added the bellow GenServer and added it to the application supervisor.
This didn’t freeze my
:observer.I think that actually the issue is not the
Task.async, but maybe the repo.transaction I’m doing inside of it. I will try simulate something similar in my test project and see if I can reproduce the issue.sezaru
So, turns out that the issue was processing the data I’m loading, I do some computations inside an Enum.reduce and this can take some time (it takes ± 5 minutes to process 2kk rows of data). When the process is doing that the observer will freeze.
dimitarvp
You can likely chunk and multiplex the work on all CPU cores.