I am working on a code that will ping an external API every 15 minutes, to retrieve the response and store it in the database.
def get_forecast(city) do
  app_id = My.api_key()
  query_params = URI.encode_query(%{"q" => city, "APPID" => app_id})
  url =
  "https://api.weather.org/data/2.5/forecast?" <> query_params
    case HTTPoison.get(url) do
      {:ok, %HTTPoison.Response{status_code: 200} = response} ->
        {:ok, Jason.decode!(response.body)}
      {:ok, %HTTPoison.Response{status_code: status_code}} ->
        {:error, {:status, status_code}}
      {:error, reason} ->
        {:error, reason}
    end
end
I am running this inside a Task, and that Task is running inside a Genserver.
In application.ex
  use Application
  def start(_type, _args) do
    children = [
      # Starts a worker by calling: FsiIntegration.Worker.start_link(arg)
      # {FsiIntegration.Worker, arg}
      {Task.Supervisor, name: Integration.TaskSupervisor, restart: :transient,  max_restarts: 3, max_seconds: 4000}
    ]
    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: Integration.Supervisor]
    Supervisor.start_link(children, opts)
  end
In genserver file
defmodule Integration.FsiServer do
  use GenServer
  @timeout 15000
  #Public API
  def start_task do
    GenServer.start_link(__MODULE__, %{ref: nil}, name: __MODULE__)
  end
  def execute_task(pid) do
    GenServer.call(pid, {:execute, @timeout})
  end
  #Callbacks API
  def init(state) do
    {:ok, state}
  end
  # In this case the task is already running, so we just return :ok.
  def handle_call({:execute, _task_timeout}, _from, %{ref: ref} = state) when is_reference(ref) do
    {:reply, :ok, state}
  end
  # The task is not running yet, so let's start it.
  def handle_call({:execute, task_timeout}, _from, %{ref: nil} = state) do
    IO.inspect state
    task =
      Task.Supervisor.start_child(Integration.TaskSupervisor, fn ->**
       {:ok, _} = IntegrationGet.get_forecast("city")**
     end)
    {:reply, :ok, %{state | ref: task.ref}}
  end
  # The task completed successfully
  def handle_info({ref, answer}, %{ref: ref} = state) do
    Process.demonitor(ref, [:flush])
    {:noreply, %{state | ref: nil}}
  end
  # The task failed
  def handle_info({:DOWN, ref, :process, _pid, _reason}, %{ref: ref} = state) do
    {:noreply, %{state | ref: nil}}
  end
end
My questions are :
I know I have to improve on the below code. Can you guys me insight on how to make this better
  use Application
  def start(_type, _args) do
    children = [
      # Starts a worker by calling: FsiIntegration.Worker.start_link(arg)
      # {FsiIntegration.Worker, arg}
      {Task.Supervisor, name: Integration.TaskSupervisor, restart: :transient,  max_restarts: 3, max_seconds: 4000}
    ]
    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: Integration.Supervisor]
    Supervisor.start_link(children, opts)
  end
  def handle_call({:execute, task_timeout}, _from, %{ref: nil} = state) do
    IO.inspect state
    task =
      Task.Supervisor.start_child(Integration.TaskSupervisor, fn ->
       {:ok, _} = IntegrationGet.get_forecast("city")
     end)
    {:reply, :ok, %{state | ref: task.ref}}
  end
- 
The time interval between restarts I have set max_seconds to 5 seconds. But the restart happens immediately.
 - 
Is Task.Supervisor.start_child is good for making an external API request. Just it will make a single API request in this case. Or I have to go for async_nolink or async under Task module
My use case is request an external API and store the response in the DB. 




















