Slide 37 de 74

Concorrência: with timeout

proc slow(label: Str, ms: Int): Str {
	hive.task.sleep(ms)
	echo "{label} terminou mesmo assim"
	return label
}

proc main(): void {
	if slow("c", 100) with timeout 20 is Result.Error(err) {
		echo "desistiu depois de {err.waited}ms"
	}
	hive.task.sleep(150)      // o bastante para ver o trabalho terminar de qualquer jeito

	both := await [slow("a", 10), slow("b", 10)] with timeout 500
	if both is Result.Ok(labels) {
		echo labels
	}
}

Uma espera escrita onde acontece pode ser limitada: f(x) with timeout 500, ou await […] with timeout 500, em milissegundos. Isso muda o que a espera responde — um Result<T, hive.task.TimeoutError> em vez do valor — então perder a paciência é um valor a tratar e não uma falha. Um TimeoutError carrega waited, os milissegundos pedidos, e uma message.

  • Ele abandona a espera, não o trabalho: uma thread não pode ser parada de fora, então a chamada roda até o fim, efeitos colaterais e tudo, e só a resposta dela é descartada.
  • Em um await-all é um prazo único para a barreira inteira, que falha junta.
  • Uma chamada que não responde nada não tem valor para o Result carregar, então limitar uma é recusado, e limitar uma ligação async também: a espera da ligação fica onde o nome dela é lido.
  • Um pedido a um serviço é a exceção à forma: ele já responde com um Result, então o prazo vira o próprio erro desse Result, com o motivo "Timeout", como mostra o slide de serviços.