3 ms·
Amen. I'm always amazed by how malleable the BEAM and the patterns built on it can be. I don't think anyone predicted Erlang to (IMO) reign supreme in frontend
by fredrikholm 3y ago
Amen.
I'm always amazed by how malleable the BEAM and the patterns built on it can be. I don't think anyone predicted Erlang to (IMO) reign supreme in frontend development. I say this having written tens of thousands of lines of React and Svelte in production, on top of all the hobby projects over the years.
- sph 3y agoIn hindsight it makes sense. Networked servers need resilience to failure, to keep running, and to make concurrency as painless as possible, especially as CPU cores count increases. Off the top of my head there's not many languages that can easily handle a million processes on consumer hardware, while the developer only has to think in single threaded mode because deadlocks and data races are literally impossible. If you're building a server of any kind, the BEAM is the bee's knees. You can always resort to using a sidecar process or a Rust NIF for the high performance hot path.
- fredrikholm 3y ago> million processes ... think in single threaded mode This is a big component of the secret sauce. Writing top down, happy path code as if you're just exploring an idea and then decide to scale it to distributed nodes without changing the implementation is just absurdly practical and blows every other VM out of the park.
- ativzzz 3y ago> while the developer only has to think in single threaded mode because deadlocks and data races are literally impossible Does Elixir somehow automatically solve the case where a row in a database is loaded into memory simultaneously across multiple requests and a value is incremented? (can be easily solved with row locking, but still needs to be done explicitly at the application level)
- sph 3y agoUsually one would use Redis for this problem, and you have a Redis-like system (but based on pattern matching) native to OTP, ets. If you need a global, cluster wide counter, spawn a process with name {:global, :whatever} and let it be the source of truth for this value. Depending on the problem, there are multiple approaches you can take. And a single Postgres instance is able to deal with massive concurrency, there might not be any need for premature optimization when SQL transaction could do.
- conradfr 3y agoI don't think any language can have a magic solution for a database problem. One solution is to dynamically update the value with Ecto on_conflict if possible. Something like this, where you try to insert instead of update and have a constraint on the id for example: > on_conflict: [set: [great_column: dynamic([t], fragment("? + ?", t.great_column, 1))]] https://hexdocs.pm/ecto/constraints-and-upserts.html#constraints-and-race-conditions https://hexdocs.pm/ecto/constraints-and-upserts.html#constra...