Olá!
Abaixo está a minha resolução exercício 05. O código é executado pelo arquivo training/main.py desse repositório mas ele não é essencial para esta dúvida. O repositório está aqui: https://github.com/foguinhoperuca/alura-python-introducao-a-linguagem/blob/master/training_py/alura_async.py
Contexto:
Note que eu adotei o uso do asyncio.Future na solução e isso me gerou uma dúvida em comparação ao gabarito proposto: No gabarito a solução acaba sendo um pouco mais simples pois a função assíncrona retorna diretamente para a variável. Essa solução talvez seja adequada, a primeira vista, pela natureza descrita do problema que acaba tendo uma estrutura sequêncial pois o processamento do estoque depende do processamento do pagamento e o problema em si tem uma "cara" mais tradicional do que paralelo.
Por outro lado eu interpretei, inicialmente, o problema como a validação do estoque dependendo do processamento do pagamento (e assumindo que essa tarefa demoraria) faria que a validação do estoque em determinado momento precisasse parar e esperar a aprovação do pagamento.
Entretanto, olhando a minha solução e comparando com o gabarito, ficou uma sensação meio "estranha" como se a minha solução acabasse sendo um overkill pra resolução do problema, no que pese ela funcionar. Talvez tenha faltado executar simultaneamente as tarefas com asyncio.gather para diminuir essa sensação.
Minha dúvida:
Assumindo o overkill da minha solução, qual seria o contexto claro para se utilizar "future"? O quê levar em considereção para que essa solução seja aplicável na hora de analisar o problema?
async def exerc_05() -> None:
"""Descritivo do exercício vai aqui"""
async def process_payment(order_id: int, future: asyncio.Future) -> None:
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} processing payment for {colored(order_id, "yellow", attrs=CGATTRS)}')
order: Dict[str, int | bool] = list(filter(lambda o: o["id"] == order_id, orders))[0]
logging.debug(f'----- {order} -----')
await asyncio.sleep(3)
future.set_result(order['payment_approved'])
async def validate_stock(order_id: int, future: asyncio.Future) -> None:
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} validating stock for {colored(order_id, "yellow", attrs=CGATTRS)}')
order: Dict[str, int | bool] = list(filter(lambda o: o["id"] == order_id, orders))[0]
logging.debug(f'----- {order} -----')
await asyncio.sleep(2)
future.set_result(order['available_stock'])
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} --- EXERCISE ---')
orders: List[Dict[str, int | bool]] = [
{"id": 101, "payment_approved": True, "available_stock": True},
{"id": 102, "payment_approved": True, "available_stock": False},
{"id": 103, "payment_approved": False, "available_stock": True},
{"id": 104, "payment_approved": True, "available_stock": True},
{"id": 105, "payment_approved": False, "available_stock": False},
]
for ord in orders:
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} order: {colored(ord, "yellow", attrs=CGATTRS)}')
fut_pay_appr: asyncio.Future = asyncio.Future()
asyncio.create_task(process_payment(order_id=ord['id'], future=fut_pay_appr))
payment_approved: bool = await fut_pay_appr
if payment_approved:
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} processing payment {colored("APPROVED", "blue", attrs=CGATTRS)} for {colored(ord["id"], "blue", attrs=CGATTRS)}')
fut_valid_stock: asyncio.Future = asyncio.Future()
asyncio.create_task(validate_stock(order_id=ord['id'], future=fut_valid_stock))
avail_stock: bool = await fut_valid_stock
if avail_stock:
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} stock availability {colored("APPROVED", "blue", attrs=CGATTRS)} for {colored(ord["id"], "blue", attrs=CGATTRS)} - {colored("ORDER WILL BE DELIVERED!!", "blue", attrs=CGATTRS)}')
else:
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} stock availability {colored("NOT APPROVED", "red", attrs=CGATTRS)} for {colored(ord["id"], "red", attrs=CGATTRS)} - {colored("ORDER IS CANCELED", "red", attrs=CGATTRS)}')
else:
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} processing payment {colored("NOT APPROVED", "red", attrs=CGATTRS)} for {colored(ord["id"], "red", attrs=CGATTRS)} - {colored("ORDER IS CANCELED", "red", attrs=CGATTRS)}')
print(f'{colored("[ALURA_ASYNC][05]", "white", attrs=CGATTRS)} --- </ORDER id={ord["id"]}> ---')