srowley

srowley

Why do Agent.start_link/2, get/3 and update/3 take a function to set/get state? Why not just pass/retrieve the state directly, i.e., if I want the state to be 42, just let me pass 42 instead of fn -> 42 end?

This isn’t a complaint as I am sure there is a good (maybe obvious) reason for this, this question is really just a request for a learning opportunity for me if anyone is willing to explain.

Showing Posts 1 to 7

joaoevangelista

joaoevangelista

:wave:
So I tried to find something on the documentation about it. It’s there but not so explicit:

start_link/2 Once the agent is spawned, the given function fun is invoked in the server process

So it seems that it uses the Agent process to run your function and from there get the initial state, since Agent abstracts the notion of state, and doesn’t leak it to you directly you send the “action” to perform on the state. The same reason applies for get and get_and_update.

Hope that this make some sense

srowley

srowley OP

Thanks - I’m sorry but I think I am still kind of puzzled. Why is not “leaking it directly” a useful/good thing? Or put differently, if Agent is just there to hold state and let us access it, what’s the benefit of requiring a function be invoked to do that instead of just handing it over?

When I look at the source, for example, all it does is send the function and arguments to start_link/3 for the underlying GenServer, the init/1 callback for which calls a function that just runs apply/2. So it doesn’t seem like the function is being transformed, evaluated, checked or otherwise “used for anything” so to speak; it’s always just getting passed along until finally it gets applied to the arguments passed along with it, which I could just as easily do myself in the first place before passing in the result to be stored.

Thanks again - I’m not trying to punish anyone for trying to be helpful and I appreciate your explanation.

Nicd

Nicd

I suppose it’s so that if the agent has heavy/long initialisation/update work, it is then run in the agent and not the calling process, and the calling process can set a timeout for the work which crashes the agent.

As for the update case specifically, if the workflow was: 1) get value from agent, 2) update value locally, 3) send updated value to agent, then there is a risk of race conditions. When the update is done in the agent process, access is serialised automatically.

IloSophiep

IloSophiep

One thing I thought was a key point about Agents is, that all those callbacks you pass in are running “server-side”. With that I mean that your client process does not run those functions, but the server-process does.
I think in some cases you want to run things client-side, sometimes it’s better to run it server-side though. The way the Agent interface is built, you can easily do both!

LostKobrakai

LostKobrakai

If you’d pass the initial state after starting the Agent process using plain messages you’ll be open to race conditions. Meaning updates might be processed before your initial state is received and applied.

dimitarvp

dimitarvp

Two reasons:

  1. Making sure the initial value gets extracted in the Agent process and not the one you are creating it in. If that analogy is easier for you, think of it in terms of multi-threading: you’re spawning thread B from thread A and want thread B to evaluate the initial value of the held state so as thread A is not blocked evaluating it.

  2. Lazy loading. You might want an Agent to actually fetch stuff from database, caches, 3rd party APIs, configuration or discovery providers etc. This circles back to the reasoning that if the initial state is expensive to compute then you’d block your original process and you don’t want that.

As for “why don’t they have an alternative API for people who know what they are doing and want to supply a static value” I’d say that it’s better safe then sorry. Writing fn -> 42 end is not much harder than 42 and you gain 100% confidence that your Agent’s state will never be evaluated in the context of the caller, only in the callee (the Agent itself).

srowley

srowley OP

Yep, now I get it - thanks everyone!

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
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
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
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
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews