pragdave / component Goto Github PK
View Code? Open in Web Editor NEWExperiment in moving towards higher-level Elixir components
Experiment in moving towards higher-level Elixir components
You used the word "application" twice in the README! ;-)
Sorry, I just finished watching your EMPEX video.
HI Dave,
Apologies for stating the obvious but at the bottom of the readme you have
MISSING: event counter
and the example is missing.
I'm a little concerned that this library to some extent, but more particularly the associated blog post could lead to Elixir new-comers thinking that software design in Elixir is always centered on the concept of user-developed servers, and that concepts such as encapsulation and separation of concerns dictate the usage of servers in ordinary application or business logic that wouldn't otherwise need its own concurrency mechanism.
This already happens - it is not hard to find examples in the wild where people use GenServer for what could be done without concurrency at all, or much more simply with Task.async
.
Would it make sense to have some guidance on when a server is needed to begin with? For example, a web request in a framework such as Phoenix should almost never make a synchronous call to a GenServer, as this would single-thread all requests making that call and incur overhead in copying messages.
I understand for global components that you don't give names, but how does that work across nodes e.g. i could use syn/global/horde/swarm and have multiple nodes running my program. In my current case i use syn (very nice it is too) and register the genservers with via tuples, but it is not clear from the readme how naming servers with atoms or via tuples works?
Apologies for the question if its obvious!
This looks really interesting!
I am an Elixir noob who wrote his first GenServer last weekend, so this feedback may be very naive and stupid; please ignore it if so.
Although the API is very much simpler and more streamlined than the traditional GenServer, it still has a few moving parts and I wonder if they're totally necessary. From my reading of the readme, it sounds like there are exactly 3 things that you might want to do when you interact with a component:
With the current API, there are two things that the user needs to do to achieve these results:
one_way
and two_way
(2 options)set_state
, set_state_and_return
, or neither (3 options)That gives you 6 possible combinations of things you could write, but only 4 of them will do what you want.
two_way -> OK (replies without updating the state)
two_way + set_state -> OK (updates the state and replies with the new state)
two_way + set_state_and_return -> OK (updates the state and replies with something else)
one_way -> OK (updates the state without replying)
one_way + set_state -> ?
one_way + set_state_and_return -> ?
Would it be possible/desirable to have an API that was more like this?
defmodule KV do
use Component.Strategy.Dynamic,
state_name: :kv_store,
initial_state: %{}
handle add(kv_store, key, value) do
%{state: Map.put(kv_store, key, value)}
end
handle get(kv_store, key) do
%{reply: Map.get(kv_store, key)}
end
handle merge_and_tell_me_the_new_value(kv_store, key, new_value) do
new_kv_store = Map.update(kv_store, key, new_value, fn old_value -> old_value + new_value end)
merged_value = Map.get(new_kv_store, key)
%{
state: new_kv_store,
reply: merged_value
}
end
end
That way, the user doesn't have to think about which type of function they're writing - they just need to specify what they want to get out of it - a new state, a reply, or both.
Very well written and interesting post!
With components how do you handle supervision trees if all the components (and hence supervision trees) are independent of each other?
I would be interested in seeing an example app (beyond trivial!) that handles genserver messages eg handle_info, terminate etc.
I look forward to see what conversation this library generates!
The component library is part of the Toyland suite.
In your blog post leading up to some of these ideas, you use a cool trick.
When the original logic code decided it needed to be wrapped in a server, you made sure the server setter's returned pid
, so you were still returning the new state as usual in functional language
(although now the state was "opaquely" represented by a pid, instead of the naked %{} or whatever other internal data structure)
As you mentioned, this kept the original api the exact same. It was beautiful! If you wrote tests or had other modules already using the "just logic" code, you didn't have to change anything. You could even keep using pipelines since the "state" was passed back at each step
def new() do
{ :ok, names } = GenServer.start_link(Kv.Server, %{})
names
end
def lookup(names, name) do
GenServer.call(names, {:lookup, name})
end
def store(names, name, value) do
GenServer.cast(names, { :store, name, value })
names
end
Anything that used to do:
kv =
Kv.new()
|> Kv.store("Cat", "meow")
assert Kv.lookup(kv, "Cat") == "meow
Still works. Pipelines don't break. The internal api changing from pure logic to being wrapped in a genserver didn't show to outsiders
Could this library's "one_way" maintain that idea by any chance and return the pid
instead of :ok
see issue #6
Right now, a one_way or two_way declaration that contains default parameters blows up during compilation because the default is also used in the GenServer tuple.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.