mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-27 09:19:01 +00:00
core, libs: configurable queue size, library fixes (#7542)
* core: add chat_migrate_init_queue FFI export * bots: fix BadgeServiceErrorCode API type * nodejs: pass required command fields * nodejs: fix migration error types * nodejs: install libsimplex from SIMPLEX_LIBS_DIR * nodejs: add queue size option * nodejs: regenerate docs * python: add queue size option * bots: pass incognito in APIConnect * nodejs: accept documented success responses * python: accept documented success responses * nodejs: dispatch each bot message once * nodejs: fix startChat events loop lifecycle * nodejs, python: parse multi-line bot commands * nodejs: fix file buffer handling in addon * nodejs: keep events loop when chat stop fails * python: fix send_and_wait race, load lib off loop * python: make queue size export optional * nodejs: receive events on a dedicated thread * nodejs: release haskell thread after receive * python: receive on a dedicated thread per chat * python: test receive shutdown order * nodejs: one receive thread per chat controller * nodejs: harden receiver shutdown and tests * nodejs: stop chat before closing store * python: stop chat before closing store * nodejs, python: harden close regression and retry * python: free results with ucrt on windows * nodejs: enable c++ exceptions on mac and windows
This commit is contained in:
@@ -9,6 +9,7 @@ from __future__ import annotations
|
||||
import asyncio
|
||||
import ctypes
|
||||
import json
|
||||
from concurrent.futures import Executor
|
||||
from enum import StrEnum
|
||||
from typing import Any, TypedDict
|
||||
|
||||
@@ -102,7 +103,9 @@ async def chat_send_cmd(ctrl: int, cmd: str) -> CR.ChatResponse:
|
||||
raise ChatAPIError(f"invalid chat command result: {raw[:200]}")
|
||||
|
||||
|
||||
async def chat_recv_msg_wait(ctrl: int, wait_us: int = 500_000) -> CEvt.ChatEvent | None:
|
||||
async def chat_recv_msg_wait(
|
||||
ctrl: int, wait_us: int = 500_000, executor: Executor | None = None
|
||||
) -> CEvt.ChatEvent | None:
|
||||
def _call() -> str:
|
||||
# On timeout, the C side returns a non-NULL pointer to a single NUL byte
|
||||
# (see Mobile.hs `fromMaybe ""`), so `_read_and_free` returns "" — no
|
||||
@@ -110,7 +113,10 @@ async def chat_recv_msg_wait(ctrl: int, wait_us: int = 500_000) -> CEvt.ChatEven
|
||||
ptr = _native.lib().chat_recv_msg_wait(ctrl, wait_us)
|
||||
return _read_and_free(ptr)
|
||||
|
||||
raw = await asyncio.to_thread(_call)
|
||||
if executor is None:
|
||||
raw = await asyncio.to_thread(_call)
|
||||
else:
|
||||
raw = await asyncio.get_running_loop().run_in_executor(executor, _call)
|
||||
if not raw:
|
||||
return None
|
||||
parsed = json.loads(raw)
|
||||
@@ -122,17 +128,29 @@ async def chat_recv_msg_wait(ctrl: int, wait_us: int = 500_000) -> CEvt.ChatEven
|
||||
raise ChatAPIError(f"invalid chat event: {raw[:200]}")
|
||||
|
||||
|
||||
async def chat_migrate_init(db_path: str, db_key: str, confirm: MigrationConfirmation) -> int:
|
||||
"""Initialize chat controller. Returns opaque ctrl pointer as Python int."""
|
||||
async def chat_migrate_init(
|
||||
db_path: str,
|
||||
db_key: str,
|
||||
confirm: MigrationConfirmation,
|
||||
queue_size: int | None = None,
|
||||
) -> int:
|
||||
"""Initialize chat controller. Returns opaque ctrl pointer as Python int.
|
||||
|
||||
`queue_size` is the size of internal queues; the core default is used when None.
|
||||
"""
|
||||
# ctypes silently wraps ints that do not fit C int.
|
||||
if queue_size is not None and ctypes.c_int(queue_size).value != queue_size:
|
||||
raise ValueError(f"queue_size {queue_size} does not fit C int")
|
||||
|
||||
init_queue = _native.migrate_init_queue() if queue_size is not None else None
|
||||
|
||||
def _call() -> tuple[int, str]:
|
||||
ctrl = ctypes.c_void_p()
|
||||
ptr = _native.lib().chat_migrate_init(
|
||||
db_path.encode("utf-8"),
|
||||
db_key.encode("utf-8"),
|
||||
confirm.encode("utf-8"),
|
||||
ctypes.byref(ctrl),
|
||||
)
|
||||
args = (db_path.encode("utf-8"), db_key.encode("utf-8"), confirm.encode("utf-8"))
|
||||
if init_queue is None:
|
||||
ptr = _native.lib().chat_migrate_init(*args, ctypes.byref(ctrl))
|
||||
else:
|
||||
ptr = init_queue(*args, queue_size, ctypes.byref(ctrl))
|
||||
return (ctrl.value or 0, _read_and_free(ptr))
|
||||
|
||||
ctrl_val, raw = await asyncio.to_thread(_call)
|
||||
|
||||
Reference in New Issue
Block a user