Giter Club home page Giter Club logo

Comments (9)

jonhoo avatar jonhoo commented on August 30, 2024

I agree with you that having to call drop explicitly is pretty unfortunate. The reason it is currently needed is to avoid swallowing any errors. I could have the implementation of Drop resolve the fin future internally, which would in turn mean you can just let Client fall out of scope as normal, but this would also mean that if any errors occur when tearing down the connection, that error would either be hidden from the user, or cause a panic (if drop calls unwrap).

For what it's worth, the reason that Client has to be explicitly dropped is that it internally contains a reference-counted Inner (This is what allows Client to be Clone). Only when the last Client is dropped will Inner's destructor be called (which calls shutdown). If shutdown isn't called, then a) the WebDriver session isn't terminated, and b) fin would never resolve.

from fantoccini.

jonhoo avatar jonhoo commented on August 30, 2024

Pushed a proposed change in bd4c9d1 — how does that look to you?
See in particular:

fantoccini/src/lib.rs

Lines 362 to 369 in bd4c9d1

/// Note that most callers should explicitly call `Client::close`, and wait for the returned
/// future before exiting. Not doing so may result in the WebDriver session not being cleanly
/// closed, which is particularly important for some drivers, such as geckodriver, where
/// multiple simulatenous sessions are not supported. If `close` is not explicitly called, a
/// session close request will be spawned on the given `handle` when the last instance of this
/// `Client` is dropped.
#[cfg_attr(feature = "cargo-clippy", allow(new_ret_no_self))]
pub fn new(

and

fantoccini/src/lib.rs

Lines 757 to 771 in bd4c9d1

/// Terminate the connection to the webservice.
///
/// Normally, a shutdown of the WebDriver connection will be initiated when the last clone of a
/// `Client` is dropped. Specifically, the shutdown request will be issued using the tokio
/// `Handle` given when creating this `Client`. This in turn means that any errors will be
/// dropped, and that the teardown may not even occur if the reactor does not continue being
/// turned.
///
/// This function is safe to call multiple times, but once it has been called on one instance
/// of a `Client`, all requests to other instances of that `Client` will fail. The returned
/// `Option` will only be true the first time `close` is called.
///
/// This function may be useful in conjunction with `raw_client_for`, as it allows you to close
/// the automated browser window while doing e.g., a large download.
pub fn close(self) -> Option<impl Future<Item = (), Error = hyper::Error>> {

As well as the updated examples in the README.

from fantoccini.

phrohdoh avatar phrohdoh commented on August 30, 2024

This is definitely a usage improvement!

Is there machinery that prevents the fin future from being driven to completion (thus ending the session) before the actual work is completed?

from fantoccini.

jonhoo avatar jonhoo commented on August 30, 2024

This is definitely a usage improvement!

Great!

Is there machinery that prevents the fin future from being driven to completion (thus ending the session) before the actual work is completed?

Hmm, I'm not entirely sure what you mean here. I think what you're asking is why fantoccini can't just internally run the fin future to completion, and thus do the cleanup for the user? If so, the answer is that the library only has a Handle to the Tokio Core used to drive the HTTP connection to the WebDriver server. It can schedule work for that core using the handle, but it can't actually execute that work. Therefore, it becomes up to the caller (who has the Core) to use core.run() to complete the request. The library also cannot just create a new Core for doing cleanup, because the hyper::Client is already tied to the user's original Handle:

fantoccini/src/lib.rs

Lines 382 to 384 in 5998924

let client = hyper::Client::configure()
.connector(hyper_tls::HttpsConnector::new(4, handle).unwrap())
.build(handle);

from fantoccini.

phrohdoh avatar phrohdoh commented on August 30, 2024

Sorry I was not very clear.

I meant "are we sure that the cleanup future won't execute until after all of the actual work* is done?"

from fantoccini.

jonhoo avatar jonhoo commented on August 30, 2024

Ah, I see. Technically, no. I don't think tokio/hyper gives guarantees about the order in which futures/requests are resolved. Given that they're all asynchronous, I suppose theoretically some existing WebDriver request could be lying around somewhere, not yet written to the wire, and then the shutdown command could be spawned on the core and race ahead of the existing command. But this sounds pretty unlikely to occur in practice to me. it's also not clear that we have a way to guard against this internally in the library, since we have no control over the execution of the futures that we return.

from fantoccini.

jonhoo avatar jonhoo commented on August 30, 2024

Publishing this now as 0.8.0, but open to further suggestions for how to improve the API :)

from fantoccini.

ababo avatar ababo commented on August 30, 2024

@jonhoo Still didn't get is there a way to make Client to close when exiting its scope?

from fantoccini.

jonhoo avatar jonhoo commented on August 30, 2024

No, sadly there is no such way since when a Client is dropped it is not able to execute any asynchronous code. We could perhaps check if there was still an active runtime, and if so, spawn the destructor, but that's itself pretty error-prone, and could result in some weird unexpected behavior. What we really want are Asynchronous Destructors, but those don't seem like they're going to be here any time soon.

from fantoccini.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.