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

Add expo-sqlite, the ability to test it, and a promisifying wrapper #5184

Merged
merged 18 commits into from Jan 11, 2022

Commits on Jan 11, 2022

  1. storage [nfc]: Make src/storage/ for below-Redux storage layers

    We'll be adding a bit more code in this area shortly.  "Storage"
    makes a more apt name for this than "boot".
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    22c77ef View commit details
    Browse the repository at this point in the history
  2. deps: Add expo-sqlite

    This isn't quite the latest version; for now we'll use v9.x in order
    to stick with "unimodules".  Issue zulip#5133 is open for the migration
    that'll let us advance to v10.x.
    
    Include a libdef, generated with flowgen with small manual fixups
    as described in comments.  The libdef is actually from a newer
    version because that's what I tried first; I tried rerunning flowgen
    on the older version, and the differences in the new one are pure
    compatible improvements (cleaning up some type definitions; adding
    comments; replacing `any[]` as the type for `args` on `executeSql`.)
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    995422a View commit details
    Browse the repository at this point in the history
  3. expo-sqlite types: Mark a read-only array

    Studied the implementation (at 10.0.3) and confirmed that this array
    doesn't get mutated.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    59f7903 View commit details
    Browse the repository at this point in the history
  4. deps: Add sqlite3 as a dev-dependency

    We'll use this to get SQLite in the Jest environment, on Node.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    6a9564c View commit details
    Browse the repository at this point in the history
  5. deps: Force sqlite3 to use a recent node-gyp

    In particular this leads to using a reasonably recent `tar` package,
    fixing vulnerabilities in the old one it was using.
    
    Upstream has already bumped this to node-gyp 7.x in their master
    branch, but haven't posted a release to NPM:
      TryGhost/node-sqlite3#1493
    
    Empirically node-gyp 8.x, the latest, works fine.  That's also
    reported by someone on that issue thread:
      TryGhost/node-sqlite3#1493 (comment)
    May as well go for that, then.  (There was no 8.x yet when the
    version specified in sqlite3 was bumped to 7.x.)
    
    Some other people on that thread report using a fork made by the
    VS Code developers, which posted some releases in November.  But
    that fork seems pretty clearly intended for VS Code's own internal
    use, with no promises for broader consumption:
      microsoft/vscode-node-sqlite3#14 (comment)
    so that doesn't seem like an improvement over upstream.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    a7d19c0 View commit details
    Browse the repository at this point in the history
  6. sqlite3: Add type definitions, as a .js.flow rather than libdef

    This is much, much nicer for actually writing the types than a
    libdef would be.  In particular iterating on changes is much
    faster and easier, because Flow does its usual incremental thing
    rather than restarting from scratch on each edit.
    
    More details in some new docs text in howto/libdefs.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    007dea3 View commit details
    Browse the repository at this point in the history
  7. Configuration menu
    Copy the full SHA
    6634190 View commit details
    Browse the repository at this point in the history
  8. expo-sqlite tests: Get a working immediate in Jest

    The `@expo/websql` package (aka `node-websql`) that provides most of
    the JS layer of expo-sqlite uses in turn the `immediate` package to
    get an implementation of basically `setImmediate`.
    
    In Jest tests, that doesn't work; the symptom is that the test hangs
    and then times out at 5 seconds, not having completed.  Looking at the
    `immediate` implementation, it relies on `process.nextTick` (when
    that's present, i.e. on Node).  With Jest's "modern" fake timers --
    which we now use, and have for a while -- that's mocked out, so that
    explains why the "immediate" callbacks never get run.  (The
    implementation also uses `setTimeout`, in what seems to be a
    convoluted substitute for try/catch.  So that'd be an additional
    reason it wouldn't work, if it got that far.)
    
    We live in a JS world that has Promises.  Given those, setImmediate
    has a trivial implementation.  Replace the whole module with that.
    
    Quite likely we want a similar substitution in the actual app, but
    leave that for another time for now, because in the app this module
    seems to at least be working at all.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    9c61edb View commit details
    Browse the repository at this point in the history
  9. expo-sqlite tests: Write a mock version of expo-sqlite

    Mostly this amounts to a fourth platform-specific implementation for
    expo-sqlite: upstream has implementations for Android, iOS, and web,
    and this is one for Node.
    
    The one "mock" aspect is that this keeps the underlying databases in
    memory, rather than on disk.  That's helpful for isolation.  There's
    also an extra function provided, to delete a database.
    
    Include a small smoke-test to demonstrate that this does indeed run.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    04805f8 View commit details
    Browse the repository at this point in the history
  10. expo-sqlite tests: Basic transactions tests

    These just exercise simple happy cases of using transactions.
    
    If you do something more complicated -- like the transaction's code
    hits an unexpected error midway through, or you need to do some
    asynchronous work with the result of one query before making the
    next -- then expo-sqlite turns out to not behave so well.
    
    Those tests get more complicated to write (partly because of the
    bad behavior itself, and the need to protect the Jest environment
    from it), so we'll add them separately.  We'll also work around
    them in the promisified wrapper we'll be adding over expo-sqlite.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    ded9cb9 View commit details
    Browse the repository at this point in the history
  11. expo-sqlite tests [nfc]: Simplifying helpers to bridge callbacks vs. …

    …Jest
    
    As we add more, and more-complex, tests here, these will help keep
    them from getting too noisily verbose with just the boring mechanics
    of wiring up expo-sqlite's callbacks-based API to the flow of Jest.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    21736e9 View commit details
    Browse the repository at this point in the history
  12. expo-sqlite tests: Demo the broken asynchrony handling

    This test shows that if using expo-sqlite you try to make a
    transaction that involves some asynchronous work between SQL queries,
    the transaction gets committed in a half-done state.
    
    This is a limitation that stems from Web SQL Database, the API (an
    old proposed standard, implemented in Chromium-based browsers but no
    others) that expo-sqlite mostly provides: that API doesn't provide
    any way for the implementation to know when you're done with any
    async work, so effectively it assumes you don't try to do any.
    
    Moreover there's an implementation bug, which isn't due to the API:
    when you do try to do this, the subsequent statements you try to add
    to the transaction get silently ignored, with no error.
    
    We'll work around this issue in the promisifying wrapper we'll add
    atop expo-sqlite.  Meanwhile, this test serves to demonstrate what
    the issue is in the first place.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    102c6da View commit details
    Browse the repository at this point in the history
  13. mock-immediate: Give immediate a mockier mock

    The base behavior is the same as the one-line implementation we'd
    had, but now there are some knobs for tests to turn.
    
    This will let us test code -- for example expo-sqlite, and its
    dependency `@expo/websql` / node-websql -- that uses `immediate`
    and allows exceptions to propagate to it unhandled.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    d0fcdb7 View commit details
    Browse the repository at this point in the history
  14. Configuration menu
    Copy the full SHA
    0804092 View commit details
    Browse the repository at this point in the history
  15. expo-sqlite tests: Show transactions' (non-)handling of exceptions

    We'll work around this behavior with our promisified wrapper.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    9af36d1 View commit details
    Browse the repository at this point in the history
  16. sqlite: Write a simple promisifying wrapper over expo-sqlite

    This simple version has some important caveats -- limitations of
    the underlying expo-sqlite library, which become more salient with
    the higher expectations set by a Promise-based API.  We'll add
    workarounds in upcoming commits to resolve those issues.
    gnprice committed Jan 11, 2022
    Configuration menu
    Copy the full SHA
    ce2a3da View commit details
    Browse the repository at this point in the history
  17. Configuration menu
    Copy the full SHA
    328963e View commit details
    Browse the repository at this point in the history
  18. Configuration menu
    Copy the full SHA
    88e46d5 View commit details
    Browse the repository at this point in the history