Skip to content

Support tracking update hooks #120

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

Merged
merged 4 commits into from
Aug 8, 2025
Merged

Support tracking update hooks #120

merged 4 commits into from
Aug 8, 2025

Conversation

simolus3
Copy link
Contributor

@simolus3 simolus3 commented Aug 8, 2025

This adds support for tracking update hooks in the core extension, making it easier for us to build SDKs ontop of libraries that may not support update hooks natively. Another benefit is that, since the hook is installed in Rust, there's not as much of an interop cost from C -> the Rust hook compared to other languages.

Update hooks are optional and registered by calling powersync_update_hook('install'). After that call, we track updated table names after a transaction completes into a set. Calling powersync_update_hook('get') will clear that set and return affected table names.

There's no way to unregister update hooks manually - instead, we rely on the xDestroy callback for powersync_update_hook to clear resources when the database is closing.

@simolus3 simolus3 requested a review from rkistner August 8, 2025 09:14
Copy link
Contributor

@rkistner rkistner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the current API, is there perhaps a possibility of losing changes when there is a db lock error or similar? Something like what happened in #97. Basically powersync_update_hook('get') -> clears committed updates -> some temporary SQLite error -> client doesn't get the results, but the queue is still cleared. In practice there all the relevant locks should already be held before clearing the queue, so I can't think of a way this would actually happen. But I was wondering if an actual temp table could be a better fit here?

I'm thinking an API like this:

select powersync_install_update_hooks();
...
delete from powersync_table_updates returning table_name;

In this case, if there is any error, the delete would also be rolled back. It would also allow the client to perform filtering on the updates, and could allow extending the info with other metadata (say operation counts).

@simolus3
Copy link
Contributor Author

simolus3 commented Aug 8, 2025

is there perhaps a possibility of losing changes when there is a db lock error or similar

I have considered the same thing, but if one just calls SELECT powersync_update_hook('get'), it doesn't seem like there's any potential for locks / a busy VFS since everything is in memory under our control?

But I was wondering if an actual temp table could be a better fit here?

What worries me is that the SQLite documentation for hooks is very clear on saying that we can't modify the database from the hook itself. So to me it sounds like inserting into a temp table from an update hook is a no-go. We could use a separate in-memory connection for that, but then we no longer benefit from transactions rolling back changes automatically.

@rkistner
Copy link
Contributor

rkistner commented Aug 8, 2025

What worries me is that the SQLite documentation for hooks is very clear on saying that we can't modify the database from the hook itself.

That's a good point, I forgot about that. A virtual table could still be an option, but at that point it's probably over-complicating things. Happy to go with the current approach.

@simolus3 simolus3 merged commit 466906d into main Aug 8, 2025
21 checks passed
@simolus3 simolus3 deleted the update-hooks branch August 8, 2025 11:37
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

Successfully merging this pull request may close these issues.

2 participants