I this this simple genserver:
def handle_info(:tick, items) do
items2 = do_job(items)
tick()
{:noreply, items2}
end
In "do_job" I need to a) iterate throug items, b) make an http request which can take long and c) depending on a response, update a database and finish with the current item by removing it from "items" or merely update the database:
def do_job(items) do
Enum.each(items, fn(a) -> # or Enum.map
Task.start fn ->
case external_request(a) do
{:terminate, data} ->
Repo.update(....)
remove(a) # send a message to this GenServer to remove itself
{:continue, data} ->
Repo.update(....)
end
end
end)
end
1) Do I have to return a new value -- updated list/state -- from "do_job" to allow my GenServer work properly?
2) If so, how? I can't return an updated state from "do_job" because I create a Task for each item because it requires sending an http request and CRUD operation in a database. That's why an asyncronous task.
3) And in general, GenServer manages the state variable by itself, in this case it's "items". What allows GenServer to understand how to update it? Let's consider this code:
def add(a) do
GenServer.cast(__MODULE__, {:add, a}) # what/who utilizes this return value?
end
def remove(....) do
# ....
def handle_cast({:add, a}, items) do
{:noreply, [a | items]} # what/who utilizes this return value?
end
A client doesn't use a returned value from "add" or "remove", thus it gets thrown away. Nonetheless, when a client calls "add" 3 times, this GenServer will have 3 items in a list. But why? How does GenServer handle that?
tickmessage before the first one's HTTP requests have finished? With the method you're proposing, you may end up processing the same item multiple times even if it returns{:terminate, _}every time. You probably want to makehandle_infowait for all requests but run the HTTP requests in parallel (useTask.asyncandTask.await). - Dogbertcaston it (which actives some custom data transformation in it) ? - elpddev