Skip to content

Commit ee9984a

Browse files
authored
Supabase error handling (#274)
1 parent 683cc69 commit ee9984a

File tree

21 files changed

+242
-89
lines changed

21 files changed

+242
-89
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
- Add `PowerSyncDatabase.inMemory` to create an in-memory SQLite database with PowerSync.
66
This may be useful for testing.
7+
- The Supabase connector can now be subclassed to customize how rows are uploaded and how errors are handled.
8+
- Experimental support for sync streams.
79

810
## 1.6.1
911

README.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,14 @@ and API documentation [here](https://powersync-ja.github.io/powersync-kotlin/).
2626

2727
- This is the Kotlin Multiplatform SDK implementation.
2828

29-
- [connectors](./connectors/)
30-
31-
- [SupabaseConnector.kt](./connectors/supabase/src/commonMain/kotlin/com/powersync/connector/supabase/SupabaseConnector.kt) An example connector implementation for Supabase (Postgres). The backend
32-
connector provides the connection between your application backend and the PowerSync managed database. It is used to:
33-
1. Retrieve a token to connect to the PowerSync service.
34-
2. Apply local changes on your backend application server (and from there, to your backend database).
35-
3629
- [integrations](./integrations/)
3730
- [room](./integrations/room/README.md): Allows using the [Room database library](https://developer.android.com/jetpack/androidx/releases/room) with PowerSync, making it easier to run typed queries on the database.
3831
- [sqldelight](./integrations/sqldelight/README.md): Allows using [SQLDelight](https://sqldelight.github.io/sqldelight)
3932
with PowerSync, also enabling typed statements on the database.
40-
33+
- [SupabaseConnector.kt](./integrations/supabase/src/commonMain/kotlin/com/powersync/connector/supabase/SupabaseConnector.kt) An example connector implementation for Supabase (Postgres). The backend
34+
connector provides the connection between your application backend and the PowerSync managed database. It is used to:
35+
1. Retrieve a token to connect to the PowerSync service.
36+
2. Apply local changes on your backend application server (and from there, to your backend database).
4137

4238
## Demo Apps / Example Projects
4339

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ tasks.getByName<Delete>("clean") {
6868
// Merges individual module docs into a single HTML output
6969
dependencies {
7070
dokka(project(":core:"))
71-
dokka(project(":connectors:supabase"))
7271
dokka(project(":compose:"))
7372
dokka(project(":integrations:room"))
7473
dokka(project(":integrations:sqldelight"))
74+
dokka(project(":integrations:supabase"))
7575
}
7676

7777
dokka {

core/src/commonIntegrationTest/kotlin/com/powersync/DatabaseTest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.powersync
22

3-
import androidx.sqlite.SQLiteConnection
4-
import androidx.sqlite.execSQL
53
import app.cash.turbine.test
64
import app.cash.turbine.turbineScope
75
import co.touchlab.kermit.ExperimentalKermitApi

core/src/commonIntegrationTest/kotlin/com/powersync/sync/SyncStreamTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,10 @@ class SyncStreamTest : AbstractSyncTest(true) {
163163
requestedSyncStreams.clear()
164164

165165
val subscription = database.syncStream("a").subscribe()
166+
waitForSyncLinesChannelClosed()
166167

167168
// Adding the subscription should reconnect
168-
turbine.waitFor { it.connected && !it.downloading }
169+
turbine.waitFor { it.connected }
169170
requestedSyncStreams shouldHaveSingleElement {
170171
val streams = it.jsonObject["streams"]!!.jsonObject
171172
val subscriptions = streams["subscriptions"]!!.jsonArray

core/src/commonIntegrationTest/kotlin/com/powersync/testutils/TestUtils.kt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ import io.ktor.client.HttpClient
2323
import io.ktor.client.engine.mock.toByteArray
2424
import io.ktor.http.ContentType
2525
import kotlinx.coroutines.channels.Channel
26+
import kotlinx.coroutines.suspendCancellableCoroutine
2627
import kotlinx.coroutines.test.TestScope
2728
import kotlinx.coroutines.test.runTest
2829
import kotlinx.io.files.Path
2930
import kotlinx.serialization.json.JsonElement
31+
import kotlin.coroutines.resume
3032

3133
expect val factory: DatabaseDriverFactory
3234

@@ -102,6 +104,23 @@ internal class ActiveDatabaseTest(
102104

103105
var connector = TestConnector()
104106

107+
suspend fun waitForSyncLinesChannelClosed() {
108+
suspendCancellableCoroutine { continuation ->
109+
var cancelled = false
110+
continuation.invokeOnCancellation {
111+
cancelled = true
112+
}
113+
114+
syncLines.invokeOnClose {
115+
if (!cancelled) {
116+
continuation.resume(Unit)
117+
}
118+
119+
syncLines = Channel()
120+
}
121+
}
122+
}
123+
105124
fun openDatabase(schema: Schema = Schema(UserRow.table)): PowerSyncDatabaseImpl {
106125
logger.d { "Opening database $databaseName in directory $testDirectory" }
107126
val db =
@@ -123,7 +142,7 @@ internal class ActiveDatabaseTest(
123142
fun createSyncClient(): HttpClient {
124143
val engine =
125144
MockSyncService(
126-
lines = syncLines,
145+
lines = { syncLines },
127146
generateCheckpoint = { checkpointResponse() },
128147
syncLinesContentType = { syncLinesContentType },
129148
trackSyncRequest = {

core/src/commonTest/kotlin/com/powersync/testutils/MockSyncService.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import kotlinx.serialization.json.JsonElement
3838
*/
3939
@OptIn(LegacySyncImplementation::class)
4040
internal class MockSyncService(
41-
private val lines: ReceiveChannel<Any>,
41+
private val lines: () -> ReceiveChannel<Any>,
4242
private val syncLinesContentType: () -> ContentType,
4343
private val generateCheckpoint: () -> WriteCheckpointResponse,
4444
private val trackSyncRequest: suspend (HttpRequestData) -> Unit,
@@ -60,12 +60,11 @@ internal class MockSyncService(
6060
trackSyncRequest(data)
6161
val job =
6262
scope.writer {
63-
lines.consume {
63+
lines().consume {
6464
while (true) {
6565
// Wait for a downstream listener being ready before requesting a sync line
6666
channel.awaitFreeSpace()
67-
val line = receive()
68-
when (line) {
67+
when (val line = receive()) {
6968
is SyncLine -> {
7069
val serializedLine = JsonUtil.json.encodeToString(line)
7170
channel.writeStringUtf8("$serializedLine\n")

demos/android-supabase-todolist/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ dependencies {
127127
// When adopting the PowerSync dependencies into your project, use the latest version available at
128128
// https://central.sonatype.com/artifact/com.powersync/core
129129
implementation(projects.core) // "com.powersync:core:latest.release"
130-
implementation(projects.connectors.supabase) // "com.powersync:connector-supabase:latest.release"
130+
implementation(projects.integrations.supabase) // "com.powersync:connector-supabase:latest.release"
131131
implementation(projects.compose) // "com.powersync:compose:latest.release"
132132
implementation(libs.uuid)
133133
implementation(libs.kermit)

demos/supabase-todolist/androidBackgroundSync/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ android {
4444
dependencies {
4545
// When copying this example, use the the current version available
4646
// at: https://central.sonatype.com/artifact/com.powersync/connector-supabase
47-
implementation(projects.connectors.supabase) // "com.powersync:connector-supabase"
47+
implementation(projects.integrations.supabase) // "com.powersync:connector-supabase"
4848

4949
implementation(projects.demos.supabaseTodolist.shared)
5050

demos/supabase-todolist/shared/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ kotlin {
4242
// When copying this example, use the current version available
4343
// at: https://central.sonatype.com/artifact/com.powersync/core
4444
api(projects.core) // "com.powersync:core"
45-
implementation(projects.connectors.supabase) // "com.powersync:connector-supabase"
45+
implementation(projects.integrations.supabase) // "com.powersync:connector-supabase"
4646
implementation(projects.compose) // "com.powersync:compose"
4747
implementation(libs.uuid)
4848
implementation(compose.runtime)

0 commit comments

Comments
 (0)