Skip to content

Instantly share code, notes, and snippets.

@zoedsoupe
Created September 15, 2024 23:56
Show Gist options
  • Save zoedsoupe/2e96bd9cb729f650f6d95516d0e716ea to your computer and use it in GitHub Desktop.
Save zoedsoupe/2e96bd9cb729f650f6d95516d0e716ea to your computer and use it in GitHub Desktop.
exemplos de camadas resilientes e anti frágeis em elixir
defmodule AntifragileWorker do
use GenServer
# Starts the GenServer
def start_link(_) do
GenServer.start_link(__MODULE__, %{attempts: 0, strategy: :default}, name: __MODULE__)
end
# Initial state
def init(state) do
# Schedule the first work
schedule_work()
{:ok, state}
end
# Handle scheduled work
def handle_info(:work, state) do
case fetch_data(state.strategy) do
{:ok, data} ->
IO.puts("Data fetched successfully: #{data}")
# Reset attempts after a success
new_state = %{state | attempts: 0}
schedule_work()
{:noreply, new_state}
{:error, reason} ->
IO.puts("Failed to fetch data: #{reason}")
new_state = %{state | attempts: state.attempts + 1}
# Adapt strategy after 3 consecutive failures
adapted_state = adapt_strategy(new_state)
schedule_work()
{:noreply, adapted_state}
end
end
defp schedule_work do
# Schedule work to run every second
Process.send_after(self(), :work, 1_000)
end
defp fetch_data(:default) do
# Simulate an unreliable external service
if :rand.uniform() < 0.7 do
{:error, :service_unavailable}
else
{:ok, "Default Strategy Data"}
end
end
defp fetch_data(:alternative) do
# Alternative strategy with higher success rate
if :rand.uniform() < 0.3 do
{:error, :service_unavailable}
else
{:ok, "Alternative Strategy Data"}
end
end
defp adapt_strategy(state) do
if state.attempts >= 3 and state.strategy == :default do
IO.puts("Adapting strategy due to failures...")
%{state | strategy: :alternative, attempts: 0}
else
state
end
end
end
# Start the AntifragileWorker
{:ok, _pid} = AntifragileWorker.start_link([])
# Keep the script running
:timer.sleep(:infinity)
defmodule FileProcessor do
use GenServer
# Starts the GenServer
def start_link(file) do
GenServer.start_link(__MODULE__, file, name: via_tuple(file))
end
defp via_tuple(file) do
{:via, Registry, {FileProcessorRegistry, file}}
end
# Initial state
def init(file) do
{:ok, %{file: file}, {:continue, :process_file}}
end
# Continue callback to start processing
def handle_continue(:process_file, state) do
case process_file(state.file) do
:ok ->
IO.puts("Successfully processed #{state.file}")
{:stop, :normal, state}
{:error, reason} ->
IO.puts("Failed to process #{state.file}: #{reason}")
# Simulate crash
{:stop, reason, state}
end
end
defp process_file(file) do
# Simulate file processing
if String.contains?(file, "corrupt") do
{:error, :corrupt_file}
else
# Simulate processing time
:timer.sleep(1000)
:ok
end
end
end
defmodule FileProcessorSupervisor do
use Supervisor
def start_link(files) do
Supervisor.start_link(__MODULE__, files, name: __MODULE__)
end
def init(files) do
children = Enum.map(files, fn file ->
Supervisor.child_spec(
{FileProcessor, file},
id: String.to_atom(file),
restart: :transient
)
end)
Supervisor.init(children, strategy: :one_for_one)
end
end
@adolfont
Copy link

Eu penso que um sistema antifrágil teria que reescrever seu código. Isso pode levá-lo a, às vezes, piorar. Isto acontece também na Natureza. Se eu fizer musculação pegando peso demais, eu perco mais músculos do que ganho ou posso até mesmo me machucar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment