2
votes

I have mix task mix fetch.btc on phoenix app (lib/mix/tasks/fetch.btc.ex):

defmodule Mix.Tasks.Fetch.Btc do
  use Mix.Task

  def run(_args) do
    res = HTTPoison.get!("https://blockchain.info/ticker")
    IO.inspect(res)
  end
end

When I run mix fetch.btc I got error:

** (ArgumentError) argument error
    (stdlib) :ets.lookup_element(:hackney_config, :mod_metrics, 2)
    PROJ_DIR/deps/hackney/src/hackney_metrics.erl:27: :hackney_metrics.get_engine/0
    PROJ_DIR/deps/hackney/src/hackney_connect.erl:78: :hackney_connect.create_connection/5
    PROJ_DIR/deps/hackney/src/hackney_connect.erl:47: :hackney_connect.connect/5
    PROJ_DIR/deps/hackney/src/hackney.erl:330: :hackney.request/5
    lib/httpoison/base.ex:787: HTTPoison.Base.request/6
    lib/httpoison.ex:128: HTTPoison.request!/5
    lib/mix/tasks/fetch.btc.ex:14: Mix.Tasks.Fetch.Btc.run/1
    (mix) lib/mix/task.ex:331: Mix.Task.run_task/3
    (mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
    (elixir) lib/code.ex:767: Code.require_file/2

But in my controller this code res = HTTPoison.get!("https://blockchain.info/ticker") is work success!

Info:

hackney: 1.15.1
httpoison: 1.5.0
phoenix: 1.4.3
  1. What am I doing wrong?
  2. What is right way make http request in mix task?
2

2 Answers

4
votes

The code in you controller runs when the application and all it’s dependencies are already started. mix tasks are run within :mix application which obviously does not start :hackney by default.

All you need is to ensure it’s started / start it manually:

def run(_args) do
  # ⇓⇓⇓⇓⇓⇓⇓ THIS ⇓⇓⇓⇓⇓⇓⇓
  Application.ensure_all_started(:hackney)
  # ⇑⇑⇑⇑⇑⇑⇑ THIS ⇑⇑⇑⇑⇑⇑⇑

  res = HTTPoison.get!("https://blockchain.info/ticker")
  IO.inspect(res)
end
1
votes

You can also use HTTPoison.start() before the actual call. That will also work, if you dont want to start the hackney application every time in mix file or if you do not want to start using Application.