Modular transports via a tractor.ipc subpkg! #24
Closed
goodboy
wants to merge 53 commits from
leslies_extra_appendix into shm_apis
pull from: leslies_extra_appendix
merge into: goodboy:shm_apis
goodboy:macos_fixed_2025
goodboy:macos_support
goodboy:piker_pin
goodboy:dereg_on_oserror
goodboy:pld_dec_refinements
goodboy:free_threading_prep
goodboy:oco_supervisor_prototype
goodboy:hilevel_serman
goodboy:multicast_revertable_streams
goodboy:ns_aware
goodboy:factor_into_hotbaud
goodboy:final_eg_refinements
goodboy:actor_cancelled_exc_type
goodboy:log_sys_testing
goodboy:main
goodboy:oob_cancel_testing
goodboy:cancelled_masking_guards
goodboy:strict_egs_everywhere
goodboy:POST_final_eg_refinements_failafter_investigation
goodboy:to_asyncio_eoc_signal
goodboy:enable_tpts
goodboy:repl_fixture
goodboy:SDOF_pre_sin_testing_XPSBACKUP
goodboy:cluster_api_egs_conflict
goodboy:moar_eg_smoothing
goodboy:pytest_pluginize
goodboy:structural_dynamics_of_flow
goodboy:one_ring_to_rule_them_all
goodboy:one_ring_to_rule_them_all_FROZEN_20250619
goodboy:auto_codecs
goodboy:shm_apis
goodboy:ext_type_plds
goodboy:py313_support
goodboy:aio_abandons
goodboy:sc_super_proto_dgrams
goodboy:runtime_to_msgspec
goodboy:pkg_tidying
goodboy:multihost_exs
goodboy:uv_migration_pre_msgspec_in_runtime
goodboy:remote_inceptions
goodboy:ext_type_plds_XPS_BACKUP
goodboy:modden_spawn_from_client_req
goodboy:multihomed
goodboy:devx_subpkg
goodboy:asyncio_debugger_support
goodboy:ctx_cancel_semantics_and_overruns
goodboy:pre_pretty_struct_dep_commit_b54cb66
goodboy:ctx_cancel_semantics_and_overruns_REVERSED_FACEPALM
goodboy:uv_migration
goodboy:to_asyncio_refinery
goodboy:runtime_to_msgspec_XPS_BACKUP
goodboy:rae_message_packing
goodboy:msg_codecs
goodboy:old_msg_types
goodboy:asyncio_debug_mode
goodboy:pause_from_sync_w_greenback
goodboy:mv_to_new_trio_py3.11
goodboy:modden_spawn_from_client_req_XPS_BACKUP
goodboy:shielded_ctx_cancel
goodboy:ctx_cancel_semantics_and_overruns_XPS_GH_BACKUP
goodboy:msgtypes
goodboy:master
goodboy:switch_to_pdbp
goodboy:proper_breakpoint_hooking
goodboy:drop_proc_actxmngr
goodboy:ctx_result_consumption
goodboy:readme_touchups
goodboy:ipython_integration
goodboy:breceiver_internals
goodboy:ipc_failure_while_streaming
goodboy:deprecate_arbiter_addr
goodboy:prompt_on_ctrlc
goodboy:dun_unset_current_actor
goodboy:ipc_failwhilestream_backup
goodboy:macos_in_ci
goodboy:harden_cluster_tests
goodboy:eg_backup
goodboy:exceptiongroups
goodboy:egs_with_ctx_res_consumption
goodboy:debug_lock_blocking
goodboy:callable_key_maybe_open_context
goodboy:spawn_backend_table
goodboy:pin_pre_trio_0.22
goodboy:pytest_report_workaround
goodboy:lifetime_stack_tests
goodboy:we_bein_all_matchy
goodboy:debug_event_guard
goodboy:disable_win_ci
goodboy:alpha5
goodboy:signint_saviour
goodboy:sigintsaviour_citesthackin
goodboy:sigintsaviour_ci_worked
goodboy:aio_error_propagation
goodboy:drop_msgpack
goodboy:310_windows
goodboy:ci_sdist_install
goodboy:include_readme
goodboy:310_plus
goodboy:name_query
goodboy:sort_subs_results_infected_aio
goodboy:aio_explicit_task_cancels
goodboy:fence_mp
goodboy:sigint_ignore_in_pdb_repl
goodboy:sigint2
goodboy:msgpack_lists_by_default
goodboy:nspaths
goodboy:experimental_subpkg
goodboy:maybe_cancel_the_cancel_
goodboy:moar_timeoutz
goodboy:drop_old_nooz_files
goodboy:raise_runinactor_error
goodboy:win_ci_timeout
goodboy:alpha4
goodboy:infect_asyncio
goodboy:expected_ctx_cancelled
goodboy:new_mypy
goodboy:context_caching
goodboy:end_of_channel_fixes
goodboy:agpl_commit_msg_fix
goodboy:agpl
goodboy:stricter_context_starting
goodboy:acked_backup
goodboy:faster_daemon_cancels
goodboy:early_deth_fixes
goodboy:clusters_and_hot_tips
goodboy:alpha3
goodboy:pubsub_startup_response_msg
goodboy:iaio_backup
goodboy:trionics
goodboy:graceful_gather
goodboy:246_facepalm_backup
goodboy:patch-async-enter-all
goodboy:immediate_remote_cancels
goodboy:less_logging
goodboy:zombie_lord_infinite
goodboy:optional_msgspec_support
goodboy:fix_kbi_in_ctx_block
goodboy:logo_tweaks
goodboy:use_trio_on_win
goodboy:alpha2
goodboy:msgspec_infect_asyncio
goodboy:live_on_air_from_tokio
goodboy:tokio_backup
goodboy:debugger_test_tweaks
goodboy:fix_news_links
goodboy:wats_da_nooz
goodboy:ctx_debugger
goodboy:bi_streaming_no_debugger_stuff
goodboy:round_2_ci_windows
goodboy:CI_increment_for_windows_bidirstreaming
goodboy:ctx_debugger_from_hardening
goodboy:infect_asyncio_backup
goodboy:debugger_hardening
goodboy:bi_streaming
goodboy:transport_cleaning
goodboy:context_finesse
goodboy:cf_backup
goodboy:db_backup
goodboy:pre_bad_close
goodboy:stdstream_clobber_fix
goodboy:bistream_backup
goodboy:transport_hardening
goodboy:msgspec_not_fucked
goodboy:try_msgspec
goodboy:prehardkill
goodboy:windows_bi_streaming
goodboy:docs_revamp
goodboy:new_docs_polish
goodboy:wip_fix_asyncio_gen_streaming
goodboy:drop_run
goodboy:mp_teardown_hardening
goodboy:stream_contexts
goodboy:drop_sync_funcs
goodboy:pub_connect_msg
goodboy:sync_cancel
goodboy:stream_clones
goodboy:first_pypi_release
goodboy:single_func_example
goodboy:readme_pump
goodboy:kinda_drop_run
goodboy:mp_hang_search
goodboy:eg_worker_poolz
goodboy:sync_breakpoint
goodboy:actor_state_via_messages
goodboy:we_aint_got_zombie_shields
goodboy:deprecate_rpcmodpaths
goodboy:implicit_runtime
goodboy:drop_tractor_run
goodboy:py3.9
goodboy:denoise_logging
goodboy:func_refs_always
goodboy:fix_debug_tests_in_ci_again
goodboy:stream_channel_shield
goodboy:pdb_madness
goodboy:advanced_debugger_testing
goodboy:clean_log_header
goodboy:debug_refine
goodboy:debug_refinements
goodboy:drop_warn
goodboy:multiproc_debug
goodboy:debugger_on_windows
goodboy:bug_in_debug
goodboy:debug_tests
goodboy:native_debugging
goodboy:matrix
goodboy:dereg_on_channel_aclose
goodboy:ensure_deregister
goodboy:start_up_sequence_trickery
goodboy:fix_win_ci_again
goodboy:stin_char_relay
goodboy:flaky_tests
goodboy:drop_cloudpickle
goodboy:reorg_entry_points
goodboy:drop-trip-update-trio
goodboy:init_sphinx_docs
goodboy:example_tests
goodboy:implicit_rpc
goodboy:fix_examples_in_docs
goodboy:try_trip
goodboy:log_task_context
goodboy:drop_event_clear
goodboy:more_thorough_super_tests
goodboy:pip_ci_fix
goodboy:windows_support
goodboy:rename_forkserver_mod
goodboy:user_update
goodboy:win_ci
goodboy:stream_functions
goodboy:propagate_loglevel
goodboy:ipc_iternals_renaming
goodboy:close_mem_chans
goodboy:docs_example_fixes
goodboy:spawn_method_support
goodboy:trio_memchans
goodboy:contexts
goodboy:remote_module_errors
goodboy:remote_task_cancelling
goodboy:fix_46
goodboy:loglevel_to_tractor_tests
goodboy:expose_tractor_test
goodboy:improved_errors
goodboy:self_register
goodboy:multi_program_tests
goodboy:tests_reorg
goodboy:type_annotations
goodboy:py3.7_tweaks
goodboy:reliable_cancel_tests
goodboy:attrs_it_up
goodboy:wait_for_actor
goodboy:draft_readme
goodboy:init_docs
goodboy:reg_with_uid
goodboy:forkserver_singleton
goodboy:drop_main_kwarg
goodboy:asyncgen_closing_fix
No reviewers
Labels
Clear labels
No items
No Label
Milestone
Clear milestone
No items
No Milestone
Projects
Clear projects
No project
Assignees
Clear assignees
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.
No due date set.
Dependencies
No dependencies set.
Reference: goodboy/tractor#24
Reference in New Issue
There is no content yet.
Delete Branch "leslies_extra_appendix"
Deleting a branch is permanent. Although the deleted branch may exist for a short time before cleaning up, in most cases it CANNOT be undone. Continue?
That’s right, we’re finally not just using TCP!
Bo
This originally started as a appendix PR to #17 and was thus named,
Now this PR will replace #17 since the history is to be fast forwarded onto the
structural_dynamics_of_flowbranch originally started by @guille (with much thanks!)The original description was,
PR land plan
I’d like to see this landed before the original upstream branch (#10) which contains the new (and much more experimental) high-perf shared-mem
.ipc._ringbugstuff from @guille.So our first common commit between this and #10 should be,
9b21615Break out transport protocol and tcp specifics into their own submodulesFrom the original history I’ve dropped the following commits that can instead go with #10:
bab265bImportant RingBuffBytesSender fix on non batched mode!010874bCatch trio cancellation on RingBuffReceiver bg eof listener taskbe7fc89Add direct ctx managers for RB channels2a9a786Improve test_ringbuf testbe818a7Switchtractor.ipc.MsgTransport.streamtype totrio.abc.Streamba353bfBetter encapsulate RingBuff ctx managment methodsAmendments to
tractor.ipcand._addrvs. original #17Much simplification to new
._addr.Addressprimitives,UnwrappedAddress,Addresstype-var inheritance,Address.open_stream(), never used.UDSAddress.unwrap()to atuple[str, str]of the(._filedir,._filename)pair, effectively the(Path.parent, Path.name)components of a (new).sockpath: Path..proto_keyandunwrapped_type.namespaceas.bindspaceto both better reflect thesocket.bind()argument significance as well as avoid collision with the linux semantics of “network namespaces” (which i’d like to utilize eventually!)..def_bindspaceattrs to each concrete type.Changes to
UDSAddress.bindspace: Pathsemantic,_state.get_rt_dir()as the default directory-value representing (in the same vein as a net-proto ip-address) the “basis of the bind space”, that is for socket-files which will be created under that directory-node.wrap_address()and.from_addr()to match.Actor.aidinfo in the socket file name to indicate that process is the likely.listen()er/server for that socket/file..close_listener()sync.moved the
_addr.preferred_transportto_state._def_tpt_proto: TransportProtocolKey = 'tcp'extend
ipc._udsfor peer-credentials reading from the OS,open_unix_socket_w_passcred()which ensures withsock.setsockopt()that the server side can always read the connecting client’s pid.get_peer_info()helper to read that^UDSAddresss with the.maybe_pidset from the peer on theraddrfor groking/introspection/repr purposes!new deps introduced,
bidictfor a 2way map._address_types: [str, Type[Address]].Changes to surrounding core components
add and use a new
Actor.aid: Aid:Channel.aid/uidto it^Aid.pid: intfield for getting any peer’s process id much more easily!.uuidfield from a new_addr.mk_uuid().add real
__repr__ = pformatrepresentations to,Actor,Channel,MsgPackTransport(well ish, it’s a start),move
Actor._do_handshake()toChannelmethod.proper/rigorous
SpawnSpechandling inActor._from_parent()such that we actually raise an explicit internal error on type-mismatches (and not some weird downstream error..).add some new runtime excs,
RuntimeFailurefor out of our control init issues.ActorFailurenow from that for failed spawns.add a new
.devx.pformat.pformat_exc()factored from the body ofRemoteActorError.pformat()and used forTransportClosed.factor out
breakpoint()blocking to a_root.maybe_block_bp(); should be factored to.devxmaybe ya?Full test suite multi-tpt support with
--tpt-proto=uds|tcpI was able to augment the entire test to opt into multi-transport-protocols via a new accumulative
--tpt-protoflag which by default is always just stored as['tcp']as before.Now any opting in test/fixture can pass it to the
enable_transports: list[str]argument exposed byopen_root_actor()to test against that backend; currently we haven’t tried to test multiple protos together yet though!brief test harness updates summary
new
conftestfixture content,tpt_protos: list[str]rendered from CLI input args.tpt_proto: strwhich just takes the first of the above for now.reg_addrnow correctly generates a random root-host-singleton-registry value per test session/run.set_script_runtime_args().test suite tweaks for UDS,
test_advanced_faults.pyadjustments for receiving non-KBIs since the socket “closure”/“breakage” will be relayed by the OS immediately.TransportClosed.src_excfield for the raised underlyingtrioexceptions.a new
test_root_runtime.pysuite with,test_only_one_root_actorto verify we error on opening a 2nd root from an actor tree.test_implicit_root_via_first_nurserywhich just verifies implicit root/runtime booting from the first opened.open_nursery().New
--devdeps introducedpsutilfor proc introspection within the discovery suite.Follow up refinements I’d like to maybe see before #17 lands,
As in after this is merged into #17, I’d like to see these additional changes considered,
Addressinto its.ipc/_tcp/udsmodule.._addrsince there’s going to be extensions necessary as we start solving the multi-addresss idea and composition of tpt protos from addresses as kinda requested in https://github.com/goodboy/tractor/pull/367 with further follow up as we research the libp2p spec-docs:TransportServer(singleton?-)wrapper which keeps track of all connections (SocketStreams wrapped byMsgTransport) per protocol and peer!.open/close_listener()meths from per-tpt addrs-types and instead offering the api at module level for each proto?GH issues landing #17 will maybe close!
A few things that can fundamentally change, - UDS addresses now always encapsulate the local and remote pid such that it denotes each side's process much like a TCP *port*. |_ `.__init__()` takes a new `maybe_pid: int`. |_ this required changes to the `.ipc._uds` backend which will come in an subsequent commit! |_ `UDSAddress.address_type` becomes a `tuple[str, int]` just like the TCP case. |_ adjust `wrap_address()` to match. - use a new `_state.get_rt_dir() -> Path` as the default location for UDS socket file: now under `XDG_RUNTIME_DIR'/tractor/` subdir by default. - re-implement `USDAddress.get_random()` to use both the local `Actor.uid` (if available) and at least the pid for its socket file name. Removals, - drop the loop generated `_default_addrs`, simplify to just `_default_lo_addrs` for per-transport default registry addresses. |_ change to `_address_types: dict[str, Type[Address]]` instead of separate types `list`. |_ adjust `is_wrapped_addr()` to just check `in _addr_types.values()`. - comment out `Address.open_stream()` it's unused and i think the wrong place for this API. Renames, - from `AddressTypes` -> `UnwrappedAddress`, since it's a simple type union and all this type set is, is the simple python data-structures we encode to for the wire. |_ see note about possibly implementing the `.[un]wrap()` stuff as `msgspec` codec `enc/dec_hook()`s instead! Additions, - add a `mk_uuid()` to be used throughout the runtime including for generating the `Aid.uuid` part. - tons of notes around follow up refinements!Such that any UDS socket pair is represented (and with the recent updates to) a `USDAddress` via a similar pair-`tuple[str, int]` as TCP sockets, a pair of the `.filepath: Path` & the peer proc's `.pid: int` which we read from the underlying `socket.socket` using `.set/getsockopt()` calls Impl deats, - using the Linux specific APIs, we add a `get_peer_info()` which reads the `(pid, uid, gid)` using the `SOL_SOCKET` and `SOL_PEECRED` opts to `sock.getsockopt()`. |_ this presumes the client has been correspondingly configured to deliver the creds via a `sock.setsockopt(SOL_SOCKET, SO_PASSCRED, 1)` call - this required us to override `trio.open_unix_socket()`. - override `trio.open_unix_socket()` as per the above bullet to ensure connecting peers always transmit "credentials" options info to the listener. - update `.get_stream_addrs()` to always call `get_peer_info()` and extract the peer's pid for the `raddr` and use `os.getpid()` for `laddr` (obvi). |_ as part of the new impl also `log.info()` the creds-info deats and socket-file path. |_ handle the oddity where it depends which of `.getpeername()` or `.getsockname()` will return the file-path; i think it's to do with who is client vs. server? Related refinements, - set `.layer_key: int = 4` for the "transport layer" ;) - tweak some typing and multi-line unpacking in `.ipc/_tcp`.Previously whenever an `ActorNursery.start_actor()` call did not receive a `bind_addrs` arg we would allocate the default `(localhost, 0)` pairs in the parent, for UDS this obviously won't work nor is it ideal bc it's nicer to have the actor to be a socket server (who calls `Address.open_listener()`) define the socket-file-name containing their unique ID info such as pid, actor-uuid etc. As such this moves "random" generation of server addresses to the child-side of a subactor's spawn-sequence when it's sin-`bind_addrs`; i.e. we do the allocation of the `Address.get_random()` addrs inside `._runtime.async_main()` instead of `Portal.start_actor()` and **only when** `accept_addrs`/`bind_addrs` was **not provided by the spawning parent**. Further this patch get's way more rigorous about the `SpawnSpec` processing in the child inside `Actor._from_parent()` such that we handle any invalid msgs **very loudly and pedantically!** Impl deats, - do the "random addr generation" in an explicit `for` loop (instead of prior comprehension) to allow for more detailed typing of the layered calls to the new `._addr` mod. - use a `match:/case:` for process any invalid `SpawnSpec` payload case where we can instead receive a `MsgTypeError` from the `chan.recv()` call in `Actor._from_parent()` to raise it immediately instead of triggering downstream type-errors XD |_ as per the big `#TODO` we prolly want to take from other callers of `Channel.recv()` (like in the `._rpc.process_messages()` loop). |_ always raise `InternalError` on non-match/fall-through case! |_ add a note about not being able to use `breakpoint()` in this section due to causality of `SpawnSpec._runtime_vars` not having been processed yet.. |_ always return a third element from `._from_rent()` eventually to be the `preferred_transports: list[str]` from the spawning rent. - use new `._addr.mk_uuid()` and pass to new `Actor.__init__(uuid: str)` for all actor creation (including in all the mods tweaked here). - Move to new type-alias-name `UnwrappedAddress` throughout.The more I think about it, it seems @guille's orig approach of unwrapping UDS socket-file addresses to strings (or `Path`) is making the most sense. I had originally thought that pairing it with the listening side's pid would add clarity (and it definitely does for introspection/debug/logging) but since we don't end up passing that pid to the eventual `.connect()` call on the client side, it doesn't make much sense to wrap it for the wire just to discard.. Further, the `tuple[str, int]` makes `wrap_address()` break for TCP since it will always match on uds first. So, on that note this patch refines a few things in prep for going back to that original `UnwrappedAddress` as `str` type though longer run i think the more "builtin approach" would be to add `msgspec` codec hooks for these types to avoid all the `.wrap()`/`.unwrap()` calls throughout the runtime. Down-low deats, - add `wrap_address()` doc string, detailed (todo) comments and handle the `[None, None]` case that can come directly from `._state._runtime_vars['_root_mailbox']`. - buncha adjustments to `UDSAddress`, - add a `filedir`, chng `filepath` -> `filename` and mk `maybe_pid` optional. - the intent `filedir` is act as the equivalent of the host part in a network proto's socket address and when it's null use the `.def_bindspace = get_rt_dir()`. - always ensure the `filedir / filename` is an absolute path and expose it as a new `.sockpath: Path` property. - mk `.is_valid` actually verify the `.sockpath` is in the valid `.bindspace: namely just checking it's in the expected dir. - add pedantic `match:`ing to `.from_addr()` such that we error on unexpected `type(addr)` inputs and otherwise parse any `sockpath: Path` inputs using a new `unwrap_sockpath()` which simply splits an abs file path to dir, file-name parts. - `.unwrap()` now just `str`-ifies the `.sockpath: Path` - adjust `.open/close_listener()` to use `.sockpath`.Via a new accumulative `--tpt-proto` arg you can select which `tpt_protos: list[str]`-fixture protocol keys will be delivered to opting in tests! B) Also includes, - CLI quote handling/stripping. - default of 'tcp'. - only support one selection per session at the moment (until we figure out how we want to support multiples, either simultaneously or sequentially). - draft a (masked) dynamic-`metafunc` parametrization in the `pytest_generate_tests()` hook. - first proven and working use in the `test_advanced_faults`-suite (and thus its underlying `examples/advanced_faults/ipc_failure_during_stream.py` script)! |_ actually needed this to prove that the suite only has 2 failures on 'uds' seemingly due to low-level `trio` error semantics translation differences to do with with calling `socket.close()`.. On a very nearly related topic, - draft an (also commented out) `set_script_runtime_args()` fixture idea for a std way of `partial`-ling in runtime args to `examples/` scripts-as-modules defining a `main()` which would proxy to `tractor.open_nursery()`.By borrowing from the implementation of `RemoteActorError.pformat()` which is now factored into a new `.devx.pformat_exc()` and re-used for both error types while maintaining the same func-sig. Obviously delegate `RemoteActorError.pformat()` to the new helper accordingly and keeping the prior `body` generation from `.devx.pformat_boxed_tb()` as before. The new helper allows for, - passing any of a `header|message|body: str` which are all combined in that order in the final output. - getting the `exc.message` as the default `message` part. - generating an objecty-looking "type-name" header to be rendered by default when `header` is not overridden. - "first-line-of `message`" processing which we split-off and then re-inject as a `f'<{type(exc).__name__}( {first} )>'` top line header. - an optional `tail: str = '>'` to "close the object"-look only added when `with_type_header: bool = True`. Adjustments to `TransportClosed` around this include, - replacing the init `cause` arg for a `src_exc` which is now always assigned to a same named instance var. - displaying that new `.src_exc` in the `body: str` arg to the `.devx.pformat.pformat_exc()` call so you can always see the underlying (normally `trio`) source error. - just make it inherit from `Exception` not `trio.BrokenResourceError` to avoid handlers catching `TransportClosed` as the former particularly in testing when we want to sometimes to distinguish them.Refinements around multiple IPC transport protos, and appendix for #17to Refinements around multiple IPC transport protos (an appendix to #17)@ -48,2 +97,4 @@# Lke, what use does this have besides a noop and if it's not# valid why aren't we erroring on creation/use?@propertydef is_valid(self) -> bool:i’m not really sure how useful this predicate is tbh.
@ -157,3 +267,1 @@async def open_listener(self, **kwargs) -> trio.SocketListener:listeners = await trio.open_tcp_listeners(async def open_listener(i think maybe we should consider moving this to
MsgpackTransportas well?If it provides an interface around
SocketStream-like instances (for each peer pair) i think it makes more sense to maybe do something like,await MsgpackUDSStream.open_listener(addr=UDSAddress.get_random())instead of pulling weirdAddress()-instance-internal state?@ -176,3 +285,1 @@trio.SocketStream,trio.SocketListener]):def unwrap_sockpath(just a helper for any
UDSAddress..sockpath: Pathstyle partitioning to dir, filename.@ -67,3 +147,3 @@# defaults are abovearbiter_addr: tuple[AddressTypes]|None = None,arbiter_addr: tuple[UnwrappedAddress]|None = None,REALLY need to drop this!
XD
i’m hoping to get to a follow up registry-sys rework this week in a follow up PR!
@ -61,0 +72,4 @@# save an indent level?#@acmasync def maybe_block_bp(NOTE most of the diff in this file is just the higher indent of
open_root_actor()due to factoring this bp blocking stuff out!@ -202,3 +202,1 @@self.uid = (name,uid or str(uuid.uuid4())self._aid = msgtypes.Aid(Notice we always stash the pid now!
@ -1199,0 +1342,4 @@if ('[Errno 98] Address already in use'inoserr.args#[0]drop that
#[0]bit..@ -146,0 +152,4 @@_rtdir: Path = Path(os.environ['XDG_RUNTIME_DIR'])def get_rt_dir(used for our
UDSAddress.def_bindspace: path44fd1ecc41to8fd7d1cec4Refinements around multiple IPC transport protos (an appendix to #17)to Modular transports via a `tractor.ipc` subpkg!Modular transports via a `tractor.ipc` subpkg!to Modular transports via a `tractor.ipc` subpkg!Wow it seems i can’t update the
pull_frombranch here!?that’s like nuts..
I guess if it can’t be done i’m going to have to open a new PR.. or just land this branch i guess..
That is moving from `._addr`, - `TCPAddress` to `.ipc._tcp` - `UDSAddress` to `.ipc._uds` Obviously this requires adjusting a buncha stuff in `._addr` to avoid import cycles (the original reason the module was not also included in the new `.ipc` subpkg) including, - avoiding "unnecessary" imports of `[Unwrapped]Address` in various modules. * since `Address` is a protocol and the main point is that it **does not need to be inherited** per (https://typing.python.org/en/latest/spec/protocol.html#terminology) thus I removed the need for it in both transport submods. * and `UnwrappedAddress` is a type alias for tuples.. so we don't really always need to be importing it since it also kinda obfuscates what the underlying pairs are. - not exporting everything in submods at the `.ipc` top level and importing from specific submods by default. - only importing various types under a `if typing.TYPE_CHECKING:` guard as needed.800c99ac41toc9e9a3949fPrimarily moving the `Actor._serve_forever()`-task-as-method and supporting actor-instance attributes to a new `.ipo._server` sub-mod which now encapsulates, - the coupling various `trio.Nursery`s (and their independent lifetime mgmt) to different `trio.serve_listener()`s tasks and `SocketStream` handler scopes. - `Address` and `SocketListener` mgmt and tracking through the idea of an "IPC endpoint": each "bound-and-active instance" of a served-listener for some (varied transport protocol's socket) address. - start and shutdown of the entire server's lifetime via an `@acm`. - delegation of starting/stopping tpt-protocol-specific `trio.abc.Listener`s to the corresponding `.ipc._<proto_key>` sub-module (newly defined mod-top-level instead of `Address` method) `start/close_listener()` funcs. Impl details of the `.ipc._server` sub-sys, - add new `IPCServer`, allocated with `open_ipc_server()`, and which encapsulates starting multiple-transport-proto-`trio.abc.Listener`s from an input set of `._addr.Address`s using, |_`IPCServer.listen_on()` which internally spawns tasks that delegate to a new `_serve_ipc_eps()`, a rework of what was (effectively) `Actor._serve_forever()` and which now, * allocates a new `IPCEndpoint`-struct (see below) for each address-listener pair alongside the specified listener-serving/stream-handling `trio.Nursery`s provided by the caller. * starts and stops each transport (socket's) listener by calling `IPCEndpoint.start/close_listener()` which in turn delegates to the underlying `inspect.getmodule(IPCEndpoint.addr)` backend tpt module's equivalent impl. * tracks all created endpoints in a `._endpoints: list[IPCEndpoint]` which is further exposed through public properties for introspection of served transport-protocols and their addresses. |_`IPCServer._[parent/stream_handler]_tn: Nursery`s which are either allocated (in which case, as the same instance) or provided by the caller of `open_ipc_server()` such that the same nursery-cancel-scope controls offered by `trio.serve_listeners(handler_nursery=)` are offered where the `._parent_tn` is used to spawn `_serve_ipc_eps()` tasks, and `._stream_handler_tn` is passed verbatim as `handler_nursery`. - a new `IPCEndpoint`-struct (as mentioned) which wraps each transport-proto's address + listener + allocated-supervising-nursery to encapsulate the "lifetime of a server IPC endpoint" such that eventually we can track and managed per-protocol/address/`.listen_on()`-call scoped starts/stops/restarts for the purposes of filtering/banning peer traffic. |_ also included is an unused `.peer_tpts` table which we can hopefully use to replace `Actor._peers` in a `Channel`-tracking transport-proto-aware way! Surrounding changes to `.ipc.*` primitives to match, - make `[TCP|UDS]Address` types `msgspec.Struct(frozen=True)` and thus drop any-and-all `addr._host =` style mutation throughout. |_ as such also drop their `.__init__()` and `.__eq__()` meths. |_ UDS tweaks to field names and thus `.__repr__()`. - move `[TCP|UDS]Address.[start/close]_listener()` meths to be mod-level equiv `start|close_listener()` funcs. - just hard code the `.ipc._types._key_to_transport/._addr_to_transport` table entries instead of all the prior fancy dynamic class property reading stuff (remember, "explicit is better then implicit"). Modified in `._runtime.Actor` internals, - drop the `._serve_forever()` and `.cancel_server()`, methods and `._server_down` waiting logic from `.cancel_soon()` - add `.[_]ipc_server` which is opened just after the `._service_n` and delegate to it for any equivalent publicly exposed instance attributes/properties.This is now replaced by an equiv PR from the branch from #17 onto
shm_apis,https://github.com/goodboy/tractor/pull/375
Once i move desired content from the descr here to there i will be closing this one.
Landed in https://github.com/goodboy/tractor/pull/375
Pull request closed