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

setTimeout problems / questions #69

Closed
joshkel opened this issue Oct 18, 2021 · 4 comments
Closed

setTimeout problems / questions #69

joshkel opened this issue Oct 18, 2021 · 4 comments

Comments

@joshkel
Copy link
Contributor

joshkel commented Oct 18, 2021

I'm having some problems since the upgrade to 3.1.4; Jest tests that previously worked fine are now timing out. I did some digging, and if I understand correctly:

  • Starting with 3.1.4, fake-indexeddb uses setTimeout instead of setImmediate.
  • In Node.js, setTimeout enforces a minimum delay of 1ms, so every fake-indexeddb operation takes at least 1 millisecond.
  • On Windows, from what I can tell, the Node.js timer has a resolution of ~15ms, so every fake-indexeddb operation takes at least 15 milliseconds.
  • jsdom uses Node.js's setTimeout implementation unchanged, so all of the above applies in jsdom test environments as well.

I experimented with using Jest's fake timers to speed up my tests, but they don't appear to be a great solution: because IndexedDB operations result in fake-indexeddb timers which resolve promises which may then trigger additional IndexedDB operations (etc.), there's an awkward dance of trying to figure out which timers and promises are outstanding after each operation so that they can all be properly resolved. (See the linked test case for an example of what this looks like - this gets even harder when using third-party code that may do multiple IndexedDB operations in a row. Maybe there's an easier way to do this in Jest? If so please let me know.)

We ran into this using the idb-keyval package, which, in order to keep a simple API, relies on lots of small operations.

Test case: https://github.com/joshkel/fake-indexeddb-settimeout-test-case

Timings for the "create and read a bunch of values" from that project in fake-indexeddb 3.1.4:

  • macOS, Node.js 14.17.1 - 71 ms
  • Windows, Node.js 14.17.0 - 54 ms

In fake-indexeddb 3.1.3:

  • macOS, Node.js 14.17.1 - 734 ms
  • Windows, Node.js 14.17.0 - 6734 ms
@ath0mas
Copy link

ath0mas commented Oct 18, 2021

Same issue for me updating from 3.1.3 to 3.1.4 as I told in #67.
I did not had much time to work on having a repro, just found that translating ph-fritsche/repro-jest-jsdom-indexeddb from jest to mocha is still running without such problem. So I would have to start from my own code to try and reduce it to a minimal repro.

My setup:

  • Windows, Node 14/16
  • latest versions of mocha, jsdom, jsdom-global, idb, fake-indexeddb, typescript, ts-node
  • no fake timers

@jleider
Copy link

jleider commented Oct 18, 2021

We just ran into issues here as well trying to get a simple test working on a standard factory open call. The setTimeout in the mocked open function was never invoked. Rolling back to 3.1.3 solved the issue for us.

Node v12.14.1

@dumbmatter
Copy link
Owner

dumbmatter commented Oct 18, 2021

Thanks for looking into this. I'm really not sure what the best solution is here, but let me try to summarize the problem as I understand it:

#68 by @ph-fritsche would make it configurable whether to use setTimeout or setImmediate. But that would still not help for people facing both of the problems above - they could only fix one of those problems, not both.

There must be a better solution. Off the top of my head, I'm not sure what that is. But if someone could figure out how to either:

  • successfully use setImmediate and jsdom together, or
  • run a macrotask in a way that is faster than setTimeout and not interfered with by jsdom (process.nextTick won't work, it's too fast!)

then that would allow me to fix this issue for all cases.

@dumbmatter
Copy link
Owner

Fixed in v3.1.6, thank you @joshkel and everyone else who helped debug this!

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

No branches or pull requests

4 participants