Resolve cyclic dependencies by aligning GRPCClient
derived classes and NodeConnection
to StartStop
pattern
#333
Labels
GRPCClient
derived classes and NodeConnection
to StartStop
pattern
#333
Specification
Currently we have 2 connection abstractions in PK:
network
-Connection
andConnectionForward
andConnectionReverse
- usesStartStop
grpc
&nodes
-GRPCClient
,GRPCClientAgent
,GRPCClientClient
andNodeConnection
- usesCreateDestroy
As you can see the
network
is using theStartStop
pattern and thegrpc
&nodes
is usingCreateDestroy
.The
CreateDestroy
is fundamentally more limiting thanStartStop
, as it enforces a sort of logical order, where asynchronous side-effects must occur first before you are given the actual object instance. Thus tying the object-lifetime to asynchronous setup and shutdown.Originally I wanted to apply
CreateDestroy
tonetwork
domain, but was impacted by some cyclic dependencies that existed innetwork
domain. However now there are cyclic dependencies in thegrpc
andnodes
domain, and it appears thatCreateDestroy
is too limiting, and instead we need to useStartStop
.Now what are these cyclic dependencies? They all boil down to needing to do some asynchronous side-effects while having access to the instance itself.
For example in
ConnectionForward
, thestart call makes use of
this.utpSocketand
this.tlsSocket, which are all properties of the instance. Some complex refactoring could move this all into async creation, and then passed in as properties of the
ConnectionForward` instance, but this is unnecessary complexity when all these properties have to be part of the instance.In the case of
NodeConnection
, we have a problem where it causes us to construct the instance firstnew NodeConnection()
and then setup theGRPCClient
and then inject the client object into theNodeConnection
instance.The reason for this is because the creation of the
GRPCClient
requires thedestroyCallback
to be set, and that requires a reference to thenodeConnection
instance.This round-about way of doing things makes things a bit strange/convoluted for no reason.
If the creation logic of
GRPCClient
andNodeConnection
were instead changed toStartStop
pattern, then we can proceed to make this logic much more cleaner.It does mean you may have
NodeConnection
instances that are not started. But that's ok, since ournetwork
proxies handle this by removing themselves from the connection proxies when they are stopped. Thenodes
connection make use of a genericdestroyCallback
to do this same behaviour. The main difference is thatnetwork
connections hardcode knowledge about the connection state from the proxies, and require it during construction. See theconnections
parameter inConnectionForward
andConnectionReverse
. WithGRPCClient
, this is more difficult sincenodes
andgrpc
are separate domains, so we don't want to hardcode knowledge aboutnodes
connection management into thegrpc
classes.Additional context
NodeManager
toNodeConnectionManager
#310 - PR that extracted node connection management intoNodeConnectionManager
Id
js-id#13 (comment) - Some discussion about polymorphicthis
, this may not be relevant if we useStartStop
Tasks
GRPCClient
andGRPCClientClient
,GRPCClientAgent
andGRPCClientTest
toStartStop
NodeConnection
toStartStop
NodeConnectionManager
, and base it on howForwardProxy
andReverseProxy
handles itThe text was updated successfully, but these errors were encountered: