-
Notifications
You must be signed in to change notification settings - Fork 36
Support async dispose
.
#168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
ea208e0
to
b145497
Compare
Instead of calling `dispose()` manually on both items, use `disposeBoth`. This is to encapsulate multiple disposition logic.
b145497
to
89625fd
Compare
Instead of returning `void`, return whatever the parent's `dispose()` had. This sets the stage for passing down results of `dispose()` functions and chaining them together using promises to wait in sequence for the result of disposing data.
Hey @izaakschroeder. Thanks for opening this. I see commits rolling in as I type this, so I wanted to get a message out to you quickly: let's discuss this before you put more energy into it. Originally, |
@briancavalier I thought about this a bit before too. I thought maybe I could track the open sessions and then just |
I'm assuming you moved away from async disposal for perf reasons? |
3c77965
to
748c950
Compare
@briancavalier Even if you don't want async disposal back, I think there are a few commits in here you can use anyway. The meat of the async disposal code is in 748c950 and is maybe 30 lines worth of changes. I think |
Hi @izaakschroeder. Yeah, there were performance implications, but the biggest reason was that use cases for async dispose proved to be extremely rare in practice. Originally, I had thought it would be a common thing, but it turned out that in practice it wasn't. In fact, this may be the only one I've ever run into! So, we decided to remove the async stuff (we missed LinkedList, oops!), and it simplified a lot of code. Thanks for giving some sample code. I'm not sure I fully understand all of it yet, but maybe we can try to boil it down to a few primary concerns. Are they something along the lines of:
Am I on the right track? |
@briancavalier Yeah. I mean this is just me playing with streams for integration tests right now. I've seen some very heavy lifting by people doing stuff like re-running tests, restarting selenium, etc. and it's all been rather messy. Seeing if streams were the answer. My thought process was:
In my example here Thanks for feedback so far 😄 |
The changes I've made in this PR are enough to cause that "serial" effect to happen and the result is |
Thanks for the extra info about the use case and the dependencies 👍. I should have time tomorrow to take a closer look and give this a bit more thought. |
Awesome thanks! 🙏 |
Hey @izaakschroeder, a few more questions after looking at the example:
Have you thought about other ways to approach this? For example, have you considered explicitly using streams to represent the lifecycle of the seleniums server and session, instead of using the dispose chain? That is, triggering shutdown using events rather than disposal? It's something that came up while the core team was discussing your example. Another interesting approach might be to embed one stream graph into another, i.e. via higher order streams. I'm imagining an outer stream that manages the creation, and later shutdown, of the server and session, and then that maps the session to an inner stream of tests. I'm probably not fully understanding how your vision for how tests might work, but maybe that will give you some ideas. |
Hey @briancavalier thanks for the update 😄
I'm not the most experienced with streams, I'm totally open to other approaches. One could use something other than the dispose chain but the big deal is that the dispose chain knows when the resource is no longer used, which is really what I'm after – not having to do ref counting myself. There are other sub-processes that need to be involved in this too like spinning up a mock API server for each test in addition to opening a selenium session. I just kind of want one way to have my resources freed when they're no longer needed and |
Hey @izaakschroeder, sorry I haven't replied. I've been focused on getting |
No rush @briancavalier thanks for the feedback so far. |
@briancavalier any updates? 😄 |
Hey @izaakschroeder, sorry for the late reply yet again. I appreciate your patience :) I've been very busy at work since the beginning of the year, and haven't had much time to spend on open source. I just read through all the comments again, and am looking at the changes to refresh my memory. I'll bring the issue up with the core team for discussion this week. One concern I remember having is about types. It looks like even though the JavaScript implementation can be made compatible with |
It looks like there started out work to implement async dispose as seen in
LinkedList
as if the expected result ofdispose()
was aPromise
:Unfortunately this behaviour exists nowhere else in the codebase and
dispose()
is called immediately everywhere. This is problematic if one wishes to usemost
to do resource management and the results carry several streams deep. For example:Previously the
test1
stream would end and the selenium server would be killed immediately because itsdispose()
method would be called without waiting for thedipose()
ofsession
.The changes here are pretty redumentary and need some cleanup, but it allows one to return a
Promise
fromdispose()
and wait for the result to finish before continuing to dispose of resources.TODO:
disposeParallel
instead ofdisposeSerial
?Promise.all
inLinkedList
actually desirable? Errors are not collected the same way as they are indisposeAll
.most
for resource management is maybe a contrived but interesting use case – I'm sure I'm doing something non-optimally here to begin with.These changes are not breaking – if nothing in your
dispose()
chain is async then no promises are used and errors get thrown as before. I'm not sure if two pathways is the best (maybe always use promises?) but the current version means no changes for consumers.