Ole Spaarmann
Ole Spaarmann

Reputation: 16749

How to use Phoenix with a different db driver than ecto? For example OrientDB

I'm trying to wrap my head around how to use Phoenix with a different DB Driver and without Ecto, since I want to connect to OrientDB. There is a binary driver called MarcoPolo and strangely enough I was able to create a worker pool using poolboy to connect to it - but not just a simple connection. I'm still very new to Elixir.

This is what I did:

Define the dependency in mix.exs

  defp deps do
    [{:phoenix, "~> 1.0.3"},
     {:phoenix_html, "~> 2.1"},
     {:phoenix_live_reload, "~> 1.0", only: :dev},
     {:cowboy, "~> 1.0"},
     {:poolboy, "~> 1.5"},
     {:marco_polo, "~> 0.2"}
   ]
  end

Create a module for my repo in lib/myapp/orientdb_repo.ex

defmodule MyApp.OrientRepo do
  use MarcoPolo
end

Define the worker in lib/myapp.ex

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      # Start the endpoint when the application starts
      supervisor(MyApp.Endpoint, []),
      # Here you could define other workers and supervisors as children
      # worker(MyApp.Worker, [arg1, arg2, arg3]),
      worker(MyApp.OrientRepo, [user: "admin", password: "admin", connection: {:db, "database", :graph}])
    ]

    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end

But when I try to start the server it tells me that MarcoPolo is undefined:

== Compilation error on file lib/myapp/orientdb_repo.ex ==
** (UndefinedFunctionError) undefined function: MarcoPolo.__using__/1
    MarcoPolo.__using__([])
    (stdlib) erl_eval.erl:669: :erl_eval.do_apply/6
    (elixir) lib/kernel/parallel_compiler.ex:100: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/8

I thought this should be available since I included MarcoPolo. Probably it is something very simple but I just don't get it...

Upvotes: 1

Views: 462

Answers (1)

arathunku
arathunku

Reputation: 1159

It looks like MarcoPolo doesn't have__using__ macro which expands into start_link, stop_link and other GenServer methods.

It's how Ecto does it in the repo - https://github.com/elixir-lang/ecto/blob/3d39d89523eb4852725799db7eb7869715bd8c0d/lib/ecto/repo.ex#L60

If you want to use MarcoPolo you need to provide that by yourself

lib/MyRepo/orient_repo.ex                                                                                                                                         
defmodule MyRepo.OrientRepo do
  require MarcoPolo

  def start_link(opts\\[]) do
    MarcoPolo.start_link opts
  end

  #  ..and many more, take a look at GenServer
end

and when you're starting the worker, pass all the arguments as one array

worker(MyRepo.OrientRepo, [[user: "admin", password: "admin", connection: {:db, "database", :graph}]])

In my case it results in error:

[error] OrientDB TCP connect error (localhost:2424): connection refused

because I don't have OrientDB on my computer. Another option is to start the MarcoPolo directly as @whatyouhide said in the comments.

More details about use are at: http://elixir-lang.org/getting-started/alias-require-and-import.html#use

Upvotes: 1

Related Questions