Skip to content

Add option to use the Rust sync client #51

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
Jun 19, 2025
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
27 changes: 26 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Changelog

## 1.1.1 (unreleased)
## 1.2.0

* Improved `CrudBatch` and `CrudTransaction` `complete` function extensions. Developers no longer need to specify `nil` as an argument for `writeCheckpoint` when calling `CrudBatch.complete`. The base `complete` functions still accept an optional `writeCheckpoint` argument if developers use custom write checkpoints.
``` diff
Expand All @@ -12,6 +12,31 @@ guard let finalBatch = try await powersync.getCrudBatch(limit: 100) else {
```
* Fix reported progress around compactions / defrags on the sync service.
* Use version `0.4.0` of the PowerSync core extension, which improves sync performance.
* Add a new sync client implementation written in Rust instead of Kotlin. While this client is still
experimental, we intend to make it the default in the future. The main benefit of this client is
faster sync performance, but upcoming features will also require this client. We encourage
interested users to try it out by opting in to experimental APIs and passing options when
connecting:
```Swift
@_spi(PowerSyncExperimental) import PowerSync

try await db.connect(connector: connector, options: ConnectOptions(
newClientImplementation: true,
))
```
Switching between the clients can be done at any time without compatibility issues. If you run
into issues with the new client, please reach out to us!
* In addition to HTTP streams, the Swift SDK also supports fetching sync instructions from the
PowerSync service in a binary format. This requires the new sync client, and can then be enabled
on the sync options:
```Swift
@_spi(PowerSyncExperimental) import PowerSync

try await db.connect(connector: connector, options: ConnectOptions(
newClientImplementation: true,
connectionMethod: .webSocket,
))
```

## 1.1.0

Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ if let kotlinSdkPath = localKotlinSdkOverride {
// Not using a local build, so download from releases
conditionalTargets.append(.binaryTarget(
name: "PowerSyncKotlin",
url: "https://github.com/powersync-ja/powersync-kotlin/releases/download/v1.1.1/PowersyncKotlinRelease.zip",
checksum: "780437e25d41e46c2c1f555adcf330436f185d3663ef442da7141381d9c0495b"
url: "https://github.com/powersync-ja/powersync-kotlin/releases/download/v1.2.0/PowersyncKotlinRelease.zip",
checksum: "7454481a245b46b1b63a42419ec27f88f2fcb7fba9b763e3085cb49db59dfd58"
))
}

Expand Down
11 changes: 10 additions & 1 deletion Sources/PowerSync/Kotlin/KotlinPowerSyncDatabaseImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,21 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
)

let resolvedOptions = options ?? ConnectOptions()
let useWebsockets = switch (resolvedOptions.connectionMethod) {
case .http: false
case .webSocket: true
}

try await kotlinDatabase.connect(
connector: connectorAdapter,
crudThrottleMs: Int64(resolvedOptions.crudThrottle * 1000),
retryDelayMs: Int64(resolvedOptions.retryDelay * 1000),
params: resolvedOptions.params.mapValues { $0.toKotlinMap() }
params: resolvedOptions.params.mapValues { $0.toKotlinMap() },
options: createSyncOptions(
newClient: resolvedOptions.newClientImplementation,
webSocket: useWebsockets,
userAgent: "PowerSync Swift SDK"
)
)
}

Expand Down
38 changes: 38 additions & 0 deletions Sources/PowerSync/Protocol/PowerSyncDatabaseProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,22 @@ public struct ConnectOptions {
/// ]
/// ```
public var params: JsonParam

/// Uses a new sync client implemented in Rust instead of the one implemented in Kotlin.
///
/// The new client is more efficient and will become the default in the future, but is still marked as experimental for now.
/// We encourage interested users to try the new client.
@_spi(PowerSyncExperimental)
public var newClientImplementation: Bool

/// The connection method used to connect to the Powersync service.
///
/// The default method is ``ConnectionMethod/http``. Using ``ConnectionMethod/webSocket(_:)`` can
/// improve performance as a more efficient binary protocol is used. However, using the websocket connection method
/// requires enabling ``ConnectOptions/newClientImplementation``.
@_spi(PowerSyncExperimental)
public var connectionMethod: ConnectionMethod

/// Initializes a `ConnectOptions` instance with optional values.
///
/// - Parameters:
Expand All @@ -49,9 +64,32 @@ public struct ConnectOptions {
self.crudThrottle = crudThrottle
self.retryDelay = retryDelay
self.params = params
self.newClientImplementation = false
self.connectionMethod = .http
}

/// Initializes a ``ConnectOptions`` instance with optional values, including experimental options.
@_spi(PowerSyncExperimental)
public init(
crudThrottle: TimeInterval = 1,
retryDelay: TimeInterval = 5,
params: JsonParam = [:],
newClientImplementation: Bool = false,
connectionMethod: ConnectionMethod = .http
) {
self.crudThrottle = crudThrottle
self.retryDelay = retryDelay
self.params = params
self.newClientImplementation = newClientImplementation
self.connectionMethod = connectionMethod
}
}

@_spi(PowerSyncExperimental)
public enum ConnectionMethod {
case http
case webSocket
}

/// A PowerSync managed database.
///
Expand Down