Skip to content

Conversation

stevensJourney
Copy link
Contributor

Overview

This adds additional helpers to the PowerSyncKotlin module for implementing custom SQLite Drivers in the Swift SDK.

Related to powersync-ja/powersync-swift#78

The main addition in this PR is a SwiftSQLiteConnectionPool implementation which can be used to bridge a Swift connection pool to the format expected by our Kotlin SDK.

Connection Pooling

For GRDB in particular: we can create a GRDB DatabasePool which can be mapped to a Kotlin SQLiteConnectionPool. GRDB provides a pointer to the raw SQLite connection when obtaining a lease to a pooled connection. We can use this pointer on the Kotlin side with the existing Database connection implementation.

GRDB only allows synchronous closures to access connection leases. The closure is executed in a managed dispatch queue. The SwiftSQLiteConnectionPool runs the Kotlin suspending callbacks in this synchronous environment by using a runBlocking call. This should be fine since we are only blocking the thread provided by the dispatch queue.

Table Updates

The Kotlin SQLiteConnectionPool requires a SharedFlow of Strings representing the tables changed. GRDB provides it's own update hooks which we can use to feed this flow. We can't generate a KotlinFlow easily on the Swift side - the SwiftSQLiteConnectionPool generates a mutable flow internally and exposes a public method to update to update this flow. The GRDB hooks trigger this method in order to convey updates.

  • TODO: Check tryEmit and backpressure

Static SQLite

GRDB relies on the system SQLite implementation by default. For our purposes, we require a custom compiled version which supports extension loading. The Kotlin SDK already compiles a static version of SQLite which we include in the Swift SDK. Including our PowerSync Swift SDK in a build currently overrides the SQLite implementation used by GRDB - providing support for extension loading. GRDB has some of its own requirements for SQLite. For its version of watched/observed queries it makes calls to sqlite3_snapshot_get. This API is only available if the SQLITE_ENABLE_SNAPSHOT compile setting is enabled. This compiler flag is now enabled in our build for compatibility.

  • TODO: Check other required compiler flags, if any

Copy link
Contributor

@simolus3 simolus3 left a comment

Choose a reason for hiding this comment

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

I'm very excited about GRDB support 🚀 Just leaving some early basic comments here.

}

fun loadExtension(
public fun loadExtension(
Copy link
Contributor

Choose a reason for hiding this comment

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

If the intention is to call this method from Swift, should it have a @Throws annotation?

}

@OptIn(ExperimentalPowerSyncAPI::class)
public open class SwiftSQLiteConnectionPool
Copy link
Contributor

Choose a reason for hiding this comment

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

Since it looks like we wouldn't extend this class from Swift, I don't think it would have to be open?

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