Failed save to database

Hello!
Git Repository here.
I have a problem with saving data to database. I use mongodb_ecto adapter, when I try save it through iex console I can do it:

iex(1)> Friends.PersonController.save()
START SAVING
SAVED

09:58:17.706 [debug] QUERY OK db=0.4ms
INSERT coll="people" document=[age: 11, _id: #BSON.ObjectId<5b027c190d1a8f0f042d5600>] []
:ok

or

iex(1)> person = %Friends.Person{}
%Friends.Person{
  __meta__: #Ecto.Schema.Metadata<:built, "people">,
  age: nil,
  first_name: nil,
  id: nil,
  last_name: nil
}
iex(2)> Friends.Repo.insert(person)

10:50:43.451 [debug] QUERY OK db=0.4ms
INSERT coll="people" document=[_id: #BSON.ObjectId<5b0288630d1a8f06ef2e3699>] []
{:ok,
 %Friends.Person{
   __meta__: #Ecto.Schema.Metadata<:loaded, "people">,
   age: nil,
   first_name: nil,
   id: "5b0288630d1a8f06ef2e3699",
   last_name: nil
 }}

But if uncomment Friends.PersonController.save and try to call it when program is work, I got error:

⇒ mix
Compiling 1 file (.ex)
START SAVING

== Compilation error in file lib/friends.ex ==
** (ArgumentError) argument error
    (stdlib) :ets.lookup_element(Mongo.IdServer, :machineprocid, 2)
    lib/mongo/id_server.ex:50: Mongo.IdServer.new/0
    lib/ecto/repo/schema.ex:651: Ecto.Repo.Schema.autogenerate_id/4
    lib/ecto/repo/schema.ex:199: anonymous fn/13 in Ecto.Repo.Schema.do_insert/4
    lib/friends/person_controller.ex:11: Friends.PersonController.save/0
    lib/friends.ex:4: (module)

What’s the solution for it? How I can do it?
I have an assumption that when I run the program, I just do not start Mongo?

It looks to me like you are calling Friends.PersonController.save() at compile time in your code. And at compile time, your DB application is not started naturally.

Can you show the code of lib/friends.ex and lib/friends/person_controller.ex?

Oh, sorry, I forgot to attach my repository.
Git Repository here.
Look to master

As @Nicd said, you are calling at compiletime. Then all the drivers and ecto aren’t running.

https://github.com/dersar00/friends/blob/master/lib/friends.ex

When this module is compiled, it will call the save function at compile time. That’s probably not what you want to do.

So how I can call it after compiling?
It’s a test project what I can publish. In my real dev project I have a program what’s listening a rabbitmq queue, when I get message I have a task to save it, so how I can at first compile program and after use without any problems?

Call the function in the code that does the handling of the RabbitMQ message. I don’t know how your program works to tell you the exact place.

I call it, but I get the same error.

Where? We need more details.

For example my main file looks like here.

Have you started the Ecto application and your repos when running that? How are you running it? I can’t see it in your git repo. It seems you may have a misunderstanding of how Elixir applications are started.

I’m running it with mix

⇒  mix
Compiling 5 files (.ex)
warning: variable "meta" is unused
  lib/dispatcher_service.ex:7

12:03:56.663 [error] Supervisor 'Elixir.Logger.Supervisor' had child 'Elixir.Logger.ErrorHandler' started with 'Elixir.Logger.Watcher':start_link({error_logger,'Elixir.Logger.ErrorHandler',{true,false,500}}) at <0.72.0> exit with reason normal in context child_terminated
12:03:56.711 [info] Application lager started on node nonode@nohost
12:03:56.717 [info] Application jsx started on node nonode@nohost
12:03:56.739 [info] Application ranch started on node nonode@nohost
12:03:56.743 [info] Application ranch_proxy_protocol started on node nonode@nohost
12:03:56.746 [info] Application recon started on node nonode@nohost
12:03:56.747 [info] Application rabbit_common started on node nonode@nohost
12:03:56.757 [info] Application amqp_client started on node nonode@nohost
 [*] Waiting for messages. To exit press CTRL+C

After my program start listen queue and stay active by that time I send to queue message from rabbitmq managment console.

I publish a rabbitmq branch. U can see it in my repository

The code at the end of the file (outside the defmodule) is again run at compile time. I suggest you read up on how Elixir programs are started as to where you should put your code. You cannot put code just anywhere, because at compile time your applications are not running.

1 Like

I made everything like in rabbitmq elixir documentation.
Part where is a full receive.exs file content
So I did not admit that the problem could be there and looked for it everywhere, but not there

That works on its own but not in a project where you have other applications that need starting up. In addition, the example in the documentation deals with exs (script mode) files, which are run like scripts. Normally your ex files are compiled first and then executed.

You need to look at how Elixir projects are started using a supervision tree. Unfortunately I’m quite busy right now so I can’t link any tutorial but I hope others can help in this regard. Basically what you want is a supervision tree that starts the necessary applications (like your Ecto.Repo), then starts a process with that RabbitMQ listener code.

2 Likes

Thanks @Nicd! Good luck!