Skip to content
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

AbortController #182

Closed

Conversation

ilan-gold
Copy link
Contributor

Fixes #170. I'm opening this as a draft so you may comment on the API structure here. I return empty arrays when the request is aborted - is there an edge case I am missing here? I can also raise an error, but I don't know if we want that error propagating out of the library. Let me know!

src/source.js Outdated Show resolved Hide resolved
@ilan-gold
Copy link
Contributor Author

@kylebarron I think this is ready for testing, if you want to give it a whirl, with the new release of deck.gl - changing your package.json entry to ilan-gold/geotiff.js#ilan-gold/signal_abort_controller should do the trick. I'm opening it up to review now for @constantinius to take a look at.

@ilan-gold ilan-gold marked this pull request as ready for review October 14, 2020 22:42
src/geotiffimage.js Outdated Show resolved Hide resolved
src/source.js Show resolved Hide resolved
@ilan-gold ilan-gold marked this pull request as draft October 16, 2020 19:29
@ilan-gold ilan-gold marked this pull request as ready for review December 1, 2020 14:35
Copy link
Member

@constantinius constantinius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice PR!

For a merge, I'd hope that you are able to provide at least one test (if that is possible) and also some documentation (a small section in the Readme should be enough).

@ilan-gold
Copy link
Contributor Author

@constantinius Just added some docs and testing.

@ilan-gold
Copy link
Contributor Author

@constantinius Just resolved the conflict.

@constantinius
Copy link
Member

@ilan-gold

One last nitpick: In my opinion the readRasters should throw an error when it was aborted, or at least return null (I'm not sure about the conventions here but the MDN docs say that fetch raises an exception upon abort).

@ilan-gold
Copy link
Contributor Author

@constantinius Should the other methods do this as well? We would change from returning some "empty" object to raising an error.

@constantinius
Copy link
Member

@ilan-gold
Which methods do you mean, exactly? Is there a way to let the exceptions bubble from the source itself? Then the problem would be solved in a single spot, I think.

@ilan-gold
Copy link
Contributor Author

I was referring to readRgb mainly but I think that calls readRasters - my bad. I will update to throw an error.

@ilan-gold
Copy link
Contributor Author

@constantinius Doing this now, but realizing DOMException does not exist in Node. Should we throw a different error?

@ilan-gold
Copy link
Contributor Author

Just reading your other comment, we could return null. We could also throw a generic error (I like this option).

@constantinius
Copy link
Member

My thought was to use whatever exception is thrown in the async operation when aborted, so that we don't have to deal with it and just let that exception bubble up

@ilan-gold
Copy link
Contributor Author

@constantinius That is ok with me but we won't be able to test this if we let the exception bubble up since all the tests run in Node, where the AbortSignal API is not available. We could use node-fetch, but that would then be the default fetch for all tests. I think it would be ok to just use a generic Error in all cases, especially since we would need to something like

// Re-use the thrown AbortError.
    let abortException;

    // determine if we are the thread to start the requests.
    if (this.blockIdsAwaitingRequest) {
      ...
            catch (err) {
              if (err.name === 'AbortError') {
                abortException = err;
                this.blocks.delete(id);
                this.blockRequests.delete(id);
                this.signals.delete(id);
                this.abortedBlockIds.add(id);
     ...
    // Some of the blocks were cancelled by a signal (AbortController)
    if (blocks.some((i) => !i)) {
      // But not by this fetch's signal
      if (signal && !signal.aborted) {
        allBlockIds.forEach((blockId) => {
          if (this.abortedBlockIds.has(blockId)) {
            const request = this.requestData(
              blockId * this.blockSize, this.blockSize,
            );
            this.blockRequests.set(blockId, (async () => {
              const response = await request;
              const t = Math.min(this.blockSize, response.data.byteLength);
              const data = response.data.slice(0, t);
              this.abortedBlockIds.delete(blockId);
              this.blocks.set(blockId, {
                data,
                offset: response.offset,
                length: data.byteLength,
                top: response.offset + t,
              });
            })());
            abortedBlocksToBeRequested.push(this.blockRequests.get(blockId));
          }
        });
      // Blocks were cancelled by this signal.
      } else if (signal && signal.aborted) {
        throw abortException;
      }

to reuse the exception.

@kylebarron
Copy link

since all the tests run in Node, where the AbortSignal API is not available

By the way, it should be possible to run tests in a browser environment outside of Node. deck.gl does it using XVFB. Though since I believe geotiff.js is intended to run in both browser and Node the point is a little moot.

@constantinius
Copy link
Member

@ilan-gold I see. Then raising a normal Error is best!

@kylebarron I'm open for new ideas to test!

@ilan-gold
Copy link
Contributor Author

@constantinius I updated the error generation but the tests log a warning that is both cryptic and hard to solve (if you google "UnhandledPromiseRejectionWarning chai" there are a lot of ways to handle this but none seemed to work for me). I can comment out the test if you wish. Otherwise, I think this is ready.

@constantinius
Copy link
Member

@ilan-gold

I reworked the whole "sources" part of geotiff.js in #94 and chose to directly incorporate the AbortController. I re-used a lot of stuff from your PR (which is effectively superseded). I would very much welcome if you could try it out and comment there!

@ilan-gold
Copy link
Contributor Author

Yes of course @constantinius!!!! Anything to help out, much appreciated :) I'll give it a whirl.

@constantinius
Copy link
Member

@ilan-gold this whole topic was integrated in PR #94

I got a lot of inspiration from this PR. Please have a look at the code and tell me if there is still some part missing.

Otherwise I think we can close this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for AbortController to fetch functions
3 participants