Skip to content
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

chore: improve error handling for kotlin errors #20

Merged
merged 2 commits into from
Feb 11, 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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Changelog

## 1.0.0-Beta.5

* Implement improvements to errors originating in Kotlin so that they can be handled in Swift
* Improve `__fetchCredentials`to log the error but not cause an app crash on error


## 1.0.0-Beta.4

* Allow cursor to use column name to get value by including the following functions that accept a column name parameter:
`getBoolean`,`getBooleanOptional`,`getString`,`getStringOptional`, `getLong`,`getLongOptional`, `getDouble`,`getDoubleOptional`
* BREAKING CHANGE: This should not affect anyone but made `KotlinPowerSyncCredentials`, `KotlinPowerSyncDatabase` and `KotlinPowerSyncBackendConnector` private as these should never have been public.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/powersync-ja/powersync-kotlin.git",
"state" : {
"revision" : "7cd47ffc9dbec8fae4f9e067945ef2279015a90d",
"version" : "1.0.0-BETA20.0"
"revision" : "61d195816585f30260181dcbd157bf1660c9ac4e",
"version" : "1.0.0-BETA22.0"
}
},
{
Expand Down
6 changes: 3 additions & 3 deletions Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ class SupabaseConnector: PowerSyncBackendConnector {

override func fetchCredentials() async throws -> PowerSyncCredentials? {
session = try await client.auth.session

if (self.session == nil) {
throw AuthError.sessionMissing
}

let token = session!.accessToken

// userId is for debugging purposes only
return PowerSyncCredentials(endpoint: self.powerSyncEndpoint, token: token, userId: currentUserID)
}
Expand Down
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/powersync-ja/powersync-kotlin.git",
"state" : {
"revision" : "7cd47ffc9dbec8fae4f9e067945ef2279015a90d",
"version" : "1.0.0-BETA20.0"
"revision" : "61d195816585f30260181dcbd157bf1660c9ac4e",
"version" : "1.0.0-BETA22.0"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let package = Package(
targets: ["PowerSync"]),
],
dependencies: [
.package(url: "https://github.com/powersync-ja/powersync-kotlin.git", exact: "1.0.0-BETA20.0"),
.package(url: "https://github.com/powersync-ja/powersync-kotlin.git", exact: "1.0.0-BETA22.0"),
.package(url: "https://github.com/powersync-ja/powersync-sqlite-core-swift.git", "0.3.9"..<"0.4.0")
],
targets: [
Expand Down
4 changes: 2 additions & 2 deletions Sources/PowerSync/Kotlin/KotlinPowerSyncDatabaseImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
) -> AsyncStream<[RowType]> {
AsyncStream { continuation in
Task {
for await values in self.kotlinDatabase.watch(
for await values in try self.kotlinDatabase.watch(
sql: sql,
parameters: parameters,
mapper: mapper
Expand All @@ -172,7 +172,7 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
) -> AsyncStream<[RowType]> {
AsyncStream { continuation in
Task {
for await values in self.kotlinDatabase.watch(
for await values in try self.kotlinDatabase.watch(
sql: sql,
parameters: parameters,
mapper: { cursor in
Expand Down
40 changes: 20 additions & 20 deletions Sources/PowerSync/Kotlin/SqlCursor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,60 +8,60 @@ extension SqlCursor {
}
return columnIndex
}
private func getValue<T>(name: String, getter: (Int32) -> T?) throws -> T {

private func getValue<T>(name: String, getter: (Int32) throws -> T?) throws -> T {
let columnIndex = try getColumnIndex(name: name)
guard let value = getter(columnIndex) else {
guard let value = try getter(columnIndex) else {
throw SqlCursorError.nullValueFound(name)
}
return value
}
private func getOptionalValue<T>(name: String, getter: (String) -> T?) throws -> T? {

private func getOptionalValue<T>(name: String, getter: (String) throws -> T?) throws -> T? {
_ = try getColumnIndex(name: name)
return getter(name)
return try getter(name)
}

public func getBoolean(name: String) throws -> Bool {
try getValue(name: name) { getBoolean(index: $0)?.boolValue }
}

public func getDouble(name: String) throws -> Double {
try getValue(name: name) { getDouble(index: $0)?.doubleValue }
}

public func getLong(name: String) throws -> Int {
try getValue(name: name) { getLong(index: $0)?.intValue }
}

public func getString(name: String) throws -> String {
try getValue(name: name) { getString(index: $0) }
}

public func getBooleanOptional(name: String) throws -> Bool? {
try getOptionalValue(name: name) { getBooleanOptional(name: $0)?.boolValue }
try getOptionalValue(name: name) { try getBooleanOptional(name: $0)?.boolValue }
}

public func getDoubleOptional(name: String) throws -> Double? {
try getOptionalValue(name: name) { getDoubleOptional(name: $0)?.doubleValue }
try getOptionalValue(name: name) { try getDoubleOptional(name: $0)?.doubleValue }
}

public func getLongOptional(name: String) throws -> Int? {
try getOptionalValue(name: name) { getLongOptional(name: $0)?.intValue }
try getOptionalValue(name: name) { try getLongOptional(name: $0)?.intValue }
}

public func getStringOptional(name: String) throws -> String? {
try getOptionalValue(name: name) { PowerSyncKotlin.SqlCursorKt.getStringOptional(self, name: $0) }
try getOptionalValue(name: name) { try PowerSyncKotlin.SqlCursorKt.getStringOptional(self, name: $0) }
}
}

enum SqlCursorError: Error {
case nullValue(message: String)

static func columnNotFound(_ name: String) -> SqlCursorError {
.nullValue(message: "Column '\(name)' not found")
}

static func nullValueFound(_ name: String) -> SqlCursorError {
.nullValue(message: "Null value found for column \(name)")
}
Expand Down
24 changes: 22 additions & 2 deletions Sources/PowerSync/PowerSyncBackendConnectorAdapter.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import OSLog

class PowerSyncBackendConnectorAdapter: KotlinPowerSyncBackendConnector {
let swiftBackendConnector: PowerSyncBackendConnector

Expand All @@ -8,11 +10,29 @@ class PowerSyncBackendConnectorAdapter: KotlinPowerSyncBackendConnector {
}

override func __fetchCredentials() async throws -> KotlinPowerSyncCredentials? {
try await swiftBackendConnector.fetchCredentials()?.kotlinCredentials
do {
let result = try await swiftBackendConnector.fetchCredentials()
return result?.kotlinCredentials
} catch {
if #available(iOS 14.0, *) {
Logger().error("🔴 Failed to fetch credentials: \(error.localizedDescription)")
} else {
print("🔴 Failed to fetch credentials: \(error.localizedDescription)")
}
return nil
}
}

override func __uploadData(database: KotlinPowerSyncDatabase) async throws {
let swiftDatabase = KotlinPowerSyncDatabaseImpl(kotlinDatabase: database)
try await swiftBackendConnector.uploadData(database: swiftDatabase)
do {
return try await swiftBackendConnector.uploadData(database: swiftDatabase)
} catch {
if #available(iOS 14.0, *) {
Logger().error("🔴 Failed to upload data: \(error)")
} else {
print("🔴 Failed to upload data: \(error)")
}
}
}
}