▶ mix new fun_with_processes --module FWP
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/fun_with_processes.ex
* creating test
* creating test/test_helper.exs
* creating test/fun_with_processes_test.exs
defmodule FWP.MixProject do
# ...
defp deps do
[
{:httpoison, "~> 1.0"}
]
end
end
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir)
iex(3)> file = Utils.open_file_for(url, dir)
iex(4)>
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir)
iex(3)> file = Utils.open_file_for(url, dir)
iex(4)> {:ok, resp} = HTTPoison.get(url)
{:ok, %HTTPoison.Response{body: ...}}
iex(5)>
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir)
iex(3)> file = Utils.open_file_for(url, dir)
iex(4)> {:ok, resp} = HTTPoison.get(url)
{:ok, %HTTPoison.Response{body: ...}}
iex(5)>
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir)
iex(3)> file = Utils.open_file_for(url, dir)
iex(4)> {:ok, resp} = HTTPoison.get(url)
{:ok, %HTTPoison.Response{body: ...}}
iex(5)> IO.binwrite(file, resp.body)
iex(6)> File.close(file)
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir)
iex(3)> file = Utils.open_file_for(url, dir)
iex(4)> {:ok, resp} = HTTPoison.get(url)
{:ok, %HTTPoison.Response{body: ...}}
iex(5)> IO.binwrite(file, resp.body)
iex(6)> File.close(file)
▶ ls -l downloads
total 1
-rw-r--r-- 1 pawel.dawczak pawel.dawczak 8109 Jul 21 21:43 logo.png
▶ ls -l downloads
total 1
-rw-r--r-- 1 pawel.dawczak pawel.dawczak 8109 Jul 21 21:43 logo.png
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> HTTPoison.get(url, [], stream_to: self())
{:ok, %HTTPoison.AsyncResponse{id: #Reference<0.1.2.3>}}
iex(3)>
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> HTTPoison.get(url, [], stream_to: self())
{:ok, %HTTPoison.AsyncResponse{id: #Reference<0.1.2.3>}}
iex(3)>
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> HTTPoison.get(url, [], stream_to: self())
{:ok, %HTTPoison.AsyncResponse{id: #Reference<0.1.2.3>}}
iex(3)> flush
%HTTPoison.AsyncStatus{code: 200, id: #Reference<0.1.2.3>}
%HTTPoison.AsyncHeaders{...}
%HTTPoison.AsyncChunk{
chunk: <<137, 80, 78, 71, ...>>,
id: #Reference<0.1.2.3>
}
%HTTPoison.AsyncChunk{
chunk: <<29, 5, 22, 220, ...>>,
id: #Reference<0.1.2.3>
}
...
%HTTPoison.AsyncEnd{id: #Reference<0.1.2.3>}
:ok
iex(1)> url = "https://elixir-lang.org/images/logo/logo.png"
iex(2)> HTTPoison.get(url, [], stream_to: self())
{:ok, %HTTPoison.AsyncResponse{id: #Reference<0.1.2.3>}}
iex(3)> flush
%HTTPoison.AsyncStatus{code: 200, id: #Reference<0.1.2.3>}
%HTTPoison.AsyncHeaders{...}
%HTTPoison.AsyncChunk{
chunk: <<137, 80, 78, 71, ...>>,
id: #Reference<0.1.2.3>
}
%HTTPoison.AsyncChunk{
chunk: <<29, 5, 22, 220, ...>>,
id: #Reference<0.1.2.3>
}
...
%HTTPoison.AsyncEnd{id: #Reference<0.1.2.3>}
:ok
defmodule FWP.Downloader.StreamServer do
# ...
def init(opts) do
file_url = Keyword.fetch!(opts, :file_url)
dir = Keyword.fetch!(opts, :dir)
state = %{
file_url: file_url,
dir: dir,
file_path: nil,
file: nil
}
{:ok, state, {:continue, :init_download}}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def init(opts) do
file_url = Keyword.fetch!(opts, :file_url)
dir = Keyword.fetch!(opts, :dir)
state = %{
file_url: file_url,
dir: dir,
file_path: nil,
file: nil
}
{:ok, state, {:continue, :init_download}}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def init(opts) do
file_url = Keyword.fetch!(opts, :file_url)
dir = Keyword.fetch!(opts, :dir)
state = %{
file_url: file_url,
dir: dir,
file_path: nil,
file: nil
}
{:ok, state, {:continue, :init_download}}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_continue(:init_download, state) do
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_continue(:init_download, state) do
{:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self())
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_continue(:init_download, state) do
{:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self())
file_path = Utils.file_path_for(state.file_url, state.dir)
file = Utils.open_file(file_path)
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_continue(:init_download, state) do
{:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self())
file_path = Utils.file_path_for(state.file_url, state.dir)
file = Utils.open_file(file_path)
new_state = %{state | file_path: file_path, file: file}
{:noreply, new_state}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do
Logger.debug("Receiving chunk...")
IO.binwrite(state.file, chunk)
{:noreply, state}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do
Logger.debug("Receiving chunk...")
IO.binwrite(state.file, chunk)
{:noreply, state}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do
Logger.debug("Receiving chunk...")
IO.binwrite(state.file, chunk)
{:noreply, state}
end
def handle_info(%HTTPoison.AsyncEnd{}, state) do
Logger.info("That's all folks!")
File.close(state.file)
{:stop, :normal, state}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do
Logger.debug("Receiving chunk...")
IO.binwrite(state.file, chunk)
{:noreply, state}
end
def handle_info(%HTTPoison.AsyncEnd{}, state) do
Logger.info("That's all folks!")
File.close(state.file)
{:stop, :normal, state}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do
Logger.debug("Receiving chunk...")
IO.binwrite(state.file, chunk)
{:noreply, state}
end
def handle_info(%HTTPoison.AsyncEnd{}, state) do
Logger.info("That's all folks!")
File.close(state.file)
{:stop, :normal, state}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do
Logger.debug("Receiving chunk...")
IO.binwrite(state.file, chunk)
{:noreply, state}
end
def handle_info(%HTTPoison.AsyncEnd{}, state) do
Logger.info("That's all folks!")
File.close(state.file)
{:stop, :normal, state}
end
def handle_info(msg, state) do
Logger.debug("Received: #{inspect(msg)}")
{:noreply, state}
end
end
iex(3)> FWP.Downloader.StreamServer.start_link(file_url: url, dir: dir)
{:ok, #PID<0.198.0>}
iex(4)>
iex(3)> FWP.Downloader.StreamServer.start_link(file_url: url, dir: dir)
{:ok, #PID<0.198.0>}
iex(4)>
21:26:54.267 [debug] Received: %HTTPoison.AsyncStatus{..., id: #Reference<1>}
21:26:54.270 [debug] Received: %HTTPoison.AsyncHeaders{..., id: #Reference<1>}
21:26:54.275 [debug] Receiving chunk…
...
21:26:54.638 [info] That's all folks!
▶ ls -l downloads
total 2
-rw-r--r-- 1 pawel.dawczak pawel.dawczak 8109 Jul 21 21:43 logo.png
-rw-r--r-- 1 pawel.dawczak pawel.dawczak 115K Jul 21 21:56 phoenix.png
▶ ls -l downloads
total 2
-rw-r--r-- 1 pawel.dawczak pawel.dawczak 8109 Jul 21 21:43 logo.png
-rw-r--r-- 1 pawel.dawczak pawel.dawczak 115K Jul 21 21:56 phoenix.png
defmodule FWP.Downloader.StreamServerTest do
# ...
@tag :capture_log
test "accepts chunks and writes them to the file" do
url = "http://foo.com/test-success.txt"
file_path = Utils.file_path_for("test-success.txt", @test_dir)
File.rm_rf!(file_path)
Process.flag(:trap_exit, true)
{:ok, server} =
StreamServer.start_link(file_url: url, dir: @test_dir, engine: HTTPMock)
send(server, %HTTPoison.AsyncChunk{chunk: [?H, ?e]})
send(server, %HTTPoison.AsyncChunk{chunk: [?l]})
send(server, %HTTPoison.AsyncChunk{chunk: [?l, ?o]})
send(server, %HTTPoison.AsyncEnd{})
assert_receive {:EXIT, ^server, :normal}
assert File.exists?(file_path)
assert File.read!(file_path) == "Hello"
end
end
defmodule FWP.Downloader.StreamServerTest do
# ...
@tag :capture_log
test "accepts chunks and writes them to the file" do
url = "http://foo.com/test-success.txt"
file_path = Utils.file_path_for("test-success.txt", @test_dir)
File.rm_rf!(file_path)
Process.flag(:trap_exit, true)
{:ok, server} =
StreamServer.start_link(file_url: url, dir: @test_dir, engine: HTTPMock)
send(server, %HTTPoison.AsyncChunk{chunk: [?H, ?e]})
send(server, %HTTPoison.AsyncChunk{chunk: [?l]})
send(server, %HTTPoison.AsyncChunk{chunk: [?l, ?o]})
send(server, %HTTPoison.AsyncEnd{})
assert_receive {:EXIT, ^server, :normal}
assert File.exists?(file_path)
assert File.read!(file_path) == "Hello"
end
end
defmodule FWP.Downloader.StreamServerTest do
# ...
@tag :capture_log
test "accepts chunks and writes them to the file" do
url = "http://foo.com/test-success.txt"
file_path = Utils.file_path_for("test-success.txt", @test_dir)
File.rm_rf!(file_path)
Process.flag(:trap_exit, true)
{:ok, server} =
StreamServer.start_link(file_url: url, dir: @test_dir, engine: HTTPMock)
send(server, %HTTPoison.AsyncChunk{chunk: [?H, ?e]})
send(server, %HTTPoison.AsyncChunk{chunk: [?l]})
send(server, %HTTPoison.AsyncChunk{chunk: [?l, ?o]})
send(server, %HTTPoison.AsyncEnd{})
assert_receive {:EXIT, ^server, :normal}
assert File.exists?(file_path)
assert File.read!(file_path) == "Hello"
end
end
defmodule FWP.Downloader.StreamServerTest do
# ...
@tag :capture_log
test "accepts chunks and writes them to the file" do
url = "http://foo.com/test-success.txt"
file_path = Utils.file_path_for("test-success.txt", @test_dir)
File.rm_rf!(file_path)
Process.flag(:trap_exit, true)
{:ok, server} =
StreamServer.start_link(file_url: url, dir: @test_dir, engine: HTTPMock)
send(server, %HTTPoison.AsyncChunk{chunk: [?H, ?e]})
send(server, %HTTPoison.AsyncChunk{chunk: [?l]})
send(server, %HTTPoison.AsyncChunk{chunk: [?l, ?o]})
send(server, %HTTPoison.AsyncEnd{})
assert_receive {:EXIT, ^server, :normal}
assert File.exists?(file_path)
assert File.read!(file_path) == "Hello"
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def init(opts) do
file_url = Keyword.fetch!(opts, :file_url)
dir = Keyword.fetch!(opts, :dir)
state = %{
file_url: file_url,
dir: dir,
file_path: nil,
file: nil
}
{:ok, state, {:continue, :init_download}}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def init(opts) do
file_url = Keyword.fetch!(opts, :file_url)
dir = Keyword.fetch!(opts, :dir)
engine = Keyword.get(opts, :engine, HTTPoison)
state = %{
file_url: file_url,
dir: dir,
engine: engine,
file_path: nil,
file: nil
}
{:ok, state, {:continue, :init_download}}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_continue(:init_download, state) do
{:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self())
file_path = Utils.file_path_for(state.file_url, state.dir)
file = Utils.open_file(file_path)
new_state = %{state | file_path: file_path, file: file}
{:noreply, new_state}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_continue(:init_download, state) do
{:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self())
file_path = Utils.file_path_for(state.file_url, state.dir)
file = Utils.open_file(file_path)
new_state = %{state | file_path: file_path, file: file}
{:noreply, new_state}
end
end
defmodule FWP.Downloader.StreamServer do
# ...
def handle_continue(:init_download, state) do
{:ok, _} = state.engine.get(state.file_url, [], stream_to: self())
file_path = Utils.file_path_for(state.file_url, state.dir)
file = Utils.open_file(file_path)
new_state = %{state | file_path: file_path, file: file}
{:noreply, new_state}
end
end
▶ mix test
▶ mix test
.
Finished in 0.07 seconds
1 test, 0 failures
Randomized with seed 941275
▶ mix test
.
Finished in 0.07 seconds
1 test, 0 failures
Randomized with seed 941275
@pawel_dawczak @pdawczak
https://github.com/pdawczak/fun_with_processes

Fun with processes - lightning talk

  • 3.
    ▶ mix newfun_with_processes --module FWP * creating README.md * creating .formatter.exs * creating .gitignore * creating mix.exs * creating config * creating config/config.exs * creating lib * creating lib/fun_with_processes.ex * creating test * creating test/test_helper.exs * creating test/fun_with_processes_test.exs
  • 4.
    defmodule FWP.MixProject do #... defp deps do [ {:httpoison, "~> 1.0"} ] end end
  • 5.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir) iex(3)> file = Utils.open_file_for(url, dir) iex(4)>
  • 6.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir) iex(3)> file = Utils.open_file_for(url, dir) iex(4)> {:ok, resp} = HTTPoison.get(url) {:ok, %HTTPoison.Response{body: ...}} iex(5)>
  • 7.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir) iex(3)> file = Utils.open_file_for(url, dir) iex(4)> {:ok, resp} = HTTPoison.get(url) {:ok, %HTTPoison.Response{body: ...}} iex(5)>
  • 8.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir) iex(3)> file = Utils.open_file_for(url, dir) iex(4)> {:ok, resp} = HTTPoison.get(url) {:ok, %HTTPoison.Response{body: ...}} iex(5)> IO.binwrite(file, resp.body) iex(6)> File.close(file)
  • 9.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> dir = Application.get_env(:fun_with_processes, :downloads_dir) iex(3)> file = Utils.open_file_for(url, dir) iex(4)> {:ok, resp} = HTTPoison.get(url) {:ok, %HTTPoison.Response{body: ...}} iex(5)> IO.binwrite(file, resp.body) iex(6)> File.close(file)
  • 10.
    ▶ ls -ldownloads total 1 -rw-r--r-- 1 pawel.dawczak pawel.dawczak 8109 Jul 21 21:43 logo.png
  • 11.
    ▶ ls -ldownloads total 1 -rw-r--r-- 1 pawel.dawczak pawel.dawczak 8109 Jul 21 21:43 logo.png
  • 19.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> HTTPoison.get(url, [], stream_to: self()) {:ok, %HTTPoison.AsyncResponse{id: #Reference<0.1.2.3>}} iex(3)>
  • 20.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> HTTPoison.get(url, [], stream_to: self()) {:ok, %HTTPoison.AsyncResponse{id: #Reference<0.1.2.3>}} iex(3)>
  • 21.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> HTTPoison.get(url, [], stream_to: self()) {:ok, %HTTPoison.AsyncResponse{id: #Reference<0.1.2.3>}} iex(3)> flush %HTTPoison.AsyncStatus{code: 200, id: #Reference<0.1.2.3>} %HTTPoison.AsyncHeaders{...} %HTTPoison.AsyncChunk{ chunk: <<137, 80, 78, 71, ...>>, id: #Reference<0.1.2.3> } %HTTPoison.AsyncChunk{ chunk: <<29, 5, 22, 220, ...>>, id: #Reference<0.1.2.3> } ... %HTTPoison.AsyncEnd{id: #Reference<0.1.2.3>} :ok
  • 22.
    iex(1)> url ="https://elixir-lang.org/images/logo/logo.png" iex(2)> HTTPoison.get(url, [], stream_to: self()) {:ok, %HTTPoison.AsyncResponse{id: #Reference<0.1.2.3>}} iex(3)> flush %HTTPoison.AsyncStatus{code: 200, id: #Reference<0.1.2.3>} %HTTPoison.AsyncHeaders{...} %HTTPoison.AsyncChunk{ chunk: <<137, 80, 78, 71, ...>>, id: #Reference<0.1.2.3> } %HTTPoison.AsyncChunk{ chunk: <<29, 5, 22, 220, ...>>, id: #Reference<0.1.2.3> } ... %HTTPoison.AsyncEnd{id: #Reference<0.1.2.3>} :ok
  • 23.
    defmodule FWP.Downloader.StreamServer do #... def init(opts) do file_url = Keyword.fetch!(opts, :file_url) dir = Keyword.fetch!(opts, :dir) state = %{ file_url: file_url, dir: dir, file_path: nil, file: nil } {:ok, state, {:continue, :init_download}} end end
  • 24.
    defmodule FWP.Downloader.StreamServer do #... def init(opts) do file_url = Keyword.fetch!(opts, :file_url) dir = Keyword.fetch!(opts, :dir) state = %{ file_url: file_url, dir: dir, file_path: nil, file: nil } {:ok, state, {:continue, :init_download}} end end
  • 25.
    defmodule FWP.Downloader.StreamServer do #... def init(opts) do file_url = Keyword.fetch!(opts, :file_url) dir = Keyword.fetch!(opts, :dir) state = %{ file_url: file_url, dir: dir, file_path: nil, file: nil } {:ok, state, {:continue, :init_download}} end end
  • 26.
    defmodule FWP.Downloader.StreamServer do #... def handle_continue(:init_download, state) do end end
  • 27.
    defmodule FWP.Downloader.StreamServer do #... def handle_continue(:init_download, state) do {:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self()) end end
  • 28.
    defmodule FWP.Downloader.StreamServer do #... def handle_continue(:init_download, state) do {:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self()) file_path = Utils.file_path_for(state.file_url, state.dir) file = Utils.open_file(file_path) end end
  • 29.
    defmodule FWP.Downloader.StreamServer do #... def handle_continue(:init_download, state) do {:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self()) file_path = Utils.file_path_for(state.file_url, state.dir) file = Utils.open_file(file_path) new_state = %{state | file_path: file_path, file: file} {:noreply, new_state} end end
  • 30.
  • 31.
    defmodule FWP.Downloader.StreamServer do #... def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do Logger.debug("Receiving chunk...") IO.binwrite(state.file, chunk) {:noreply, state} end end
  • 32.
    defmodule FWP.Downloader.StreamServer do #... def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do Logger.debug("Receiving chunk...") IO.binwrite(state.file, chunk) {:noreply, state} end end
  • 33.
    defmodule FWP.Downloader.StreamServer do #... def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do Logger.debug("Receiving chunk...") IO.binwrite(state.file, chunk) {:noreply, state} end def handle_info(%HTTPoison.AsyncEnd{}, state) do Logger.info("That's all folks!") File.close(state.file) {:stop, :normal, state} end end
  • 34.
    defmodule FWP.Downloader.StreamServer do #... def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do Logger.debug("Receiving chunk...") IO.binwrite(state.file, chunk) {:noreply, state} end def handle_info(%HTTPoison.AsyncEnd{}, state) do Logger.info("That's all folks!") File.close(state.file) {:stop, :normal, state} end end
  • 35.
    defmodule FWP.Downloader.StreamServer do #... def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do Logger.debug("Receiving chunk...") IO.binwrite(state.file, chunk) {:noreply, state} end def handle_info(%HTTPoison.AsyncEnd{}, state) do Logger.info("That's all folks!") File.close(state.file) {:stop, :normal, state} end end
  • 36.
    defmodule FWP.Downloader.StreamServer do #... def handle_info(%HTTPoison.AsyncChunk{chunk: chunk}, state) do Logger.debug("Receiving chunk...") IO.binwrite(state.file, chunk) {:noreply, state} end def handle_info(%HTTPoison.AsyncEnd{}, state) do Logger.info("That's all folks!") File.close(state.file) {:stop, :normal, state} end def handle_info(msg, state) do Logger.debug("Received: #{inspect(msg)}") {:noreply, state} end end
  • 37.
  • 38.
    iex(3)> FWP.Downloader.StreamServer.start_link(file_url: url,dir: dir) {:ok, #PID<0.198.0>} iex(4)> 21:26:54.267 [debug] Received: %HTTPoison.AsyncStatus{..., id: #Reference<1>} 21:26:54.270 [debug] Received: %HTTPoison.AsyncHeaders{..., id: #Reference<1>} 21:26:54.275 [debug] Receiving chunk… ... 21:26:54.638 [info] That's all folks!
  • 39.
    ▶ ls -ldownloads total 2 -rw-r--r-- 1 pawel.dawczak pawel.dawczak 8109 Jul 21 21:43 logo.png -rw-r--r-- 1 pawel.dawczak pawel.dawczak 115K Jul 21 21:56 phoenix.png
  • 40.
    ▶ ls -ldownloads total 2 -rw-r--r-- 1 pawel.dawczak pawel.dawczak 8109 Jul 21 21:43 logo.png -rw-r--r-- 1 pawel.dawczak pawel.dawczak 115K Jul 21 21:56 phoenix.png
  • 44.
    defmodule FWP.Downloader.StreamServerTest do #... @tag :capture_log test "accepts chunks and writes them to the file" do url = "http://foo.com/test-success.txt" file_path = Utils.file_path_for("test-success.txt", @test_dir) File.rm_rf!(file_path) Process.flag(:trap_exit, true) {:ok, server} = StreamServer.start_link(file_url: url, dir: @test_dir, engine: HTTPMock) send(server, %HTTPoison.AsyncChunk{chunk: [?H, ?e]}) send(server, %HTTPoison.AsyncChunk{chunk: [?l]}) send(server, %HTTPoison.AsyncChunk{chunk: [?l, ?o]}) send(server, %HTTPoison.AsyncEnd{}) assert_receive {:EXIT, ^server, :normal} assert File.exists?(file_path) assert File.read!(file_path) == "Hello" end end
  • 45.
    defmodule FWP.Downloader.StreamServerTest do #... @tag :capture_log test "accepts chunks and writes them to the file" do url = "http://foo.com/test-success.txt" file_path = Utils.file_path_for("test-success.txt", @test_dir) File.rm_rf!(file_path) Process.flag(:trap_exit, true) {:ok, server} = StreamServer.start_link(file_url: url, dir: @test_dir, engine: HTTPMock) send(server, %HTTPoison.AsyncChunk{chunk: [?H, ?e]}) send(server, %HTTPoison.AsyncChunk{chunk: [?l]}) send(server, %HTTPoison.AsyncChunk{chunk: [?l, ?o]}) send(server, %HTTPoison.AsyncEnd{}) assert_receive {:EXIT, ^server, :normal} assert File.exists?(file_path) assert File.read!(file_path) == "Hello" end end
  • 46.
    defmodule FWP.Downloader.StreamServerTest do #... @tag :capture_log test "accepts chunks and writes them to the file" do url = "http://foo.com/test-success.txt" file_path = Utils.file_path_for("test-success.txt", @test_dir) File.rm_rf!(file_path) Process.flag(:trap_exit, true) {:ok, server} = StreamServer.start_link(file_url: url, dir: @test_dir, engine: HTTPMock) send(server, %HTTPoison.AsyncChunk{chunk: [?H, ?e]}) send(server, %HTTPoison.AsyncChunk{chunk: [?l]}) send(server, %HTTPoison.AsyncChunk{chunk: [?l, ?o]}) send(server, %HTTPoison.AsyncEnd{}) assert_receive {:EXIT, ^server, :normal} assert File.exists?(file_path) assert File.read!(file_path) == "Hello" end end
  • 47.
    defmodule FWP.Downloader.StreamServerTest do #... @tag :capture_log test "accepts chunks and writes them to the file" do url = "http://foo.com/test-success.txt" file_path = Utils.file_path_for("test-success.txt", @test_dir) File.rm_rf!(file_path) Process.flag(:trap_exit, true) {:ok, server} = StreamServer.start_link(file_url: url, dir: @test_dir, engine: HTTPMock) send(server, %HTTPoison.AsyncChunk{chunk: [?H, ?e]}) send(server, %HTTPoison.AsyncChunk{chunk: [?l]}) send(server, %HTTPoison.AsyncChunk{chunk: [?l, ?o]}) send(server, %HTTPoison.AsyncEnd{}) assert_receive {:EXIT, ^server, :normal} assert File.exists?(file_path) assert File.read!(file_path) == "Hello" end end
  • 48.
    defmodule FWP.Downloader.StreamServer do #... def init(opts) do file_url = Keyword.fetch!(opts, :file_url) dir = Keyword.fetch!(opts, :dir) state = %{ file_url: file_url, dir: dir, file_path: nil, file: nil } {:ok, state, {:continue, :init_download}} end end
  • 49.
    defmodule FWP.Downloader.StreamServer do #... def init(opts) do file_url = Keyword.fetch!(opts, :file_url) dir = Keyword.fetch!(opts, :dir) engine = Keyword.get(opts, :engine, HTTPoison) state = %{ file_url: file_url, dir: dir, engine: engine, file_path: nil, file: nil } {:ok, state, {:continue, :init_download}} end end
  • 50.
    defmodule FWP.Downloader.StreamServer do #... def handle_continue(:init_download, state) do {:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self()) file_path = Utils.file_path_for(state.file_url, state.dir) file = Utils.open_file(file_path) new_state = %{state | file_path: file_path, file: file} {:noreply, new_state} end end
  • 51.
    defmodule FWP.Downloader.StreamServer do #... def handle_continue(:init_download, state) do {:ok, _} = HTTPoison.get(state.file_url, [], stream_to: self()) file_path = Utils.file_path_for(state.file_url, state.dir) file = Utils.open_file(file_path) new_state = %{state | file_path: file_path, file: file} {:noreply, new_state} end end
  • 52.
    defmodule FWP.Downloader.StreamServer do #... def handle_continue(:init_download, state) do {:ok, _} = state.engine.get(state.file_url, [], stream_to: self()) file_path = Utils.file_path_for(state.file_url, state.dir) file = Utils.open_file(file_path) new_state = %{state | file_path: file_path, file: file} {:noreply, new_state} end end
  • 53.
  • 54.
    ▶ mix test . Finishedin 0.07 seconds 1 test, 0 failures Randomized with seed 941275
  • 55.
    ▶ mix test . Finishedin 0.07 seconds 1 test, 0 failures Randomized with seed 941275
  • 56.