Goal: Have a phoenix app (#1), that has empty (no tables) Postgres and on first boot waits to be further setup. Once it receives migration and model/schema files via http from other phoenix app (#2), it runs migrations, starts a supervisor(App1.Repo, []),
and all received models/schemas from app #2 puts in state in worker(App1.Models, [])
, so that app #1 can process queries like Repo.all(User)
. Then, app #1 listens for requests from the app #2 and performs changes in Postgres.
Reason: Idea is to isolate DB completely from app #2, so that when it needs something from db, it just sends Ecto
queries to app #1, and app #1 is able to perform that query and return a result. However, app #1 copy can be spawned for different apps, i.e. app #2, #3, #4, which all have different models/schemas, and on first connection provide their db settings (models/migrations) to app #1, which prepares its Postgres with those settings, and then just accept db queries.
Example:
Step 1: App #1 receives User
model and respective migration file from app #2.
Step 2: App #1 runs migration file to prepare Postgres.
Step 3: App #1 starts a GenServer (process?) with Ecto, Repo and newly received User
model from app #2 and listens for incoming requests.
Step 4: App #1 receives request, runs query, and returns list of all users in its db.
%{
query: 'User',
command: 'all'
}
# Should run by app #1 as Repo.all(User)
Problems:
- First of all, is it even possible to do something like this? Or there is some fundamental issue in the idea?
- How can app #1 run migrations received dynamically, without start/stopping its server? Can we place migrations files (received from app #2) in some directory and then run something like
Mix.Tasks.Ecto.Migrate.run()
to run all migrations? - Solved Can App #1 compile models/schemas (received from app #2), start a GenServer with those models and make them available to run commands, like
Repo.all(User)
? Or can we use received models/schemas to dynamically create modules, and pass those modules toApp1.Repo
, in order to perform queries likeRepo.all(User)
, whereUser
is a dynamically generated module? Solution: Using logic from here, I was able to dynamically create modules, and then use them to perform queries.
I might have confused some things, but I believe solving these problems will help achieve the goal...? Any help appreciated!