this reverts commit 749a323597. the pool
does hurt performance and concurreny, so let's revert now that we can.
Change-Id: I0b154cf04d14fa2cb4d2028f9cc865e463cd2265
connection pools of remote stores can currently block. this is not a
problem when each request runs on a dedicated thread, but with async
code this is no longer true. if a remote store has exhausted all its
available connections on one executor and another job starts *on the
same executor* we'll deadlock if that job makes another remote store
request. unlike with sqlite previously it's not reasonable, not even
necessary, to make the pools unbounded: since we use pools only with
remote stores we can asyncify all of them at once, and since they're
leaves of all call stacks we do not have much code to change either.
Change-Id: I8c457e27893e22c2cfc35933307a5283c986805a
this is a connection pool of size 1. it's also extremely in the way of
making store methods async since all methods are necessarily entangled
with all other methods via this blocking connection pool. we also will
not be able to convert *all* public methods to async code at once (not
without losing what little remains of our sanity, anyway). we'll treat
the connection pool as unbounded for a while, until the conversion has
been completed. if it turns out to be too expensive to keep db handles
in a pool like this we can tune it back down to small, or even size 1.
Change-Id: I0f3adb66df6f45a84e480c090d6627a368917db5
processGraph is not always safe to use in async code, but whether that's
the case depends on whether the caller is holding locks or not. (-sigh-)
Change-Id: Ieecea9c6d3c6abae222332bc6e3869bfd97631dd
this could be a method of AsyncCollect, but putting there would require
another overload that synthesizes the empty key types we use here. even
then a separate function is slightly nicer because it spares us writing
things like `asyncCollect(someIterableOfPromises).collect()` or similar
Change-Id: Ia92abc105016414a2171e237f2a0bc6233d3ccbf
more precisely, split it into store preparation (which remains in the
constructor proper), db initialization, and prepared statements init.
this will let us more easily turn the dbState into a connection pool.
Change-Id: I894acd4553bc83a2d86229922b757c573e394cac
this is one of the cases retrySQLite is supposed to handle. with busy
timeouts set at the connection level we may instead wait for up to an
hour to acquire locks before actually falling back to the retrySQLite
loop, blocking an entire thread in the process. this isn't painful in
the current system that uses dedicated threads for everything, but an
async executor actually suffers. since we use sqlite in WAL mode, and
WAL mode still allows reads to happen concurrently with writes, we'll
want to not block an executor on sqlite write locks. (note that while
we do have a mutex around db access that mutex is only held inside of
retrySQLite callbacks, so it will be released where we'd block today)
do note that we don't disable the timeout completely since that could
drastically reduce write performance. multiple daemon processes using
the same database file will naturally conflict, but each write is not
usually that expensive. going to sleep immediately instead of waiting
a bit can greatly impact throughput. waiting for 50ms should be fine.
Change-Id: I2d8e36ed7a0183bbc213490ebde2c79fc6e2f4b2
this is like a condition variable associated with the mutex. it's all
we'll need for the async transition, so we don't add a separate type.
Change-Id: Id9aefadd3b50e5f14f7b4d6bad41721f5249ce59