Gyllsdorff

Gyllsdorff

The Plug.init/1 method gets called during the compile step and not during the startup like I thought, is there someway to update a plugs config when the router supervisor tree is being setup?

Background info: All of our applications/servers/api:s connect to a configuration server during startup and loads their config at that point, without the config the applications will not work since the configuration contains things like “How are the authentication rows formatted in redis”. The configuration can change depending on which datacenter the application will end up in so we can’t tell the application this during the compile step or by using environment variables.

Now, this was a easy problem to solve for most of our elixir apps, just add the configuration genserver to the top of the supervisor tree, it loads the config and the rest of the genservers can query it in their init/1 calls. Our only problem is the Plugs init/1 functions which are called during the compilation and we don’t have access to the configuration at that point. The config is a deeply nested, large (200 000 rows) map which means asking for the configuration rows each request might be too expensive.

We can of course just extract the plug functionality into a genserver but I would prefer to avoid the extra step if we could avoid it.

Showing Posts 1 to 10

idi527

idi527

You can add a separate plug in the beginning of your “plug pipeline” to assign the necessary values into :private or :assigns fields, which can then be accessed by other plugs down the line.

This separate plug would act like the init callback in a genserver.

Gyllsdorff

Gyllsdorff OP

That would still make a config request for each incoming web request, right?

Besides, I would prefer to not have a dependency between the different plugs. If we add plug that requires some config information we would have to add that config key to the “Setup configuration” plug.

idi527

idi527

That would still make a config request for each incoming web request, right?

I would imagine that you would request the config at the start up of your web app, and save it into either a module with :code.load_binary/3 (if the config won’t change for the life time of the app) or into a genserver (if it will change). The separate plug would then request those.

I don’t quite get your second point …

Gyllsdorff

Gyllsdorff OP

That was what I was afraid of. I think we will just add a backing genserver for each plug. If the plugs behaved like genservers then we would not have had this problem but perhaps the the current plug behaviour gives you some other benefits.

idi527

idi527

Plugs are functions, basically … so they can’t really behave like genservers.

Why would you add a genserver for each plug though? Wouldn’t one be enough? It would be a bit more efficient (less message passing between processes, the webserver’s and your genservers’).

But I would probably go with the :code.load_binary/3 approach (you can see how it works in the fastglobal library), because calling genservers might result in a bottleneck.

Gyllsdorff

Gyllsdorff OP

Why would you add a genserver for each plug though? Wouldn’t one be enough?

Each api can have different plugs enabled so we can’t have a large genserver that loads the configuration for every one of them.

For example, we have these two plugs which both need access to configuration values that we get during the app startup.

  • Is this api enabled plug: The config can enabled/disable certain api:s.
  • Authenticate: this one need information about which redis server it should talk to, how the redis key is formatted and which keys from redis should be loaded for this particular api.
  • The CORS headers needs to be configurable by the security team and loaded through the configuration.

because calling genservers might result in a bottleneck.

Agreed. :frowning:

i-n-g-m-a-r

i-n-g-m-a-r

@Gyllsdorff did you find a solution to configuring plugs at runtime?

LostKobrakai

LostKobrakai

See this post:

i-n-g-m-a-r

i-n-g-m-a-r

tnx @LostKobrakai, so I guess it’s not possible to configure a plug at runtime, the solution seems to configure the call to a plug (every time) instead of just once on init.

LostKobrakai

LostKobrakai

I’m not sure what you expect. You either have compile time configuration (init/1) or runtime (call/2). “Once on init” is just a variation of “retrieve it every time” in that the caller queries the config from any kind of runtime cache like e.g. the app environment or some started processes instead of recalculating the config from more expensive sources. There are ways of compiling data into actual code (see e.g. GitHub - discord/fastglobal: Fast no copy globals for Elixir & Erlang. · GitHub) but that’s that’s the edge-case solution not the norm.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
ryanwinchester
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted” Version...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews