Futures

Resultados de operações assíncronas. Futures sao retornados por funcs.async() e chamadas async de contract.

Carregamento

Não e um módulo carregavel. Futures sao criados por operações assíncronas:

local funcs = require("funcs")
local future, err = funcs.async("app.compute:task", data)
if err then
    return nil, err
end

Channel de Resposta

Obter channel para receber resultado:

local ch = future:response()
local _, open = ch:receive()
if not open then
    return nil, errors.new("future response channel closed")
end

local payload, err = future:result()
if err then
    return nil, err
end
local result, data_err = payload:data()
if data_err then return nil, data_err end

channel() e um alias para response().

O valor do channel é o payload, a tabela de payloads ou o erro da operação. Depois que o channel estiver pronto, result() oferece uma interface consistente para sucesso ou erro e retorna o valor em cache mesmo após o channel ser drenado.

Verificação de Conclusao

Verificação não-bloqueante se future completou:

if future:is_complete() then
    local result, err = future:result()
end

Verificação de Cancelamento

Verificar se o future foi cancelado:

if future:is_canceled() then
    print("Operation was canceled")
end

Obtendo Resultado

Obter resultado em cache (não-bloqueante):

local val, err = future:result()

Retorna:

  • Não completo: nil, nil
  • Cancelado: nil, error (tipo CANCELED)
  • Erro: nil, error
  • Sucesso: Payload, nil ou table, nil (multiplos payloads)

Obtendo Erro

Quando a operação falha, error() retorna um wrapper INTERNAL não retentável. Use result() quando for necessário preservar o tipo e a retentabilidade originais do erro da função chamada.

Obter erro se future falhou:

local err, has_error = future:error()
if has_error then
    print("Failed:", err:message())
end

Retorna: error, boolean

Cancelando

Cancelar operação assíncrona (best-effort):

local canceled, err = future:cancel()

Retorna: boolean, error

A operação ainda pode completar se ja estiver em andamento.

Retorna: boolean, error

No runtime v0.3.32a, futures de funções e contratos compartilham um único callback de cancelamento global ao processo. Quando os dois providers estão carregados, cancel() e is_canceled() não formam um contrato estável entre providers. Não use o cancelamento para garantir a correção da aplicação; aplique um timeout local e ignore resultados tardios até que o runtime separe o cancelamento dos providers.

Padrão de Timeout

local time = require("time")

local future, err = funcs.async("app.compute:slow", data)
if err then
    return nil, err
end

local timeout, err = time.after("5s")
if err then
    return nil, err
end

local r = channel.select {
    future:channel():case_receive(),
    timeout:case_receive()
}

if r.channel == timeout then
    future:cancel()
    return nil, errors.new({ kind = errors.TIMEOUT, message = "Operation timed out" })
end

local payload, result_err = future:result()
if result_err then
    return nil, result_err
end
local value, data_err = payload:data()
if data_err then return nil, data_err end
return value

Primeiro a Completar

local f1, err = funcs.async("app.cache:get", key)
if err then
    return nil, err
end
local f2, err = funcs.async("app.db:get", key)
if err then
    return nil, err
end

local ch1 = f1:channel()
local ch2 = f2:channel()

local r = channel.select {
    ch1:case_receive(),
    ch2:case_receive()
}

-- The slower operation may still complete; this caller ignores its result.
local winner
if r.channel == ch1 then
    winner = f1
else
    winner = f2
end

local payload, result_err = winner:result()
if result_err then
    return nil, result_err
end
local value, data_err = payload:data()
if data_err then return nil, data_err end
return value

Erros

Condição Tipo
Operação cancelada CANCELED
Operação async falhou result() preserva o kind da operação; error() reporta INTERNAL