Skip to content

Instantly share code, notes, and snippets.

@hieuphq
Last active July 1, 2021 03:37
Show Gist options
  • Save hieuphq/f949e2a7074b0f23edb5f7dee2ad2533 to your computer and use it in GitHub Desktop.
Save hieuphq/f949e2a7074b0f23edb5f7dee2ad2533 to your computer and use it in GitHub Desktop.
Scenarios using concurrency in elixir
defmodule EtsCacheExample do
def init!(seed, table_name) when is_atom(table_name) do
case :ets.info(table_name) do
:undefined ->
:ets.new(table_name, [:set, :public, :named_table])
_ ->
raise "ETS table with name #{table_name(pool_name)} already exists."
end
add(seed, pool_name)
end
def teardown(table_name) do
:ets.delete(table_name)
end
def add(value, table_name) do
:ets.insert_new(table_name, {value})
end
def exists?(value, pool_name) do
case :ets.lookup(table_name, value) do
[] -> false
_ -> true
end
end
def retrieve_all(table_name) do
table_name
|> :ets.match({:"$1"})
|> List.flatten()
end
end
defmodule FanInFanOutExample do
def send_notifications(notifications) do
notifications
# Spin a task per element
|> Enum.map(&Task.async(fn -> send_single_notification(&1) end)
# Await all of them
|> Enum.map(&Task.await/1)
end
def send_single_notification(notification) do
# ...
end
end
defmodule FireAndForgetExample.Application do
use Application
def start(_type, _args) do
children = [
# Start the supervision tree under the OTP Application.
{Task.Supervisor, name: FireAndForgetExample.TaskSupervisor}
]
Supervisor.start_link(children, strategy: :one_for_one)
end
end
defmodule FireAndForgetExample.OtherModule do
def process_event(event) do
# Start the task under the supervision tree.
Task.Supervisor.start_child(FireAndForgetExample.TaskSupervisor, fn ->
send_slack_notification("Hey! We got an event!")
end)
event
|> do_something()
|> do_something_else()
end
end
defmodule SchedulingExample do
use GenServer
@default_minutes 3
def start_link(args \\ []) do
GenServer.start_link(__MODULE__, to_map(args))
end
defp to_map(args) do
%{
minutes: Keyword.get(args, :minutes, @default_minutes),
forever: Keyword.get(args, :forever, true),
}
end
def init(%{minutes: minutes} = state) do
schedule_work(minutes)
{:ok, state}
end
def handle_info(:work, %{minutes: minutes, forever: forever} = state) do
# Do my work here ...
if forever do
schedule_work(minutes)
end
{:noreply, state}
end
defp schedule_work(minutes) do
milliseconds = to_milliseconds(minutes)
Process.send_after(self(), :work, milliseconds)
end
defp to_milliseconds(minutes) do
minutes
|> :timer.minutes()
|> Kernel.trunc()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment