digital-fabric / extralite

Ruby on SQLite
http://www.rubydoc.info/gems/extralite
MIT License
247 stars 7 forks source link

Add progress handler callback #62

Closed noteflakes closed 5 months ago

noteflakes commented 5 months ago

SQLite API here: https://www.sqlite.org/c3ref/progress_handler.html

Normally, Extralite releases the GVL periodically while running queries, which is good for multi-threaded apps. However, this does not play well with multi-fibered apps where we want to be able to switch fibers while a query is running, and also to be able to cancel queries (on timeout or any other condition). So, a Polyphony-based app might want to do the following:

# The parameter is passed to SQLite as the number of SQLite VM instructions to 
# run between successive invocations of the block. In this case, we perform a
# snooze (fiber switch) every 10 VM instructions.
db.on_progress(10) { snooze }

Behaviour when an error is raised

If an error is raised from the progress handler, the query is interrupted and the error is propagated. This lets apps cancellation due timeouts or any other reason:

db.on_progress(10) { snooze }

# cancel query after 5 seconds
value = move_on_after(5) { db.query_single_value(long_running_query_sql) }

GVL changes

This also means that the GVL must be held, so we also need to make some changes to the code that handles that: