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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
# Changelog

## 1.8.0 (unreleased)
## 1.8.0

- Refactor SDK: `com.powersync:powersync-core` has an identical API, but now depends on
`com.powersync:powersync-common` where most logic is implemented.
- __POTENTIALLY BREAKING CHANGE__: If you were injecting a `DatabaseDriverFactory` into Koin or Dagger, note that the
`PowerSyncDatabase()` factory method now takes a more generic `PersistentConnectionFactory`.
- If you're using `PowerSyncDatabase.inMemory`, you explicitly have to import `com.powersync.inMemory` now.
- Update the PowerSync core extension to version 0.4.8.
- Add the `soft` flag to `disconnectAndClear()` which keeps an internal copy of synced data in the database, allowing
faster re-sync if a compatible token is used in the next `connect()` call.
- Add the `clear` parameter to `RawTable` to run a statement helping the core extension clear raw tables.

## 1.7.0

Expand Down
8 changes: 4 additions & 4 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ val downloadPowersyncDesktopBinaries by tasks.registering(Download::class) {
libs.versions.powersync.core
.get()
val linux_aarch64 =
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_aarch64.so"
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_aarch64.linux.so"
val linux_x64 =
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_x64.so"
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_x64.linux.so"
val macos_aarch64 =
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_aarch64.dylib"
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_aarch64.macos.dylib"
val macos_x64 =
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_x64.dylib"
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_x64.macos.dylib"
val windows_x64 =
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/powersync_x64.dll"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import com.powersync.db.ActiveDatabaseGroup
import com.powersync.db.crud.CrudEntry
import com.powersync.db.crud.CrudTransaction
import com.powersync.db.getString
import com.powersync.db.schema.PendingStatement
import com.powersync.db.schema.PendingStatementParameter
import com.powersync.db.schema.RawTable
import com.powersync.db.schema.Schema
import com.powersync.sync.LegacySyncImplementation
import com.powersync.test.getTempDir
import com.powersync.test.waitFor
import com.powersync.testutils.UserRow
Expand Down Expand Up @@ -548,4 +552,56 @@ class DatabaseTest {
job.cancelAndJoin()
hadOtherWrite.await()
}

@Test
fun testSoftClear() =
databaseTest {
database.execute("INSERT INTO users (id, name) VALUES (uuid(), ?)", listOf("testuser"))
database.execute("INSERT INTO ps_buckets (name, last_applied_op) VALUES (?, ?)", listOf("bkt", 10))

// Doing a soft-clear should delete data but keep the bucket around.
database.disconnectAndClear(soft = true)
database.getAll("SELECT name FROM ps_buckets") { it.getString("name") } shouldHaveSize 1

// Doing a default clear also deletes buckets
database.disconnectAndClear()
database.getAll("SELECT name FROM ps_buckets") { it.getString("name") } shouldHaveSize 0
}

@Test
@OptIn(ExperimentalPowerSyncAPI::class)
fun testRawTablesClear() =
databaseTest(createInitialDatabase = false) {
val db =
openDatabase(
Schema(
listOf(
RawTable(
name = "lists",
put =
PendingStatement(
"INSERT OR REPLACE INTO lists (id, name) VALUES (?, ?)",
listOf(
PendingStatementParameter.Id,
PendingStatementParameter.Column("name"),
),
),
delete =
PendingStatement(
"DELETE FROM lists WHERE id = ?",
listOf(PendingStatementParameter.Id),
),
clear = "DELETE FROM lists",
),
),
),
)

db.execute("CREATE TABLE lists (id TEXT NOT NULL PRIMARY KEY, name TEXT)")
db.execute("INSERT INTO lists (id, name) VALUES (uuid(), ?)", listOf("list"))

db.getAll("SELECT * FROM lists") { } shouldHaveSize 1
db.disconnectAndClear()
db.getAll("SELECT * FROM lists") { } shouldHaveSize 0
}
}
16 changes: 14 additions & 2 deletions common/src/commonMain/kotlin/com/powersync/PowerSyncDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,26 @@ public interface PowerSyncDatabase : Queries {

/**
* Disconnect and clear the database.
* Use this when logging out.
*
* Clearing the database is useful when a user logs out, to ensure another user logging in later would not see
* previous data.
*
* The database can still be queried after this is called, but the tables
* would be empty.
*
* To preserve data in local-only tables, set clearLocal to false.
*
* A "soft" clear deletes publicly visible tables, but keeps internal copies of data synced in the database. This
* usually means that if the same user logs out and back in again, the first sync is very fast because all internal
* data is still available. When a different user logs in, no old data would be visible at any point.
* Using soft deletes is recommended where it's not a security issue that old data could be reconstructible from the
* database.
*/
@Throws(PowerSyncException::class, CancellationException::class)
public suspend fun disconnectAndClear(clearLocal: Boolean = true)
public suspend fun disconnectAndClear(
clearLocal: Boolean = true,
soft: Boolean = false,
)

/**
* Close the database, releasing resources.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,22 @@ internal class PowerSyncDatabaseImpl(
}
}

override suspend fun disconnectAndClear(clearLocal: Boolean) {
override suspend fun disconnectAndClear(
clearLocal: Boolean,
soft: Boolean,
) {
disconnect()

var flags = 0
if (clearLocal) {
flags = flags or 1 // MASK_CLEAR_LOCAL
}
if (soft) {
flags = flags or 2 // MASK_SOFT_CLEAR
}

internalDb.writeTransaction { tx ->
tx.getOptional("SELECT powersync_clear(?)", listOf(if (clearLocal) "1" else "0")) {}
tx.getOptional("SELECT powersync_clear(?)", listOf(flags)) {}
}
currentStatus.update { copy(lastSyncedAt = null, hasSynced = false) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public class RawTable(
* The statement to run when the sync client wants to delete a row.
*/
public val delete: PendingStatement,
/**
* An optional statement to run when [com.powersync.PowerSyncDatabase.disconnectAndClear] is called on the database.
*/
public val clear: String? = null,
) : BaseTable {
override fun validate() {
// We don't currently have any validation for raw tables
Expand All @@ -42,6 +46,7 @@ public class RawTable(
put("name", name)
put("put", put.serialize())
put("delete", delete.serialize())
clear?.let { put("clear", it) }
}
}

Expand Down
4 changes: 2 additions & 2 deletions common/src/jvmMain/kotlin/com/powersync/ExtractLib.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ internal fun extractLib(fileName: String): String {
val os = System.getProperty("os.name").lowercase()
val (prefix, extension) =
when {
os.contains("nux") || os.contains("nix") || os.contains("aix") -> "lib" to "so"
os.contains("mac") -> "lib" to "dylib"
os.contains("nux") || os.contains("nix") || os.contains("aix") -> "lib" to "linux.so"
os.contains("mac") -> "lib" to "macos.dylib"
os.contains("win") -> "" to "dll"
else -> error("Unsupported OS: $os")
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ development=true
RELEASE_SIGNING_ENABLED=true
# Library config
GROUP=com.powersync
LIBRARY_VERSION=1.7.0
LIBRARY_VERSION=1.8.0
GITHUB_REPO=https://github.com/powersync-ja/powersync-kotlin.git
# POM
POM_URL=https://github.com/powersync-ja/powersync-kotlin/
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ serialization = "1.9.0"
kotlinx-io = "0.8.0"
ktor = "3.2.3"
uuid = "0.8.4"
powersync-core = "0.4.6"
powersync-core = "0.4.8"
turbine = "1.2.1"
kotest = "5.9.1" # we can't upgrade to 6.x because that requires Java 11 or above (we need Java 8 support)

Expand Down