Repository navigation
Apply timedCancellable across the board to control how long side-effects are allowed to complete #450
Copy link
Copy link
Closed as not planned
6 / 76 of 7 issues completedClosed as not planned
Apply
timedCancellable across the board to control how long side-effects are allowed to complete#4506 / 76 of 7 issues completed
Copy link
Labels
developmentStandard developmentStandard developmentr&d:polykey:supporting activitySupporting core activitySupporting core activity
Description
Specification
With the application of timedCancellable to functions within the nodes domain. We have encountered new connection errors randomly during tests. These error started after applying a deadline of 1500 ms to pingNode usage. We suspect the problem is coming from openConnectionForward after setting such a short deadline. These may be bugs that existed previously that was never revealed by the current testing. Currently there is 1 NodeConnectionManager test where we override the deadline for openConnectionForward.
The occur randomly and are as follows. the can be re-created by running all of the nodes domain tests concurrently.
Details
Error: Socket is closed
at UTP.Object.<anonymous>.UTP.send (/home/faulkes/matrixCode/polykey/js-polykey/node_modules/utp-native/index.js:121:50)
at /home/faulkes/matrixCode/polykey/js-polykey/src/utils/utils.ts:178:9
at new Promise (<anonymous>)
at UTP.<anonymous> (/home/faulkes/matrixCode/polykey/js-polykey/src/utils/utils.ts:163:12)
at constructor_.send (/home/faulkes/matrixCode/polykey/js-polykey/src/network/Connection.ts:79:11)
at Timeout.<anonymous> (/home/faulkes/matrixCode/polykey/js-polykey/src/network/ConnectionReverse.ts:147:20)
at listOnTimeout (node:internal/timers:559:17)
at processTimers (node:internal/timers:502:7)
Error: Unhandled error. (Error: UTP_ECONNRESET
at createUTPError (/home/faulkes/matrixCode/polykey/js-polykey/node_modules/utp-native/lib/connection.js:238:15)
at Connection.Object.<anonymous>.Connection._onerror (/home/faulkes/matrixCode/polykey/js-polykey/node_modules/utp-native/lib/connection.js:175:16) {
code: 'UTP_ECONNRESET',
errno: 1
})
at new NodeError (node:internal/errors:372:5)
at Connection.emit (node:events:516:17)
at Connection.Object.<anonymous>.Connection._onclose (/home/faulkes/matrixCode/polykey/js-polykey/node_modules/utp-native/lib/connection.js:169:25)
Error: address already in use
at UTP.Object.<anonymous>.UTP.bind (/home/faulkes/matrixCode/polykey/js-polykey/node_modules/utp-native/index.js:198:13)
at /home/faulkes/matrixCode/polykey/js-polykey/src/utils/utils.ts:178:9
at new Promise (<anonymous>)
at UTP.<anonymous> (/home/faulkes/matrixCode/polykey/js-polykey/src/utils/utils.ts:163:12)
at Object.<anonymous> (/home/faulkes/matrixCode/polykey/js-polykey/tests/nodes/NodeManager.test.ts:83:11)
Additional context
- Related discussion starting at Integrate TaskManager into NodeGraph and Discovery #445 (comment)
- Related Integrate TaskManager into NodeGraph and Discovery #445
- Related Apply
timedCancellabletoSigchainsuch as the deadline in nodes claim process #243 - Related Add extra testing for nodes claims process #242
Tasks
- Explore and find the root cause of the errors
- Apply a fix for the errors
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
developmentStandard developmentStandard developmentr&d:polykey:supporting activitySupporting core activitySupporting core activity
Activity
[-]Fix errors due to short `pingNode` timeout[/-][+]Apply `timedCancellable` across the board to control how long side-effects are allowed to complete[/+]tegefaulkes commentedon Sep 28, 2022
This is going to be a pretty large change. Converting everything to
TimedCancellableis pretty simple. there is just a lot of things to change and cover.TimedCancellablealready but needs to be reviewed again.tegefaulkes commentedon Sep 28, 2022
I don't think the default timeout for the
timedCancellabledecorator can be set at any time. It has to be defined at import time. This means we can't configure a default time when starting theNodeConnectionManager. We also don't want to have hard coded timeouts everywhere so we may have to define the defaults in the config file.CMCDragonkai commentedon Sep 29, 2022
There are several places where
timedCancellableand variants of this should be used. Basically anywhere where there is non-deterministic side-effects.Pretty much all of them concern around network usage.
Promise.racework arounds until https://github.com/MatrixAI/js-async-locks/issues/21For long running computations, we're talking about generators and related iterators. In these cases, the cancellation of generators hasn't been entirely worked out yet, and instead it is expected that you would stop consuming the generator (if you don't ask for the next item, it would continue computing). The only case where cancellation applies is when you do ask for the next item, but you must await for it, in which case you'd like to have the ability to do
p.cancel(). However atm, we don't have this ability yet, so instead, you may need to pass an overall signal to the generator function and for it to signal cancellation the traditional way.Remember similar to
async ffunctions, I believeasync f*forces them to be regular promises and not our extended promises. But I don't remember if I confirmed this fact.As for the network, pretty much all network operations should be cancellable or timed cancellable if there's a timeout. This requires a big major refactor of the
Proxycode to support this. There are multiple "default" timeouts currently configured during class construction. If we use the decorators, the defaults has to be set statically and cannot take in instance parameters.Alternatively you can also not use the decorators, and just directly use
PromiseCancellablewhile taking in the signal. That would allow you to take the instance/constructor parameters as the defaults for theProxy.So we have to decide whether to use static parameters and the decorators, or whether to swap to just using the
PromiseCancellableand taking in the signal directly.It's important to understand that the decorators are for convenience, but they are not infinitely flexible, it trades off some flexibility for some better convenience.
CMCDragonkai commentedon Sep 29, 2022
Yes, because if decorators are static, then the parameters they take are static too. This is of course only necessary for "default" deadlines. Whatever is passed into the method/function will override it. If we do use static deadlines, then it does make sense to propagate these static parameters directly from the config object.
I discussed that you can also use signals and promise cancellable directly in the method to avoid static parameterisation...
CMCDragonkai commentedon Sep 29, 2022
I suggest we do a priority here.
networkdomain, we should refactor this to support timers and cancellability (this may mean we can remove the existing timer utility)Also additionally there's the
identitiesdomain, which also has network side effects from contacting identity providers, these should also start using timed cancellable too.CMCDragonkai commentedon Sep 29, 2022
I'm thinking there's sort of like 3 levels of defaults here:
src/config.tsI'm not sure if
2is possible if we use the decorators, unless we change them up to look up parameters on the instance if the method parameter isn't passed in (that is is set toundefined). But we would need to pass in astringto indicate the name of the parameter to look up.CMCDragonkai commentedon Sep 29, 2022
I think it is possible to do all 3.
This is the function head:
It's possible to do something like:
And then do
timedCancellable('lazyProp', delaySym). And later use thethis[lazy]andthis[delay]to acquire the parameters.However this pattern may not be scalable to other decorators which have actual string/symbol parameters...
So it may be better to actually have a separate set of parameters to refer to the instance.
But I find this syntax way too verbose...
We could also use a more different type like arrow functions.
It'd be unlikely for a decorator parameter to be an arrow function, but if they needed to differentiate, they could also check the number of parameters... etc.
Notice the
thisis literallyanyhere.Using it would be like:
CMCDragonkai commentedon Sep 29, 2022
The last style is likely the more flexible.
CMCDragonkai commentedon Sep 29, 2022
I've added related issues #243 and #242. They should be addressed together here.
If there are going to be multiple PRs here, this should be made an epic and with subissues and subPRs.
CMCDragonkai commentedon Sep 29, 2022
Full work on this might take 1 sprint and a bit.
CMCDragonkai commentedon Sep 29, 2022
The todos relating to cancellability should also be done in this issue. This issue is an epic so there are multiple subissues. @tegefaulkes you can add more issues into this epic as you see fit.
14 remaining items
CMCDragonkai commentedon Apr 24, 2023
The deadline mechanism works in the JSON RPC system now. It's just a matter of doing agent migration. But also ensuring that the subissues here are completed.
CMCDragonkai commentedon Jul 10, 2023
Applying it to sigchain depends on agent migration.
Applying it to identity management only requires bridging it to the underlying IO which can be just the
fetchfunction provided bycross-fetch.tegefaulkes commentedon Oct 18, 2024
This issue is very old and predates the network stack overhaul. I'm going to close it as not planned.
CMCDragonkai commentedon Oct 18, 2024
This is still required. It's independent of networking. It's basically any kind of operation that is meant to be timed and cancellable. It's a general pattern. Of course new issues should be more specific.
NodeConnectionManager) #353timedCancellabletoSigchainsuch as the deadline in nodes claim process #243timedCancllabledecorator to support dynamic timeouts #463Proxydomain to usetimedCancellable#464Nodesdomain to usedtimedCancellable#465Discoverydomain to usetimedCancellable#477