Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mnesia dir changes based upon context in umbrella project #40

Open
adamdaugherty opened this issue Apr 26, 2017 · 3 comments
Open

Mnesia dir changes based upon context in umbrella project #40

adamdaugherty opened this issue Apr 26, 2017 · 3 comments

Comments

@adamdaugherty
Copy link

Using Ecto 2.1.4, ecto_mnesia 0.9.0, and Elixir 19, there appears to be inconsistent behavior with respect to the path to mnesia's disc copies in umbrella projects.

During the execution of ecto.create and ecto.migrate, the mnesia files for the app under the umbrella are created relative to the app, as one might expect:

# run from the root of the umbrella, with config :mnesia, dir: 'priv/thingy/data' in config.exs
$ mix ecto.create

18:40:42.973 [info]  ==> Setting Mnesia schema table copy type

18:40:42.984 [info]  ==> Ensuring Mnesia schema exists
==> under_umbrella
The database for Thingy has been created
$ mix ecto.migrate

18:40:46.983 [debug] Selecting all records by match specification `[{{:schema_migrations, :"$1", :"$2"}, [], [[:"$1"]]}]` with limit nil

18:40:47.005 [info]  == Running Thingy.Migrations.MakeThingies.change/0 forward

18:40:47.005 [info]  create table if not exists thingies

18:40:47.024 [info]  == Migrated in 0.0s
$ ls apps/under_umbrella/priv/thingy/data/
DECISION_TAB.LOG	LATEST.LOG		id_seq.DCD		schema.DAT		schema_migrations.DCD	schema_migrations.DCL	schema_migrations.TMP	thingies.DCD

However, when the umbrella project is run, mnesia appears to be looking at the configured path relative to the root of the umbrella project, not relative to the app:

# run from the root of the umbrella, with config :mnesia, dir: 'priv/thingy/data' in config.exs
$ iex -S mix
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :mnesia.info
---> Processes holding locks <--- 
---> Processes waiting for locks <--- 
---> Participant transactions <--- 
---> Coordinator transactions <---
---> Uncertain transactions <--- 
---> Active tables <--- 
schema         : with 1        records occupying 421      words of mem
===> System info in version "4.14.3", debug level = none <===
opt_disc. Directory "/mnesia_paths/priv/thingy/data" is NOT used.
use fallback at restart = false
running db nodes   = [nonode@nohost]
stopped db nodes   = [] 
master node tables = []
remote             = []
ram_copies         = [schema]
disc_copies        = []
disc_only_copies   = []
[{nonode@nohost,ram_copies}] = [schema]
2 transactions committed, 0 aborted, 0 restarted, 0 logged to disc
0 held locks, 0 in queue; 0 local transactions, 0 remote
0 transactions waits for other nodes: []
:ok

You'll notice that it's looking for the mnesia files in /priv/thingy/data, not /apps/under_umbrella/priv/thingy/data, and so things don't work. If you run the ecto.create and ecto.migrate commands with the aforementioned configuration, and then change config.exs to use apps/under_umbrella/priv/thingy/data before running iex, things work as expected:

# run from the root of the umbrella, with config :mnesia, dir: 'apps/under_umbrella/priv/thingy/data' in config.exs
$ iex -S mix
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :mnesia.info
---> Processes holding locks <--- 
---> Processes waiting for locks <--- 
---> Participant transactions <--- 
---> Coordinator transactions <---
---> Uncertain transactions <--- 
---> Active tables <--- 
schema_migrations: with 1        records occupying 115      words of mem
schema         : with 4        records occupying 774      words of mem
thingies       : with 0        records occupying 304      words of mem
id_seq         : with 0        records occupying 304      words of mem
===> System info in version "4.14.3", debug level = none <===
opt_disc. Directory "/mnesia_paths/apps/under_umbrella/priv/thingy/data" is used.
use fallback at restart = false
running db nodes   = [nonode@nohost]
stopped db nodes   = [] 
master node tables = []
remote             = []
ram_copies         = []
disc_copies        = [id_seq,schema,schema_migrations,thingies]
disc_only_copies   = []
[{nonode@nohost,disc_copies}] = [id_seq,thingies,schema,schema_migrations]
2 transactions committed, 0 aborted, 0 restarted, 0 logged to disc
0 held locks, 0 in queue; 0 local transactions, 0 remote
0 transactions waits for other nodes: []
:ok

However, I don't know if there is a way to change the configuration based on context, though I doubt this is intentional behavior. I've created a repo that demonstrates the issue for you here.

Please let me know if you need anything else.

@AndrewDryga
Copy link
Member

Hello,

Thanks for a detailed feedback. Unfortunately adapter itself has nothing to do with Mnesia migrations (there we simply use Erlang implementation), however I'll try to look closer if we can fix it on our side.

@adamdaugherty
Copy link
Author

Just in case anyone else is having a similar issue and needs a workaround, use the following config for mnesia in your app's config.exs:

config :mnesia, dir: to_charlist Path.join(File.cwd!, "priv/data")

It seems that mix tasks run relative to the path of the mix file. Consequently, this change will make it so running mix ecto.create and mix ecto.migrate from the root of the umbrella will create the mnesia files in the /priv/data directory under the umbrella root, which is the same location that will be found by mnesia when running iex -S mix from the umbrella root.

This workaround is far from ideal, since the behavior is different depending on where you run mix and iex. If you run mix ecto.create and mix ecto.migrate from the root of the umbrella, the files will be created in the place mentioned above. If you then run iex from inside the app itself (like if debugging something in the app), the mnesia database wouldn't be available, since it'd be looking for its data files in /apps/my_app/priv/data. The same holds true if you run mix ecto.create and mix ecto.migrate from the root of the app and then run iex from the umbrella - it'd be looking for its data files in /priv/data after they were created in /apps/my_app/priv/data.

If you always (or usually) interact with your project from the root of the umbrella, this approach will get you over the hump until a more permanent solution is found, though.

@troygnichols
Copy link

troygnichols commented Jun 2, 2017

Hi, I'm using this workaround and it seems to do the same thing whether I'm in the umbrella root or the apps/<project> dir

config :mnesia, :dir, [__DIR__, "..", "priv", "data"]
  |> Path.join()
  |> Path.expand()
  |> to_charlist()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants