Пример использования Elixir postgrex с poolboy в Windows завершается с «модулем DBConnection.Poolboy недоступен» - PullRequest
0 голосов
/ 04 декабря 2018

Я изучаю использование Elixir для быстрого импорта данных Postgres смешанных типов (CSV, JSON).Будучи новичком в Elixir, я следую примеру, приведенному в видеоролике youtube «Быстрый импорт и экспорт с Elixir и Postgrex - витрина пакета Elixir Hex» (https://www.youtube.com/watch?v=YQyKRXCtq4s). Приложение базового микса работает до момента, когда будет представлен Poolboyт.е. Postgrex успешно загружает записи в базу данных, используя одно соединение.

Когда я пытаюсь следовать конфигурации Poolboy и проверить ее, запустив

FastIoWithPostgrex.import ("./data_with_ids.txt ")

в iex или командной строке я получаю следующую ошибку, для которой не могу определить причину (имя пользователя и пароль удалены):

** (UndefinedFunctionError) function DBConnection.Poolboy.child_spec/1 is 
undefined (module DBConnection.Poolboy is not available)
DBConnection.Poolboy.child_spec({Postgrex.Protocol, [types: 
Postgrex.DefaultTypes, name: :pg, pool: DBConnection.Poolboy, pool_size: 4, 
hostname: "localhost", port: 9000, username: "XXXX", password: 
"XXXX", database: "ASDDataAnalytics-DEV"]})
(db_connection) lib/db_connection.ex:383: DBConnection.start_link/2
(fast_io_with_postgrex) lib/fast_io_with_postgrex.ex:8: 
FastIoWithPostgrex.import/1

Я запускаю это в Windows 10, подключаясь к серверу PostgreSQL 10.x через локальный туннель SSH. Вот файл lib / fast_io_with_postgrex.ex:

defmodule FastIoWithPostgrex do
  @moduledoc """
  Documentation for FastIoWithPostgrex.
  """

  def import(filepath) do

    {:ok, pid} = Postgrex.start_link(name: :pg,
      pool: DBConnection.Poolboy,
      pool_size: 4,
      hostname: "localhost",
      port: 9000,
      username: "XXXX", password: "XXXX", database: "ASDDataAnalytics-DEV")

    File.stream!(filepath)
    |> Stream.map(fn line ->
        [id_str, word] = line |> String.trim |> String.split("\t", trim: true, parts: 2)
        {id, ""} = Integer.parse(id_str)
        [id, word]
    end)
    |> Stream.chunk_every(10_000, 10_000, [])
    |> Task.async_stream(fn word_rows ->
      Enum.each(word_rows, fn word_sql_params ->
        Postgrex.transaction(:pg, fn conn ->
          IO.inspect Postgrex.query!(conn, "INSERT INTO asdda_dataload.words (id, word) VALUES ($1, $2)", word_sql_params)
#        IO.inspect Postgrex.query!(pid, "INSERT INTO asdda_dataload.words (id, word) VALUES ($1, $2)", word_sql_params)    
        end , pool: DBConnection.Poolboy, pool_timeout: :infinity, timeout: :infinity) 
      end)
    end, timeout: :infinity)
    |> Stream.run

  end # def import(file)
end

Вот файл mix.exs:

defmodule FastIoWithPostgrex.MixProject do
  use Mix.Project

  def project do
    [
      app: :fast_io_with_postgrex,
      version: "0.1.0",
      elixir: "~> 1.7",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger, :poolboy, :connection]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", 
tag: "0.1.0"},

      {:postgrex, "~>0.14.1"},
      {:poolboy, "~>1.5.1"}
    ]
  end
end

Вот файл config / config.exs:

# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.

use Mix.Config

config :fast_io_with_postgrex, :postgrex,
  database: "ASDDataAnalytics-DEV",
  username: "XXXX",
  password: "XXXX",
  name: :pg,
  pool: DBConnection.Poolboy,
  pool_size: 4

# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for
# 3rd-party users, it should be done in your "mix.exs" file.

# You can configure your application as:
#
#     config :fast_io_with_postgrex, key: :value
#
# and access this configuration in your application as:
#
#     Application.get_env(:fast_io_with_postgrex, :key)
#
# You can also configure a 3rd-party app:
#
#     config :logger, level: :info
#

# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
#     import_config "#{Mix.env()}.exs"

Любая помощь в поиске причины этой ошибки будет принята с благодарностью!

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Спасибо, используя ваш совет, я получил оригинальный пример для работы, понизив версии зависимостей в файле mix.exs и добавив зависимость к более ранней версии db_connection:

   # Run "mix help deps" to learn about dependencies.
   defp deps do
     [
       # {:dep_from_hexpm, "~> 0.3.0"},
       # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"},

      {:postgrex, "0.13.5"},
      {:db_connection, "1.1.3"},
      {:poolboy, "~>1.5.1"}
 ]
 end

Я также будупопробуйте предложить изменить код для замены Poolboy на новый менеджер пула в более поздней версии db_connection, чтобы увидеть, работает ли он также.

Я уверен, что в архитектуру было много мыслейИзменения, однако я должен сказать, что с точки зрения того, почему Poolboy когда-то был так популярен, очень мало, но в последней версии db_connection он даже не поддерживается как тип соединения.

0 голосов
/ 05 декабря 2018

Я не хотел вдаваться в подробности того, как это не работает, но этот пример немного стар, и что poolboy 1.5.1 вы получаете с deps.get от 2015 .и пример использует elixir 1.4

Кроме того, если вы увидите mix.exs депс Postgrex, вы заметите, что ваша только что установленная библиотека lib (1.14) зависит от elixir_ecto/db_connection 2.x

The код, на который вы ссылаетесь использует Postgres 1.13.x, который зависит от {:db_connection, "~> 1.1"}.Так что я ожидаю несовместимости.

Я бы поиграл с версиями библиотек, которые вы видите в файле code mix.lock примеров, версией эликсира, если бы я хотел, чтобы это работало.

Может бытьпопробуйте сначала понизить версию Postgrex примерно до этого времени (возможно, между 0.12.2 и заблокированной версией примера).

Кроме того, версия elixir может сыграть здесь, отметьте this

Привет!

  • веселиться

РЕДАКТИРОВАТЬ:

Вы можете использовать DBConnection.ConnectionPool вместо Poolboy и получить путьиспользуя последние версии postgrex и elixir, не уверены в разнице в производительности, но вы можете сравнить, просто сделайте это:

на config/config.exs (проверьте, нужны ли вам пароли и т. д.)

config :fast_io_with_postgrex, :postgrex,
  database: "fp",
  name: :pg,
  pool: DBConnection.ConnectionPool,
  pool_size: 4

И в lib/fast_io_with.....ex замените обе Postgrex.start_link(... строки на:

{:ok, pid} = Application.get_env(:fast_io_with_postgrex, :postgrex)
          |> Postgrex.start_link

Это даст мне:

mix run -e 'FastIoWithPostgrex.import("./data_with_ids.txt")'
1.76s user 0.69s system 106% cpu 2.294 total

на Postgrex 0.14.1 и Elixir 1.7.3

...