I have a situation at work where two distinct Phoenix projects, A and B, duplicate the same schemas, since they truck in the same db tables. This is painful, since migrations must be done twice. My instinct is to make a sort of library project, C, which A and B would call as file dependencies. All the schemas would reside there. I understand that this might not be conventional, or that it would also be possible to merge the A and B into one (much) larger project, but I’m wondering if this dependency model is even possible. If so, what would you call out as drawbacks? What would you call out as benefits? I should say that I’m a rank beginner. Please simplify.
I did exactly this and it does work.
But there is a BIG gotcha you have look out for. If you create a database repo in project C (which you probably will for testing and development), when you include project C in your dependencies for A or B its going to automatically try to connect with the database when you run A or B. (I don’t 100% know why, but it does.) I didn’t realize this and had setup a separate connection with the database in my “project A”. And I kept getting an error about a missing socket (even though I was using tcp) – it was Project C’s repo trying to talk to the database but hadn’t been fully configured.
The solution was to utilize the repo from project C and not try to recreate it in A or B. There is probably a way to do otherwise but this worked for me. FYI you still have to config C’s repo in project A (and B). I also added it to A’s (or B’s) supervision tree (though maybe that wasn’t necessary?)
Thanks for this detailed answer, especially for the warning about the DB repo in C. A few other things:
- When you wrote migrations for the underlying table(s), the work was isolated to C, right? IOW, schemas only needed to be changed in C, the migration only run within C.
- The schemas were in C, but were accessible to A and B?
- How was testing impacted? Did you have all tests of validations in C, for example?
- What would you consider the benefits of this approach? Drawbacks?
- I’m curious about how this approach impacts CI pipelines and deployment. We are using Jenkins to deploy Docker images.
- Did you find yourself needing to perform more deployments? For example, the changes in C are ultimately for the sake of accommodating some change in B or A, so you wound up deploying/PRing changes to the same number or perhaps more projects per task?
- How did the API for C look? Did you set up like an API module that utilized
Again, thank you for your time!
Correct. And that was a major motivation for this approach.
It SoC’d the rest well too. Everything related to that database was test in C. C gets involved in tests for A (and B) but indirectly (integration testing basically).
Some people/organizations like monorepos but I tend to find clean separations easier on my mind. It’s important that they are clean separations though! C should straightforward and general.
Hmm… I don’t think it’s too much of an issue. I use a git dependency in A/B’s mix.exs. So that pulls it in just fine.
A little but not much. Again with a clear separation, C doesn’t change much once built out.
No defdelegate. I kept it very simple. C is almost all schema code, and some very general reusable queries. Not much else.
I think the question to ask is how strongly tied they are. If C could be useful for more then just A and/or B (at least hypothetically) then it probably makes sense.
Again, thank you for this. Knowing that it’s been done before, and successfully, makes me more eager to cajole my team into trying!
Do you know of any online resources that do something similar? It might be good to 1) have something of a template I could follow, since I’m new to Elixir, and 2) have something the team could look at to draw parallels to our own work.
Sorry, I am not aware of any resources as such. If I had more time I might write a blog post on the topic. If I ever get a chance… but alas right now I have too much on my plate.