spacebat

spacebat

Using an Ash Resource with a Dynamic Repository

Hi, we are writing an application that will have its own single/static database, as well as needing to manage connections to an arbitrary number of other databases. Ecto supports this and I wonder if there are any Ash-specific twists to this approach?
If it simplifies things, I think there would be some resources that are always from a preconfigured database, while some other resources would always come from dynamic repos.

Marked As Solved

spacebat

spacebat

Hey I got it working with the tracer - having not used tracers before and couldn’t find examples of use was the problem. Now I’m worried that the tracer is being called everywhere - is there a way to only turn on the tracer for the duration/scope of a dynamic repo query?

Thanks for all your help!

The preparation:

      prepare fn query, context ->
        if %{arguments: %{tenant: tenant}} = query do
          pid = Dyndb.Repo.get_connection!(tenant)
          Dyndb.DynamicRepoTracer.set_span_context({Dyndb.Repo, pid})
        end

        query
      end

…and the custom part of the tracer…

  @impl Ash.Tracer
  def get_span_context() do
    Process.get(:dynamic_repo_tracer)
  end

  @impl Ash.Tracer
  def set_span_context({repo_module, repo_pid} = dynamic_repo) do
    Process.put(:dynamic_repo_tracer, dynamic_repo)
    repo_module.put_dynamic_repo(repo_pid)
    :ok
  end

The github repo has been updated.

Also Liked

zachdaniel

zachdaniel

Creator of Ash

To do that with Ash the way it generally works is that you can set a context in your action to set (or override the default) repo. For example:

read :read do
  prepare fn query, _ -> 
    repo = figure_out_repo()
    Ash.Query.set_context(query, %{data_layer: %{repo: repo}})
  end
end

You can abstract this using a module-backed preparation, and attach it to a resource using the global preparations block in the resource, to trigger it on all queries:

preparations do
  prepare SetDynamicRepo
end

Not necessarily a full breakdown, but that should give you a starting point :slight_smile:

zachdaniel

zachdaniel

Creator of Ash

Totally, makes sense. We ultimately want Ash to be able to support all of those models too, even though naturally database per tenant will be a bit more challenging than the alternatives. I could even see a case for building database-per-tenant multi tenancy into ash_postgres as a first class thing at some point.

zachdaniel

zachdaniel

Creator of Ash

So, there are two relevant answers here.

Changes are the equivalent of preparations for other action types

Preparations are for read actions only, but changes can do the same thing for all other action types.

changes do
  change SetDynamicRepo
end

Keeping process context

For this, you need to add an Ash.Tracer. Ash.Tracer can “move” process context from one process to any process that Ash starts.

defmodule YourApp.DynamicRepoTracer do
  use Ash.Tracer

  def get_process_context() do
     get_dynamic_repo()
  end

  def set_process_context(repo) do
    set_dynamic_repo(repo)
  end
end

And then you can configure the tracer statically:

config :ash, tracer: [YourApp.DynamicRepoTracer]

YMMV on using put_dynamic_repo, but will be interested to hear how it goes if you go that route.

Where Next?

Popular in Questions Top

chokchit
** (DBConnection.ConnectionError) connection not available and request was dropped from queue after 2733ms. You can configure how long re...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: <h1>Create Post</h1> <%= ...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29603 241
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52673 488
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement