Agent & Task

Good for simple shared state; the function runs inside the agent process (keep it cheap).

31.1 Agent — simple state wrapper

Good for simple shared state; the function runs inside the agent process (keep it cheap).

{:ok, agent} = Agent.start_link(fn -> %{} end, name: :cache)
Agent.update(:cache, &Map.put(&1, :a, 1))
Agent.get(:cache, &Map.get(&1, :a))              # 1
Agent.get_and_update(:cache, fn s -> {Map.get(s, :a), Map.delete(s, :a)} end)
Agent.stop(agent)

31.2 Task — one-off async work

task = Task.async(fn -> expensive_computation() end)
other_work()
result = Task.await(task, 10_000)       # default timeout 5000 ms

# Parallel map with bounded concurrency
urls
|> Task.async_stream(&fetch/1, max_concurrency: 10, timeout: 30_000, ordered: false)
|> Enum.map(fn {:ok, res} -> res end)

Task.await_many([t1, t2])
Task.yield(task, 1000) || Task.shutdown(task)    # non-crashing timeout handling
Task.start(fn -> fire_and_forget() end)

31.3 Task.Supervisor

children = [{Task.Supervisor, name: MyApp.TaskSup}]

Task.Supervisor.start_child(MyApp.TaskSup, fn -> send_email() end)
Task.Supervisor.async_nolink(MyApp.TaskSup, fn -> risky() end)   # caller isn't linked
Task.Supervisor.async_stream_nolink(MyApp.TaskSup, items, &work/1)