As Erel suggested, doing an async SQL query seems like the proper way to do this. However, I don't trust myself to modify the KVS (or Serializator) source, and I'd rather not have to dust off my limited SQL skills from 30 years ago.
I also didn't immediately understand how locks work in the Threading library, so I ultimately went with this amateur solution to avoid data contention:
- When the app loads, load the current poker hand from the KVS data file.
- Copy the data file, and load the old hands from the second file in a background thread, while the user plays more hands. (Typically takes up to 10 seconds.)
- Delete the second data file. The thread auto-ends when the load is finished.
- If they happen to call up the stats page before the old hands are loaded, show a spinner until the load is done.
I suppose this is "cheating" in terms of proper database management, but using a temporary second data source eliminated the need for locks. Also, it took 5 minutes to code, I understand the code I wrote, and it seems to work, so I'm calling it a win for now.