How to safely process a collection inside GenServer? Should I let it crash?

I’ve built a batch processor using GenStage, and now am wondering how I can isolate exceptions/crashes triggered by processing single items.

Let’s say I have this in a GenStage consumer (every 5 seconds it asks for 250 results):

def handle_events(results, _from, state) do
  results
  |> Task.async_stream(&process_result/1, max_concurrency: 50)
  |> Enum.to_list
end

def process_result(result) do
  # triggers many operations which may or may not raise exceptions
end

What I’m trying to avoid is having an exception/crash in process_result bring down the GenServer process and/or affect processing of the rest of the batch.

What is an effective/idiomatic way of doing this (spawn, try/catch, trap exit?)

I’m dealing with a similar challenge would love some feedback on what I am doing as well. Currently I am doing surrounding my version of process_result that returns {:ok, result} or {:error, error}. It looks like:

  def process_result(result) do
    try do
      result = some_stuff()
      {:ok, result}
    rescue
      exception -> {:error, exception}
    end
  end

However I’m not sure if this is the most idiomatic approach.