Bounded fiber worker pool with indexed results

Crystal
def run_pool(items : Array(T), workers : Int32 = 4, &work : T -> U) : Array(Tuple(Int32, U?, String?)) forall T, U
  raise ArgumentError.new("workers must be positive") if workers < 1
  jobs = Channel(Tuple(Int32, T)).new(items.size)
  results = Channel(Tuple(Int32, U?, String?)).new(items.size)
  items.each_with_index { |item, i| jobs.send({i, item}) }
  jobs.close
  workers.times do
    spawn do
      while job = jobs.receive?
        begin
          i, item = job
          results.send({i, work.call(item), nil})
        rescue ex
          results.send({i, nil, ex.message})
        end
      end
    end
  end
  Array(Tuple(Int32, U?, String?)).new(items.size) { results.receive }.sort_by { |r| r[0] }
end