Elixir Phoenix - 使用任务模块上传多个图像

时间:2017-05-28 12:07:24

标签: asynchronous elixir phoenix-framework

这是我的第一个Elixir / Phoenix项目,到目前为止我很喜欢它。可悲的是,我还没有多少时间真正探索任务/并发或otp。

我有一张表格,一次最多可以上传7张图片。我最初设置代码同步上传这些,1乘1.我的下一次迭代是尝试并行运行这些,这可以在下面的upload_many函数中看到。

上传7 x 250kb图像所花费的总时间并没有缩短(约15秒),重新写入,这清楚地表明我做错了什么。

我真的很感激任何帮助或建议。

defmodule MyApp.S3 do
  def upload_many(params, keys) do
    ops = [max_concurrency: System.schedulers_online() * 3, timeout: 20000]

    keys
    # [{"passport_image_url", file}, {"drivers_license_url", file2}, ...]
    |> Task.async_stream(&upload/1, ops)
    |> Enum.to_list()
  end

  def upload({url_key, image_params}) do
    unique_filename = get_unique_filename(image_params.filename)

    case File.read(image_params.path) do
      {:error, _} ->
        {:error, url_key, "file could not be read"}
      {:ok, image_binary} ->
        # returns image url string or error
        res = put_object(unique_filename, image_binary)
        IO.inspect url_key
        Tuple.insert_at(res, 1, url_key)
        # {:ok, url_key, url}
    end
  end


  def get_unique_filename(filename) do
    file_uuid = UUID.uuid4(:hex)
    image_filename = filename
    "#{file_uuid}-#{image_filename}"
  end


  def put_object(unique, image_binary) do
    bucket = System.get_env("BUCKET_NAME")

    res = ExAws.S3.put_object(bucket, unique, image_binary)
    |> ExAws.request!

    case res do
      %{status_code: 200} ->
        {:ok, image_url(unique, bucket)}
      _ ->
        {:error, "error uploading to S3"}
    end
  end

  def image_url(unique, bucket) do
    "https://#{bucket}.s3.amazonaws.com/#{bucket}/#{unique}"
  end
end

我已经编写了一个上传7张图片的测试,并且使用ExAws模拟了Process.sleep(4000); %{status_code: 200}请求,并使用 test "updates startpack with many file uploads", %{conn: conn, user: user} do startpack = Repo.insert! %Startpack{user_id: user.id} image_upload = %Plug.Upload{path: "test/fixtures/foxy.png", filename: "foxy.png"} # possible solution for multiple fields images = %{ "passport_image" => image_upload, "vehicle_insurance_image" => image_upload, "box_rental_image" => image_upload, "equipment_rental_image" => image_upload, "p45_image" => image_upload, "schedule_d_letter_image" => image_upload, "loan_out_company_cert_image" => image_upload } valid = Map.merge(@valid_attrs, images) with_mock ExAws, [request!: fn(_) -> Process.sleep(4000) %{status_code: 200} end] do conn = put conn, startpack_path(conn, :update, startpack), startpack: valid assert redirected_to(conn) == startpack_path(conn, :show, startpack) startpack = Repo.get_by(Startpack, user_id: user.id) assert startpack.passport_url end end 进行了操作。使用4秒模拟,它可以在4秒内同时执行7个任务,但如果我删除模拟并上传真实文件,则需要大约15秒钟。这是测试:

<field src="/my_module/static/src/img/my_image.png"/>

0 个答案:

没有答案