Hey, today I give amnesia library a try and found a few problems. I would like describe how to setup it properly and solve problems which could occur due to using it in my specific situation.
Problem with Elixir 1.7
It’s not easy even at start. When I have added {:amnesia, "~> 0.2.7"}
to my dependencies then exquisite (amnesia
dependecy) gives me such error:
==> exquisite
Compiling 1 file (.ex)
== Compilation error in file lib/exquisite.ex ==
** (CompileError) lib/exquisite.ex:103: __CALLER__ is available only inside defmacro and defmacrop
lib/exquisite.ex:103: (module)
could not compile dependency :exquisite, "mix compile" failed. You can recompile this dependency with "mix deps.compile exquisite", update it with "mix deps.update exquisite" or clean it with "mix deps.clean exquisite"
Fortunately it’s already solved in master
branch (just no new hex
package), so solution is as easy as adding: {:exquisite, "~> 0.1.8", github: "meh/exquisite", override: true}
to project dependencies. This will force mix
to use github
version (defaults to master
branch) by ignoring amnesia
dependency declaration.
Weird database compilation problem
The next problem occurs also at compilation. However both exquisite
and amnesia
compiles correctly. The error looks like:
Compiling … files (.ex)
== Compilation error in file lib/my_app/database.ex ==
** (UndefinedFunctionError) function Kernel.Typespec.defines_type?/3 is undefined or private. Did you mean one of:
* defines_type?/2
(elixir) Kernel.Typespec.defines_type?(Database.TableName, :t, 0)
lib/my_app/database.ex:…: (module)
lib/my_app/database.ex:…: (module)
This error occurs, because amnesia
is using Elixir
private API. Such code could change really often and developers should not depend on it. Fortunately fixing it is pretty easy. Simply navigate to: deps/amnesia/lib/amnesia/table/definition.ex
and replace line 938
:
unless Kernel.Typespec.defines_type?(__MODULE__, :t, 0) do
with this one:
unless Kernel.Typespec.defines_type?(__MODULE__, {:t, 0}) do
Note: Don’t forget to run mix deps.compile
to force recompile our change. Without it command error would occur again, because this dependency is already compiled and such old compiled version is used instead. Of course it’s not a good production solution, but temporary tip which allow use it now without waiting on package owner.
Multiple nodes in test environment
Last problem which I found is how to properly use amnesia
in test environment. We are able to create simple cluster without any extra commands, but amnesia
would fail lots of times. For example:
Calling Amnesia.Schema.create(nodes)
would give us:
{:error,
{'Cannot install fallback',
{'No disc resident schema on local node',
…}}}
Calling Database.create!(disk: nodes)
would even freeze our prompt without any warning and/or error.
This could be solved by using amnesia
on any slave nodes instead master node.
Helpful resources
-
Compilation error after upgrading elixir #10 issue at meh/ exquisite
This is related to first problem I described. -
PSA: Do not use private APIs, request a feature instead
This is related to second problem I described. @josevalim describes the problem with lots of dependencies and projects when trying to update toElixir
version1.7
-
Starting multiple named nodes locally for ExUnit tests
Here @beardedeagle summaries answers in his topic and is giving of cluster example which could cause some troubles withamnesia
for newbies. -
Finally here is Elixir + Phoenix + Amnesia + Multi-node article written by @jmerriweather which inspires me to give
amnesia
a try and write this topic.
Hope that I have explained everything correctly. Let me know if you have any questions. I would like to say thank you for everyone which helps community. Without all of you such problems would definitely took me much more time than I spend today in this topic.