chore: support read_only replicas#52
Conversation
There was a problem hiding this comment.
@itamm15 there is one thing that I failed to realize, and that is how these functions may be used in Repo.transact/2. If a transaction is read and write, and since transactions should use the same connection, (i.e. either the primary, or just the replica) there needs to be a mechanism to specify the repo then as well.
I need to investigate further if the following is the case, but I believe the read would break out of the transaction and use the read repo which would not reflect reality. If that is the case, then some mechanism needs to be in place for these cases.
Example Arbitrary Conflict
def some_transaction do
Repo.transact(fn ->
with {:ok, _} <- User.delete_user(1) do # delete user 1
User.list_users() # user 1 in result set
end
end
endPossible Solution
def some_transaction do
Repo.transact(fn repo ->
with {:ok, _} <- User.delete_user(1) do # delete user 1
User.list_users(with_repo: repo)
end
end
endor
def some_transaction do
Repo.transact(fn repo ->
Contexted.with_repo(repo, fn ->
# all crud calls assume a single repo.
with {:ok, _} <- User.delete_user(1) do # delete user 1
User.list_users()
end
end)
end
endThe second option feels safer but more like an application concern rather than a library concern (i.e. with_repo/2 shouldnt be defined by Contexted). Likely, a third option would be to actually not make any changes to Contexted at all.
Since we guard against using the Repo module in LiveViews in our project, we'd have to remove that restriction. Our project would then implement our own Repo.with_repo/2. Then no transaction needs to change. This option might actually be preferable.
7fba97e to
af9215b
Compare
af9215b to
bfd5844
Compare
atcherry
left a comment
There was a problem hiding this comment.
Might be causing a compile error. will re-approve if I can determine if new changes dont cause the issue
| plural_resource_name = | ||
| if plural_resource_name, do: plural_resource_name, else: "#{resource_name}s" | ||
|
|
||
| read_repo_body = read_repo_body(read_repo_mfa, repo, caller) |
There was a problem hiding this comment.
Found the compilation issue!
crud_repo_repo/0 should be build with quote/unquote and NOT bind_quoted. Since read_repo_body returns function call AST, it needs to be deferred to runtime, which does not occur when using bind_quoted.
| read_repo_body = read_repo_body(read_repo_mfa, repo, caller) | |
| read_repo_body = read_repo_body(read_repo_mfa, repo, caller) | |
| read_repo_def = | |
| quote do | |
| defp crud_read_repo do | |
| unquote(read_repo_body) | |
| end | |
| end |
Remove crud_read_repo/0 from the bind_quoted body, and then return [read_repo_def, main] from the macro.
Description
Type of Change
Changes Made
Testing
Manual Testing Details
Context Integration
Contexted.TracerfunctionalityContexted.DelegatorfunctionalityContexted.CRUDfunctionalityDocumentation
Breaking Changes
Additional Notes
Checklist