Elixir in Heterogeneous Infrastructure
Alex Rozumii, Toptal
Elixir Club, 28 January 2017
About me
What's up, doc?
ActionCable vs AnyCable
ActionCable broadcast performance
But how to connect different technologies?
Integrating with stateless node
HTTP API
Queue
Message passing
Message passing
Message passing
But wait!
Functions + Messages + Concurrency = Erlang
Connect to the real node
Erlix
Erlix
require "erlix"
Erlix::Node.init("ruby",nil)
c=Erlix::Connection.new("foo@kdr2-pc")
p=Erlix::Pid.new(c)
# {Pid, :test_atom}
c.esend("my_pid", Erlix::Tuple.new([p, Erlix::Atom.new("test_atom")]))
Erlport/Export
Erlport/Export
defmodule SomePythonCall do
use Export.Python
def call_python_method
# path to our python files
{:ok, py} = Python.start(python_path: Path.expand("lib/python"))
# call "upcase" method from "test" file with "hello" argument
py |> Python.call("test", "upcase", ["hello"])
# same as above but prettier
py |> Python.call(upcase("hello"), from_file: "test")
end
end
Integrating with stateful node
"Hey man, we don't have such option!"
What database do you use?
Database preferences
*according to poll, 2014
SQLite
Supports
- Triggers
- Views
Redis
Redis
- Lua
- Pub/Sub
- Keyspace notifications
Redis Lua + Pub/Sub
>>> import redis
>>> r = redis.StrictRedis()
>>> lua = """
... local res = {}
... for i = 2, #ARGV do
... table.insert(res,
redis.call('publish', ARGV[i], ARGV[1]))
... end
... return res
... """
>>> multipublish = r.register_script(lua)
>>> multipublish(args=["message", "channel1",
"channel2", "channel3"])
[1L, 0L, 0L]
MySQL
MySQL
- Stored functions
- Triggers
- Views
- UDF
MySQL UDF
MySQL UDF
MySQL UDF
MySQL UDF
You're welcome!
PostgreSQL
PostgreSQL
- Stored functions
- Triggers
- Views
- Foreign Data Wrappers
- JSON
- Pub/Sub
PostgreSQL FDW
PostgreSQL FDW
PostgreSQL FDW
brain-geek/telepathy
worker(CitiesInsertListener, [Application.get_env(:app, Repo)]),
defmodule CitiesInsertListener do
use Telepathy.Listener, table_name: "cities"
def handle_insert(new, state) do
CitiesListenerAgent.push_message(__MODULE__, new)
{:noreply, state}
end
end
brain-geek/telepathy
CREATE OR REPLACE FUNCTION <%= @function_name %>()
RETURNS trigger AS $$
BEGIN
CASE TG_OP
WHEN 'INSERT' THEN
PERFORM pg_notify(
'<%= @channel_name %>',
json_build_object(
'table', TG_TABLE_NAME,
'type', TG_OP,
'old_data', NULL,
'new_data', row_to_json(NEW)
)::text
);
brain-geek/telepathy
{:ok, notif_pid} = Postgrex.Notifications.start_link(db_connection)
Postgrex.Notifications.listen(notif_pid, "cities")
{:ok, %{notif_pid: notif_pid, pg_pid: pg_pid}}
...
def handle_info(raw_msg, state) do
msg = Poison.decode! elem(raw_msg, 4)
...
Microservices are not the only option
Which one did you like?
Thanks!
Alex Rozumii
@brain-geek
alex@rozumiy.name
Elixir in Heterogeneous Infrastructure
By Alex Rozumii
Elixir in Heterogeneous Infrastructure
- 1,664