Replace all "Repo" with "MyRepoHelper" smoofly

I have a middle size web project in Phoenix. I’ve began to need to use multiple databases. Therefore, all calls to:

Repo.get(....)
Repo.all(....)
Repo.preload(....)
# etc

now should be replaced with

current_repo = MyRepoHelper.get_current_repo()
current_repo.get(...)
current_repo.all(....)
current_repo.preload(....)
# etc

almost everywhere accross the project.

Except replacing all those manually by “Find all -> Replace All”, is there a smarter way, and more flexible, to achieve this?

Perhaps, dispatching calls from Repo to MyRepoHelper somehow.

And such that all the code I have won’t break, for instance, the functions of Ecto.Query

Also, I’d prefer this:

  MyRepoHelper.get(....)
  MyRepoHelper.all(....)
  MyRepoHelper.preload(....)
  # etc

You can programatically identify most/all(?) calling sites using mix xref naming your Repo module:

https://hexdocs.pm/mix/Mix.Tasks.Xref.html#module-callers-callee

mix xref callers Core.Repo

This won’t help you perform the actual text edits but it can at least give you a good inventory vs raw substring search.

2 Likes

You could name your module MyApp.Helper.Repo and then replace the alias to MyApp.Repo with MyApp.Helper.Repo in all the relevant files.

that won’t work completely because first I have to get a referrence to a current repo.

current_repo = MyRepoHelper.get_current_repo()

I don’t get that part. Why would you need a reference to current_repo? Also, current_repo.get(...) doesn’t look like valid Elixir code unless current_repo is a reference to a module. If current_repo is a reference to a module, then why is that needed?

Dynamic repos is recently added feature, which allows you to dynamically start repo connections.

Just checked it out. You can do MyApp.Repo.put_dynamic_repo(:tenant_foo) and then all your Repo queries will use that :tenant_foo. There doesn’t seem to be a need to maintain a reference with current_repo.

Imagine situation where you have multiple read-only repos connected to read replicas and one repo connected to write replica. Then you would get a read replica at random by some function and you would use that for read queries.

1 Like

FWIW, there’s a pretty detailed guide for that specific situation in the Ecto repo:

2 Likes

I see. Looks like picking a random read-only repo can be done inside your helper’s get and all functions. All your write functions can have the logic inside for using just the write repo. That way, you dont need to think about getting the right repo and passing that to the respective read or write functions.

1 Like