Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let package = Package(
targets: [
.binaryTarget(
name: packageName,
path: "./PowerSyncKotlin/build/XCFrameworks/debug/PowerSyncKotlin.xcframework"
path: "./PowerSyncKotlin/build/XCFrameworks/debug/\(packageName).xcframework"
)
,
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public actual class DatabaseDriverFactory(
@Suppress("unused")
private fun onTransactionCommit(success: Boolean) {
driver?.also { driver ->
if (success) {
driver.fireTableUpdates()
} else {
// Only clear updates if a rollback happened
// We manually fire updates when transactions are completed
if (!success) {
driver.clearTableUpdates()
}
}
Expand All @@ -42,38 +42,38 @@ public actual class DatabaseDriverFactory(
PsSqlDriver(
scope = scope,
driver =
AndroidSqliteDriver(
context = context,
schema = schema,
name = dbFilename,
factory =
RequerySQLiteOpenHelperFactory(
listOf(
RequerySQLiteOpenHelperFactory.ConfigurationOptions { config ->
config.customExtensions.add(
SQLiteCustomExtension(
"libpowersync",
"sqlite3_powersync_init",
),
)
config.customExtensions.add(
SQLiteCustomExtension(
"libpowersync-sqlite",
"powersync_init",
),
)
config
},
),
),
callback =
object : AndroidSqliteDriver.Callback(schema) {
override fun onConfigure(db: SupportSQLiteDatabase) {
db.enableWriteAheadLogging()
super.onConfigure(db)
}
AndroidSqliteDriver(
context = context,
schema = schema,
name = dbFilename,
factory =
RequerySQLiteOpenHelperFactory(
listOf(
RequerySQLiteOpenHelperFactory.ConfigurationOptions { config ->
config.customExtensions.add(
SQLiteCustomExtension(
"libpowersync",
"sqlite3_powersync_init",
),
)
config.customExtensions.add(
SQLiteCustomExtension(
"libpowersync-sqlite",
"powersync_init",
),
)
config
},
),
),
callback =
object : AndroidSqliteDriver.Callback(schema) {
override fun onConfigure(db: SupportSQLiteDatabase) {
db.enableWriteAheadLogging()
super.onConfigure(db)
}
},
),
)
setupSqliteBinding()
return this.driver as PsSqlDriver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlinx.serialization.encodeToString

Expand All @@ -33,6 +36,12 @@ internal class InternalDatabaseImpl(
override val transactor: PsDatabase = PsDatabase(driver)
override val queries: PowersyncQueries = transactor.powersyncQueries

// Register callback for table updates
private fun tableUpdates(): Flow<List<String>> = driver.tableUpdates()

// Debounced by transaction completion
private val tableUpdatesMutex = Mutex()

// Could be scope.coroutineContext, but the default is GlobalScope, which seems like a bad idea. To discuss.
private val dbContext = Dispatchers.IO
private val transaction =
Expand Down Expand Up @@ -62,30 +71,44 @@ internal class InternalDatabaseImpl(
}

companion object {
const val POWERSYNC_TABLE_MATCH: String = "(^ps_data__|^ps_data_local__)"
const val DEFAULT_WATCH_THROTTLE_MS: Long = 30L
const val POWERSYNC_TABLE_MATCH = "(^ps_data__|^ps_data_local__)"
const val DEFAULT_WATCH_THROTTLE_MS = 30L
}

init {
scope.launch {
val accumulatedUpdates = mutableSetOf<String>()
// Store table changes in an accumulated array which will be (debounced) emitted on transaction end
tableUpdates()
// Debounce will discard any events which occur inside the debounce window
// This will accumulate those table updates
.onEach { tables -> accumulatedUpdates.addAll(tables) }
.onEach { tables ->
val dataTables =
tables
.map { toFriendlyTableName(it) }
.filter { it.isNotBlank() }
tableUpdatesMutex.withLock {
accumulatedUpdates.addAll(dataTables)
}
}
// debounce ignores events inside the throttle. Debouncing needs to be done after accumulation
.debounce(DEFAULT_WATCH_THROTTLE_MS)
.collect {
val dataTables = accumulatedUpdates.map { toFriendlyTableName(it) }.filter { it.isNotBlank() }
driver.notifyListeners(queryKeys = dataTables.toTypedArray())
accumulatedUpdates.clear()
.collect { _ ->
tableUpdatesMutex.withLock {
driver.notifyListeners(queryKeys = accumulatedUpdates.toTypedArray())
accumulatedUpdates.clear()
}
}
}
}

override suspend fun execute(
sql: String,
parameters: List<Any?>?,
): Long = withContext(dbContext) { executeSync(sql, parameters) }
): Long =
withContext(dbContext) {
val r = executeSync(sql, parameters)
driver.fireTableUpdates()
r
}

private fun executeSync(
sql: String,
Expand Down Expand Up @@ -233,20 +256,21 @@ internal class InternalDatabaseImpl(

override suspend fun <R> writeTransaction(callback: ThrowableTransactionCallback<R>): R =
withContext(dbContext) {
transactor.transactionWithResult(noEnclosing = true) {
runWrapped {
val result = callback.execute(transaction)
if (result is PowerSyncException) {
throw result
val r =
transactor.transactionWithResult(noEnclosing = true) {
runWrapped {
val result = callback.execute(transaction)
if (result is PowerSyncException) {
throw result
}
result
}
result
}
}
// Trigger watched queries
driver.fireTableUpdates()
r
}

// Register callback for table updates
private fun tableUpdates(): Flow<List<String>> = driver.tableUpdates()

// Register callback for table updates on a specific table
override fun updatesOnTable(tableName: String): Flow<Unit> = driver.updatesOnTable(tableName)

Expand Down
49 changes: 25 additions & 24 deletions core/src/iosMain/kotlin/com/powersync/DatabaseDriverFactory.ios.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public actual class DatabaseDriverFactory {

private fun onTransactionCommit(success: Boolean) {
driver?.also { driver ->
if (success) {
driver.fireTableUpdates()
} else {
// Only clear updates on rollback
// We manually fire updates when a transaction ended
if (!success) {
driver.clearTableUpdates()
}
}
Expand All @@ -63,7 +63,8 @@ public actual class DatabaseDriverFactory {
override fun eWrite(
message: String,
exception: Throwable?,
) {}
) {
}

override fun trace(message: String) {}

Expand All @@ -74,27 +75,27 @@ public actual class DatabaseDriverFactory {
PsSqlDriver(
scope = scope,
driver =
NativeSqliteDriver(
configuration =
DatabaseConfiguration(
name = dbFilename,
version = schema.version.toInt(),
create = { connection -> wrapConnection(connection) { schema.create(it) } },
loggingConfig = Logging(logger = sqlLogger),
lifecycleConfig =
DatabaseConfiguration.Lifecycle(
onCreateConnection = { connection ->
setupSqliteBinding(connection)
wrapConnection(connection) { driver ->
schema.create(driver)
}
},
onCloseConnection = { connection ->
deregisterSqliteBinding(connection)
},
),
),
NativeSqliteDriver(
configuration =
DatabaseConfiguration(
name = dbFilename,
version = schema.version.toInt(),
create = { connection -> wrapConnection(connection) { schema.create(it) } },
loggingConfig = Logging(logger = sqlLogger),
lifecycleConfig =
DatabaseConfiguration.Lifecycle(
onCreateConnection = { connection ->
setupSqliteBinding(connection)
wrapConnection(connection) { driver ->
schema.create(driver)
}
},
onCloseConnection = { connection ->
deregisterSqliteBinding(connection)
},
),
),
),
)
return this.driver as PsSqlDriver
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public actual class DatabaseDriverFactory {
@Suppress("unused")
private fun onTransactionCommit(success: Boolean) {
driver?.also { driver ->
if (success) {
driver.fireTableUpdates()
} else {
// Only clear updates on rollback
// We manually fire updates when a transaction ended
if (!success) {
driver.clearTableUpdates()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@android:style/Theme.Material.Light.NoActionBar">

<activity
android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|mnc|colorMode|density|fontScale|fontWeightAdjustment|keyboard|layoutDirection|locale|mcc|navigation|smallestScreenSize|touchscreen|uiMode"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>
Loading