修复模拟盘卖币握锁导致 database is locked 与中控超时离线。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -303,60 +303,99 @@ def rollback_bought_coin_to_usdt(
|
||||
|
||||
|
||||
def sell_residual_after_option_flat(
|
||||
conn: sqlite3.Connection,
|
||||
conn_or_get_db: Any,
|
||||
ex: Any,
|
||||
*,
|
||||
underlying: str,
|
||||
inst_id: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""期权已平:卖掉本桥残留标的币;优先关闭 matching holding/pending 桥."""
|
||||
ensure_bridge_table(conn)
|
||||
bridges = list_open_bridges(conn)
|
||||
target = None
|
||||
for b in bridges:
|
||||
if str(b.get("status")) in (BRIDGE_HOLDING, BRIDGE_PENDING_SELL, BRIDGE_BOUGHT):
|
||||
if not underlying or str(b.get("underlying") or "").upper() == underlying.upper():
|
||||
target = b
|
||||
break
|
||||
# 卖币(模拟盘)会另开连接写钱包,须先释放本连接事务锁,否则 database is locked
|
||||
try:
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
"""期权已平:卖掉本桥残留标的币;优先关闭 matching holding/pending 桥.
|
||||
|
||||
可传 get_db 可调用对象(推荐)或已打开的 Connection。
|
||||
卖币(尤其模拟盘写钱包)期间绝不握着业务连接,否则会 database is locked。
|
||||
"""
|
||||
get_db = conn_or_get_db if callable(conn_or_get_db) else None
|
||||
bid: int | None = None
|
||||
if get_db is not None:
|
||||
conn = get_db()
|
||||
try:
|
||||
ensure_bridge_table(conn)
|
||||
bridges = list_open_bridges(conn)
|
||||
for b in bridges:
|
||||
if str(b.get("status")) in (BRIDGE_HOLDING, BRIDGE_PENDING_SELL, BRIDGE_BOUGHT):
|
||||
if not underlying or str(b.get("underlying") or "").upper() == underlying.upper():
|
||||
bid = int(b["id"])
|
||||
break
|
||||
try:
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
try:
|
||||
conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
conn = conn_or_get_db
|
||||
ensure_bridge_table(conn)
|
||||
bridges = list_open_bridges(conn)
|
||||
for b in bridges:
|
||||
if str(b.get("status")) in (BRIDGE_HOLDING, BRIDGE_PENDING_SELL, BRIDGE_BOUGHT):
|
||||
if not underlying or str(b.get("underlying") or "").upper() == underlying.upper():
|
||||
bid = int(b["id"])
|
||||
break
|
||||
try:
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 此处无业务连接:模拟盘 convert 可安全另开写钱包
|
||||
sell = spot_market_sell_coin_to_usdt(ex, underlying=underlying)
|
||||
if target is None:
|
||||
if bid is None:
|
||||
if not sell.get("ok"):
|
||||
msg = str(sell.get("msg") or "")
|
||||
if "无可用" in msg or "过小" in msg:
|
||||
return {"ok": True, "msg": "无残留币需卖回", "skipped": True}
|
||||
return {"ok": False, "msg": msg, "bridge_status": BRIDGE_PENDING_SELL}
|
||||
return {"ok": True, "sell": sell, "bridge_status": None}
|
||||
bid = int(target["id"])
|
||||
if not sell.get("ok"):
|
||||
|
||||
def _apply_bridge(c: sqlite3.Connection) -> dict[str, Any]:
|
||||
if not sell.get("ok"):
|
||||
update_bridge(
|
||||
c,
|
||||
bid,
|
||||
status=BRIDGE_PENDING_SELL,
|
||||
inst_id=inst_id,
|
||||
message=str(sell.get("msg") or "卖回 USDT 失败"),
|
||||
)
|
||||
return {
|
||||
"ok": False,
|
||||
"msg": sell.get("msg") or "卖回 USDT 失败",
|
||||
"bridge_id": bid,
|
||||
"bridge_status": BRIDGE_PENDING_SELL,
|
||||
}
|
||||
update_bridge(
|
||||
conn,
|
||||
c,
|
||||
bid,
|
||||
status=BRIDGE_PENDING_SELL,
|
||||
status=BRIDGE_CLOSED,
|
||||
sell_ord_id=str(sell.get("ord_id") or ""),
|
||||
coin_sold=_safe_float(sell.get("coin_sold")),
|
||||
inst_id=inst_id,
|
||||
message=str(sell.get("msg") or "卖回 USDT 失败"),
|
||||
message="期权已平,币已卖回 USDT",
|
||||
close=True,
|
||||
)
|
||||
return {
|
||||
"ok": False,
|
||||
"msg": sell.get("msg") or "卖回 USDT 失败",
|
||||
"bridge_id": bid,
|
||||
"bridge_status": BRIDGE_PENDING_SELL,
|
||||
}
|
||||
update_bridge(
|
||||
conn,
|
||||
bid,
|
||||
status=BRIDGE_CLOSED,
|
||||
sell_ord_id=str(sell.get("ord_id") or ""),
|
||||
coin_sold=_safe_float(sell.get("coin_sold")),
|
||||
inst_id=inst_id,
|
||||
message="期权已平,币已卖回 USDT",
|
||||
close=True,
|
||||
)
|
||||
return {"ok": True, "sell": sell, "bridge_id": bid, "bridge_status": BRIDGE_CLOSED}
|
||||
return {"ok": True, "sell": sell, "bridge_id": bid, "bridge_status": BRIDGE_CLOSED}
|
||||
|
||||
if get_db is not None:
|
||||
conn2 = get_db()
|
||||
try:
|
||||
return _apply_bridge(conn2)
|
||||
finally:
|
||||
try:
|
||||
conn2.close()
|
||||
except Exception:
|
||||
pass
|
||||
return _apply_bridge(conn_or_get_db)
|
||||
|
||||
|
||||
def bridge_blocks_new_open_msg(conn: sqlite3.Connection) -> str | None:
|
||||
|
||||
Reference in New Issue
Block a user