Drop task-per-method `trio`-`asyncio` proxying
Use method proxies through the remaining endpoints and drop the old spawn-a-task-per-method-call style helpers from module.ib_dedicated_data_client
parent
a96f1dec3a
commit
6f172479eb
|
@ -1143,6 +1143,13 @@ def get_preferred_data_client(
|
|||
clients: dict[str, Client],
|
||||
|
||||
) -> tuple[str, Client]:
|
||||
'''
|
||||
Load and return the (first found) `Client` instance that is
|
||||
preferred and should be used for data by iterating, in priority
|
||||
order, the ``ib.prefer_data_account: list[str]`` account names in
|
||||
the users ``brokers.toml`` file.
|
||||
|
||||
'''
|
||||
conf = get_config()
|
||||
data_accounts = conf['prefer_data_account']
|
||||
|
||||
|
@ -1165,7 +1172,6 @@ async def open_data_client() -> MethodProxy:
|
|||
and deliver that client wrapped in a ``MethodProxy``.
|
||||
|
||||
'''
|
||||
|
||||
async with (
|
||||
open_client_proxies() as (proxies, clients),
|
||||
):
|
||||
|
@ -1179,60 +1185,6 @@ async def open_data_client() -> MethodProxy:
|
|||
yield proxy
|
||||
|
||||
|
||||
async def _aio_run_client_method(
|
||||
meth: str,
|
||||
to_trio=None,
|
||||
from_trio=None,
|
||||
client=None,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
|
||||
async with load_aio_clients() as accts2clients:
|
||||
client = list(accts2clients.values())[0]
|
||||
async_meth = getattr(client, meth)
|
||||
|
||||
# handle streaming methods
|
||||
args = tuple(inspect.getfullargspec(async_meth).args)
|
||||
if to_trio and 'to_trio' in args:
|
||||
kwargs['to_trio'] = to_trio
|
||||
|
||||
log.runtime(f'Running {meth}({kwargs})')
|
||||
return await async_meth(**kwargs)
|
||||
|
||||
|
||||
async def _trio_run_client_method(
|
||||
method: str,
|
||||
client: Optional[Client] = None,
|
||||
**kwargs,
|
||||
|
||||
) -> None:
|
||||
'''
|
||||
Asyncio entry point to run tasks against the ``ib_insync`` api.
|
||||
|
||||
'''
|
||||
ca = tractor.current_actor()
|
||||
assert ca.is_infected_aio()
|
||||
|
||||
# if the method is an *async gen* stream for it
|
||||
# meth = getattr(Client, method)
|
||||
|
||||
# args = tuple(inspect.getfullargspec(meth).args)
|
||||
|
||||
# if inspect.isasyncgenfunction(meth) or (
|
||||
# # if the method is an *async func* but manually
|
||||
# # streams back results, make sure to also stream it
|
||||
# 'to_trio' in args
|
||||
# ):
|
||||
# kwargs['_treat_as_stream'] = True
|
||||
|
||||
return await to_asyncio.run_task(
|
||||
_aio_run_client_method,
|
||||
meth=method,
|
||||
client=client,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
||||
class MethodProxy:
|
||||
|
||||
def __init__(
|
||||
|
@ -1830,6 +1782,9 @@ async def _setup_quote_stream(
|
|||
'''
|
||||
Stream a ticker using the std L1 api.
|
||||
|
||||
This task is ``asyncio``-side and must be called from
|
||||
``tractor.to_asyncio.open_channel_from()``.
|
||||
|
||||
'''
|
||||
global _quote_streams
|
||||
|
||||
|
@ -1926,6 +1881,7 @@ async def open_aio_quote_stream(
|
|||
_setup_quote_stream,
|
||||
symbol=symbol,
|
||||
contract=contract,
|
||||
|
||||
) as (first, from_aio):
|
||||
|
||||
# cache feed for later consumers
|
||||
|
@ -1956,10 +1912,9 @@ async def stream_quotes(
|
|||
sym = symbols[0]
|
||||
log.info(f'request for real-time quotes: {sym}')
|
||||
|
||||
con, first_ticker, details = await _trio_run_client_method(
|
||||
method='get_sym_details',
|
||||
symbol=sym,
|
||||
)
|
||||
async with open_data_client() as proxy:
|
||||
|
||||
con, first_ticker, details = await proxy.get_sym_details(symbol=sym)
|
||||
first_quote = normalize(first_ticker)
|
||||
# print(f'first quote: {first_quote}')
|
||||
|
||||
|
@ -1968,7 +1923,8 @@ async def stream_quotes(
|
|||
syminfo = asdict(details)
|
||||
syminfo.update(syminfo['contract'])
|
||||
|
||||
# nested dataclass we probably don't need and that won't IPC serialize
|
||||
# nested dataclass we probably don't need and that won't IPC
|
||||
# serialize
|
||||
syminfo.pop('secIdList')
|
||||
|
||||
# TODO: more consistent field translation
|
||||
|
@ -1980,7 +1936,8 @@ async def stream_quotes(
|
|||
|
||||
syminfo['price_tick_size'] = max(syminfo['minTick'], min_tick)
|
||||
|
||||
# for "traditional" assets, volume is normally discreet, not a float
|
||||
# for "traditional" assets, volume is normally discreet, not
|
||||
# a float
|
||||
syminfo['lot_tick_size'] = 0.0
|
||||
|
||||
# TODO: for loop through all symbols passed in
|
||||
|
@ -1999,10 +1956,7 @@ async def stream_quotes(
|
|||
# TODO: we should instead spawn a task that waits on a feed to start
|
||||
# and let it wait indefinitely..instead of this hard coded stuff.
|
||||
with trio.move_on_after(1):
|
||||
contract, first_ticker, details = await _trio_run_client_method(
|
||||
method='get_quote',
|
||||
symbol=sym,
|
||||
)
|
||||
contract, first_ticker, details = await proxy.get_quote(symbol=sym)
|
||||
|
||||
# it might be outside regular trading hours so see if we can at
|
||||
# least grab history.
|
||||
|
@ -2466,9 +2420,11 @@ async def open_symbol_search(
|
|||
ctx: tractor.Context,
|
||||
|
||||
) -> None:
|
||||
# load all symbols locally for fast search
|
||||
|
||||
# TODO: load user defined symbol set locally for fast search?
|
||||
await ctx.started({})
|
||||
|
||||
async with open_data_client() as proxy:
|
||||
async with ctx.open_stream() as stream:
|
||||
|
||||
last = time.time()
|
||||
|
@ -2518,11 +2474,10 @@ async def open_symbol_search(
|
|||
async with trio.open_nursery() as sn:
|
||||
sn.start_soon(
|
||||
stash_results,
|
||||
_trio_run_client_method(
|
||||
method='search_symbols',
|
||||
proxy.search_symbols(
|
||||
pattern=pattern,
|
||||
upto=5,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
# trigger async request
|
||||
|
|
Loading…
Reference in New Issue