Skip to content
[OPEN_POKER]

Por Qué tu Poker Bot Hace Timeout: Causas y Fixes Async

JJoão Carvalho||3 min read

Un timeout del poker bot hace auto-fold de la mano que estés jugando. Pocket aces, nut flush, no importa: el servidor descarta la acción y tu stack retrocede. La ventana de 120 segundos suena generosa hasta que ves un bot real pasarse en la mano #47 de una sesión. Esto es lo que lo causa y cómo arreglar cada variante.

¿Qué pasa cuando tu poker bot hace timeout?

Open Poker impone una ventana rígida de 120 segundos desde que tu bot recibe your_turn hasta que envía un mensaje action válido. Si pierdes el plazo, el servidor fuerza un fold (o check). Tu bot sigue en la mesa pero la mano se fue. El servidor registra cada timeout, y timeouts repetidos causan desconexión. Comportamiento completo en la referencia de timeouts.

Los timeouts se sesgan hacia tus manos más fuertes. Los bots piensan más en decisiones que importan.

¿Por qué 120 segundos no es realmente generoso?

1. Llamadas de red síncronas en tu loop de decisión. Causa #1. Cada llamada síncrona bloquea todo el bot.

2. Reconexiones durante una decisión. Si tu red falla durante una decisión, el WebSocket se desconecta y tu acción falla silenciosamente.

3. Pausas del garbage collector en bots de larga ejecución.

¿Cómo encontrar qué decisiones son lentas?

import time
 
async def handle_your_turn(msg, ws):
    start = time.monotonic()
    try:
        action = await decide(msg)
        await ws.send(json.dumps({
            "type": "action",
            "action": action["type"],
            "amount": action.get("amount", 0),
            "client_action_id": f"a-{msg['turn_token'][:8]}",
            "turn_token": msg["turn_token"],
        }))
    finally:
        elapsed_ms = (time.monotonic() - start) * 1000
        if elapsed_ms > 1000:
            print(f"[SLOW] decision took {elapsed_ms:.0f}ms on hand {msg.get('hand_number')}")

¿Cómo arreglar llamadas de red síncronas?

Convierte todo a async. Usa httpx en vez de requests:

import httpx
http = httpx.AsyncClient(timeout=3.0)
 
async def decide(msg):
    response = await http.get("https://api.example.com/equity")
    equity = response.json()["equity"]
    return ("call" if equity > 0.4 else "fold")

¿Cómo envolver decisiones con timeout?

async def decide_with_fallback(msg):
    try:
        return await asyncio.wait_for(decide(msg), timeout=10.0)
    except asyncio.TimeoutError:
        return fallback_decision(msg)
 
def fallback_decision(msg):
    actions = {a["action"]: a for a in msg["valid_actions"]}
    if "check" in actions:
        return ("check", 0)
    if "call" in actions:
        call_amt = actions["call"]["amount"]
        if call_amt < msg.get("pot", 0) * 0.2:
            return ("call", call_amt)
    return ("fold", 0)

¿Cómo manejar reconexiones?

while True:
    try:
        async with websockets.connect(WS_URL, additional_headers=headers) as ws:
            await ws.send(json.dumps({"type": "set_auto_rebuy", "enabled": True}))
            await ws.send(json.dumps({"type": "join_lobby", "buy_in": 2000}))
            async for raw in ws:
                msg = json.loads(raw)
                await handle_message(msg, ws)
    except websockets.ConnectionClosed:
        print("Connection lost, reconnecting in 2s...")
        await asyncio.sleep(2)

FAQ

¿Cuál es el timeout de acción en Open Poker? 120 segundos. Auto-fold si no respondes a tiempo.

¿Por qué mi bot solo hace timeout en decisiones difíciles? Porque disparan más rutas de código: llamadas de red, calculadoras de equity, lookups de perfiles.

¿Puedo extender el timeout? No. 120 segundos es fijo para todos los bots.

¿Cuál es una latencia objetivo razonable? Menos de 200ms es excelente. Más de 5 segundos necesita investigación.


Los timeouts son el bug invisible que destruye win rates. La solución: logea la latencia, envuelve tu lógica en asyncio.wait_for(), usa clientes async, y ten un fallback seguro. Construye tu primer bot con estos patrones desde el inicio.

Seguir Leyendo