@trainstar/synchro-react-native 0.4.0-rc.2 → 0.4.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/SynchroReactNative.podspec +1 -0
- package/android/build.gradle +1 -1
- package/android/src/androidTest/kotlin/com/trainstar/synchro/rn/SynchroModuleTransactionTest.kt +7 -10
- package/ios/SynchroModule.swift +277 -273
- package/ios-tests/SynchroModuleTransactionTests.swift +264 -0
- package/lib/module/NativeSynchro.js.map +1 -1
- package/lib/typescript/src/NativeSynchro.d.ts +13 -14
- package/lib/typescript/src/NativeSynchro.d.ts.map +1 -1
- package/package.json +9 -8
- package/src/NativeSynchro.ts +13 -17
package/ios/SynchroModule.swift
CHANGED
|
@@ -179,6 +179,7 @@ enum TransactionOp {
|
|
|
179
179
|
private struct TransactionTimeoutError: Error {}
|
|
180
180
|
private struct TransactionRollbackError: Error {}
|
|
181
181
|
private struct DatabaseAlreadyExistsError: Error {}
|
|
182
|
+
private struct InvalidAuthoredWriteOperationError: Error {}
|
|
182
183
|
private struct TransactionAbortedError: LocalizedError {
|
|
183
184
|
let message: String
|
|
184
185
|
|
|
@@ -219,6 +220,7 @@ public class SynchroModuleImpl: NSObject {
|
|
|
219
220
|
|
|
220
221
|
private(set) var client: SynchroClient?
|
|
221
222
|
private let lifecycleMutex = LifecycleMutex()
|
|
223
|
+
private let databaseBridgeQueue = DispatchQueue(label: "com.trainstar.synchro.react-native.database")
|
|
222
224
|
var sessions: [String: TransactionSession] = [:]
|
|
223
225
|
let sessionsLock = NSLock()
|
|
224
226
|
private var acceptingTransactions = false
|
|
@@ -253,6 +255,8 @@ public class SynchroModuleImpl: NSObject {
|
|
|
253
255
|
reject("TRANSACTION_TIMEOUT", "Transaction timed out due to inactivity", nil)
|
|
254
256
|
} else if error is TransactionAbortedError {
|
|
255
257
|
reject("NOT_CONNECTED", "Client closed during transaction", error)
|
|
258
|
+
} else if error is InvalidAuthoredWriteOperationError {
|
|
259
|
+
reject("INVALID_CONFIG", "Invalid authored write operation", nil)
|
|
256
260
|
} else {
|
|
257
261
|
reject("UNKNOWN", error.localizedDescription, error)
|
|
258
262
|
}
|
|
@@ -487,16 +491,13 @@ public class SynchroModuleImpl: NSObject {
|
|
|
487
491
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
488
492
|
reject: @escaping RCTPromiseRejectBlock
|
|
489
493
|
) {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
} catch {
|
|
498
|
-
rejectWithError(reject, error)
|
|
499
|
-
}
|
|
494
|
+
submitDatabaseOperation(
|
|
495
|
+
resolve: resolve,
|
|
496
|
+
reject: reject,
|
|
497
|
+
operation: { client in
|
|
498
|
+
try self.rowsToBridgeRows(client.query(sql, params: try self.bridgeParams(params)))
|
|
499
|
+
}
|
|
500
|
+
)
|
|
500
501
|
}
|
|
501
502
|
|
|
502
503
|
@objc
|
|
@@ -506,20 +507,16 @@ public class SynchroModuleImpl: NSObject {
|
|
|
506
507
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
507
508
|
reject: @escaping RCTPromiseRejectBlock
|
|
508
509
|
) {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
} else {
|
|
518
|
-
resolve(NSNull())
|
|
510
|
+
submitDatabaseOperation(
|
|
511
|
+
resolve: resolve,
|
|
512
|
+
reject: reject,
|
|
513
|
+
operation: { client -> Any? in
|
|
514
|
+
if let row = try client.queryOne(sql, params: try self.bridgeParams(params)) {
|
|
515
|
+
return self.rowToBridgeRow(row)
|
|
516
|
+
}
|
|
517
|
+
return NSNull()
|
|
519
518
|
}
|
|
520
|
-
|
|
521
|
-
rejectWithError(reject, error)
|
|
522
|
-
}
|
|
519
|
+
)
|
|
523
520
|
}
|
|
524
521
|
|
|
525
522
|
@objc
|
|
@@ -529,16 +526,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
529
526
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
530
527
|
reject: @escaping RCTPromiseRejectBlock
|
|
531
528
|
) {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
rejectWithError(reject, error)
|
|
541
|
-
}
|
|
529
|
+
submitDatabaseOperation(
|
|
530
|
+
resolve: resolve,
|
|
531
|
+
reject: reject,
|
|
532
|
+
operation: { client in
|
|
533
|
+
let result = try client.execute(sql, params: try self.bridgeParams(params))
|
|
534
|
+
return ["rowsAffected": result.rowsAffected]
|
|
535
|
+
}
|
|
536
|
+
)
|
|
542
537
|
}
|
|
543
538
|
|
|
544
539
|
@objc
|
|
@@ -551,27 +546,24 @@ public class SynchroModuleImpl: NSObject {
|
|
|
551
546
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
552
547
|
reject: @escaping RCTPromiseRejectBlock
|
|
553
548
|
) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
549
|
+
submitDatabaseOperation(
|
|
550
|
+
resolve: resolve,
|
|
551
|
+
reject: reject,
|
|
552
|
+
operation: { client in
|
|
553
|
+
guard let authoredOperation = Synchro.Operation(rawValue: operation) else {
|
|
554
|
+
throw InvalidAuthoredWriteOperationError()
|
|
555
|
+
}
|
|
556
|
+
let params = try self.bridgeParams(values)
|
|
557
|
+
let result = try client.authoredWriteTransaction(
|
|
558
|
+
tableName: tableName,
|
|
559
|
+
operation: authoredOperation,
|
|
560
|
+
columnNames: columnNames
|
|
561
|
+
) { transaction in
|
|
562
|
+
try transaction.execute(sql, params: params)
|
|
563
|
+
}
|
|
564
|
+
return ["rowsAffected": result.rowsAffected]
|
|
570
565
|
}
|
|
571
|
-
|
|
572
|
-
} catch {
|
|
573
|
-
rejectWithError(reject, error)
|
|
574
|
-
}
|
|
566
|
+
)
|
|
575
567
|
}
|
|
576
568
|
|
|
577
569
|
@objc
|
|
@@ -580,16 +572,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
580
572
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
581
573
|
reject: @escaping RCTPromiseRejectBlock
|
|
582
574
|
) {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
rejectWithError(reject, error)
|
|
592
|
-
}
|
|
575
|
+
submitDatabaseOperation(
|
|
576
|
+
resolve: resolve,
|
|
577
|
+
reject: reject,
|
|
578
|
+
operation: { client in
|
|
579
|
+
let total = try client.executeBatch(try self.bridgeStatements(statements))
|
|
580
|
+
return ["totalRowsAffected": total]
|
|
581
|
+
}
|
|
582
|
+
)
|
|
593
583
|
}
|
|
594
584
|
|
|
595
585
|
// MARK: - Transactions
|
|
@@ -917,20 +907,17 @@ public class SynchroModuleImpl: NSObject {
|
|
|
917
907
|
}
|
|
918
908
|
|
|
919
909
|
private func wireClientEvents(_ client: SynchroClient) {
|
|
920
|
-
statusSubscription?.cancel()
|
|
921
|
-
syncEventSubscription?.cancel()
|
|
922
|
-
conflictSubscription?.cancel()
|
|
923
910
|
statusDetailsLock.lock()
|
|
924
911
|
cachedBackoff = nil
|
|
925
912
|
cachedFailure = nil
|
|
926
913
|
statusDetailsLock.unlock()
|
|
927
914
|
|
|
928
|
-
statusSubscription = client.onStatusChange { [weak self] status in
|
|
915
|
+
let statusSubscription = client.onStatusChange { [weak self] status in
|
|
929
916
|
guard status != .backoff, status != .error else { return }
|
|
930
|
-
self?.emit("onStatusChange", self?.statusPayload(status) ?? [:])
|
|
917
|
+
self?.emit("onStatusChange", self?.statusPayload(status, client: client) ?? [:])
|
|
931
918
|
}
|
|
932
919
|
|
|
933
|
-
syncEventSubscription = client.onSyncEvent { [weak self] event in
|
|
920
|
+
let syncEventSubscription = client.onSyncEvent { [weak self] event in
|
|
934
921
|
guard let self else { return }
|
|
935
922
|
self.recordStatusDetails(event)
|
|
936
923
|
self.emit("onSyncEvent", self.syncEventPayload(event))
|
|
@@ -938,16 +925,22 @@ public class SynchroModuleImpl: NSObject {
|
|
|
938
925
|
case .backoff, .failure:
|
|
939
926
|
self.emit(
|
|
940
927
|
"onStatusChange",
|
|
941
|
-
self.statusPayload(client.getSyncStatus())
|
|
928
|
+
self.statusPayload(client.getSyncStatus(), client: client)
|
|
942
929
|
)
|
|
943
930
|
default:
|
|
944
931
|
break
|
|
945
932
|
}
|
|
946
933
|
}
|
|
947
934
|
|
|
948
|
-
conflictSubscription = client.onConflict { [weak self] event in
|
|
935
|
+
let conflictSubscription = client.onConflict { [weak self] event in
|
|
949
936
|
self?.emit("onConflict", self?.conflictPayload(event) ?? [:])
|
|
950
937
|
}
|
|
938
|
+
|
|
939
|
+
sessionsLock.lock()
|
|
940
|
+
self.statusSubscription = statusSubscription
|
|
941
|
+
self.syncEventSubscription = syncEventSubscription
|
|
942
|
+
self.conflictSubscription = conflictSubscription
|
|
943
|
+
sessionsLock.unlock()
|
|
951
944
|
}
|
|
952
945
|
|
|
953
946
|
private func setClient(_ client: SynchroClient?, acceptingTransactions: Bool) {
|
|
@@ -968,13 +961,30 @@ public class SynchroModuleImpl: NSObject {
|
|
|
968
961
|
}
|
|
969
962
|
}
|
|
970
963
|
|
|
964
|
+
private func submitDatabaseOperation(
|
|
965
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
966
|
+
reject: @escaping RCTPromiseRejectBlock,
|
|
967
|
+
operation: @escaping (SynchroClient) throws -> Any?
|
|
968
|
+
) {
|
|
969
|
+
sessionsLock.lock()
|
|
970
|
+
guard acceptingTransactions, let client else {
|
|
971
|
+
sessionsLock.unlock()
|
|
972
|
+
reject("NOT_CONNECTED", "Client not initialized", nil)
|
|
973
|
+
return
|
|
974
|
+
}
|
|
975
|
+
databaseBridgeQueue.async {
|
|
976
|
+
let result = Result { try operation(client) }
|
|
977
|
+
switch result {
|
|
978
|
+
case .success(let value):
|
|
979
|
+
resolve(value)
|
|
980
|
+
case .failure(let error):
|
|
981
|
+
self.rejectWithError(reject, error)
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
sessionsLock.unlock()
|
|
985
|
+
}
|
|
986
|
+
|
|
971
987
|
private func detachRuntimeState() -> [TransactionSession] {
|
|
972
|
-
statusSubscription?.cancel()
|
|
973
|
-
syncEventSubscription?.cancel()
|
|
974
|
-
conflictSubscription?.cancel()
|
|
975
|
-
statusSubscription = nil
|
|
976
|
-
syncEventSubscription = nil
|
|
977
|
-
conflictSubscription = nil
|
|
978
988
|
transportObservations?.cancelPauseBarrier()
|
|
979
989
|
transportObservations = nil
|
|
980
990
|
statusDetailsLock.lock()
|
|
@@ -982,14 +992,25 @@ public class SynchroModuleImpl: NSObject {
|
|
|
982
992
|
cachedFailure = nil
|
|
983
993
|
statusDetailsLock.unlock()
|
|
984
994
|
|
|
985
|
-
observers.values.forEach { $0.cancel() }
|
|
986
|
-
observers.removeAll()
|
|
987
|
-
|
|
988
995
|
sessionsLock.lock()
|
|
989
996
|
acceptingTransactions = false
|
|
990
997
|
let activeSessions = Array(sessions.values)
|
|
991
998
|
sessions.removeAll()
|
|
999
|
+
let activeObservers = Array(observers.values)
|
|
1000
|
+
observers.removeAll()
|
|
1001
|
+
let activeSubscriptions = (
|
|
1002
|
+
statusSubscription,
|
|
1003
|
+
syncEventSubscription,
|
|
1004
|
+
conflictSubscription
|
|
1005
|
+
)
|
|
1006
|
+
statusSubscription = nil
|
|
1007
|
+
syncEventSubscription = nil
|
|
1008
|
+
conflictSubscription = nil
|
|
992
1009
|
sessionsLock.unlock()
|
|
1010
|
+
activeObservers.forEach { $0.cancel() }
|
|
1011
|
+
activeSubscriptions.0?.cancel()
|
|
1012
|
+
activeSubscriptions.1?.cancel()
|
|
1013
|
+
activeSubscriptions.2?.cancel()
|
|
993
1014
|
|
|
994
1015
|
authLock.lock()
|
|
995
1016
|
let authContinuations = pendingAuthContinuations
|
|
@@ -1013,9 +1034,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1013
1034
|
for session in activeSessions {
|
|
1014
1035
|
await session.waitUntilFinished()
|
|
1015
1036
|
}
|
|
1037
|
+
await withCheckedContinuation { continuation in
|
|
1038
|
+
databaseBridgeQueue.async {
|
|
1039
|
+
continuation.resume()
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1016
1042
|
}
|
|
1017
1043
|
|
|
1018
|
-
private func statusPayload(_ status: SyncStatus) -> [String: Any] {
|
|
1044
|
+
private func statusPayload(_ status: SyncStatus, client: SynchroClient) -> [String: Any] {
|
|
1019
1045
|
var payload: [String: Any] = [
|
|
1020
1046
|
"status": status.rawValue,
|
|
1021
1047
|
"retryAt": NSNull(),
|
|
@@ -1038,11 +1064,7 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1038
1064
|
let cachedFailure = self.cachedFailure
|
|
1039
1065
|
statusDetailsLock.unlock()
|
|
1040
1066
|
let persistedFailure: SyncFailure?
|
|
1041
|
-
|
|
1042
|
-
persistedFailure = try? client.getBlockingFailure()
|
|
1043
|
-
} else {
|
|
1044
|
-
persistedFailure = nil
|
|
1045
|
-
}
|
|
1067
|
+
persistedFailure = try? client.getBlockingFailure()
|
|
1046
1068
|
if let failure = cachedFailure ?? persistedFailure {
|
|
1047
1069
|
payload["failure"] = failurePayload(failure)
|
|
1048
1070
|
}
|
|
@@ -1234,18 +1256,16 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1234
1256
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1235
1257
|
reject: @escaping RCTPromiseRejectBlock
|
|
1236
1258
|
) {
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
rejectWithError(reject, error)
|
|
1248
|
-
}
|
|
1259
|
+
submitDatabaseOperation(
|
|
1260
|
+
resolve: resolve,
|
|
1261
|
+
reject: reject,
|
|
1262
|
+
operation: { client in
|
|
1263
|
+
let columns = try self.parseColumns(columnsJson)
|
|
1264
|
+
let options = try optionsJson.flatMap { try self.parseTableOptions($0) }
|
|
1265
|
+
try client.createTable(name, columns: columns, options: options)
|
|
1266
|
+
return nil
|
|
1267
|
+
}
|
|
1268
|
+
)
|
|
1249
1269
|
}
|
|
1250
1270
|
|
|
1251
1271
|
@objc
|
|
@@ -1255,17 +1275,15 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1255
1275
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1256
1276
|
reject: @escaping RCTPromiseRejectBlock
|
|
1257
1277
|
) {
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
rejectWithError(reject, error)
|
|
1268
|
-
}
|
|
1278
|
+
submitDatabaseOperation(
|
|
1279
|
+
resolve: resolve,
|
|
1280
|
+
reject: reject,
|
|
1281
|
+
operation: { client in
|
|
1282
|
+
let columns = try self.parseColumns(columnsJson)
|
|
1283
|
+
try client.alterTable(name, addColumns: columns)
|
|
1284
|
+
return nil
|
|
1285
|
+
}
|
|
1286
|
+
)
|
|
1269
1287
|
}
|
|
1270
1288
|
|
|
1271
1289
|
@objc
|
|
@@ -1276,16 +1294,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1276
1294
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1277
1295
|
reject: @escaping RCTPromiseRejectBlock
|
|
1278
1296
|
) {
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
rejectWithError(reject, error)
|
|
1288
|
-
}
|
|
1297
|
+
submitDatabaseOperation(
|
|
1298
|
+
resolve: resolve,
|
|
1299
|
+
reject: reject,
|
|
1300
|
+
operation: { client in
|
|
1301
|
+
try client.createIndex(table, columns: columns, unique: unique)
|
|
1302
|
+
return nil
|
|
1303
|
+
}
|
|
1304
|
+
)
|
|
1289
1305
|
}
|
|
1290
1306
|
|
|
1291
1307
|
// MARK: - Observation
|
|
@@ -1297,14 +1313,18 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1297
1313
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1298
1314
|
reject: @escaping RCTPromiseRejectBlock
|
|
1299
1315
|
) {
|
|
1300
|
-
|
|
1316
|
+
sessionsLock.lock()
|
|
1317
|
+
guard acceptingTransactions, let client else {
|
|
1318
|
+
sessionsLock.unlock()
|
|
1301
1319
|
reject("NOT_CONNECTED", "Client not initialized", nil)
|
|
1302
1320
|
return
|
|
1303
1321
|
}
|
|
1304
1322
|
let cancellable = client.onChange(tables: tables) { [weak self] in
|
|
1305
1323
|
self?.emit("onChange", ["observerID": observerID])
|
|
1306
1324
|
}
|
|
1307
|
-
|
|
1325
|
+
let previous = observers.updateValue(cancellable, forKey: observerID)
|
|
1326
|
+
sessionsLock.unlock()
|
|
1327
|
+
previous?.cancel()
|
|
1308
1328
|
resolve(nil)
|
|
1309
1329
|
}
|
|
1310
1330
|
|
|
@@ -1317,7 +1337,9 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1317
1337
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1318
1338
|
reject: @escaping RCTPromiseRejectBlock
|
|
1319
1339
|
) {
|
|
1320
|
-
|
|
1340
|
+
sessionsLock.lock()
|
|
1341
|
+
guard acceptingTransactions, let client else {
|
|
1342
|
+
sessionsLock.unlock()
|
|
1321
1343
|
reject("NOT_CONNECTED", "Client not initialized", nil)
|
|
1322
1344
|
return
|
|
1323
1345
|
}
|
|
@@ -1328,9 +1350,12 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1328
1350
|
self?.emit("onQueryResult", ["observerID": observerID, "rows": payload])
|
|
1329
1351
|
}
|
|
1330
1352
|
}
|
|
1331
|
-
|
|
1353
|
+
let previous = observers.updateValue(cancellable, forKey: observerID)
|
|
1354
|
+
sessionsLock.unlock()
|
|
1355
|
+
previous?.cancel()
|
|
1332
1356
|
resolve(nil)
|
|
1333
1357
|
} catch {
|
|
1358
|
+
sessionsLock.unlock()
|
|
1334
1359
|
rejectWithError(reject, error)
|
|
1335
1360
|
}
|
|
1336
1361
|
}
|
|
@@ -1341,9 +1366,10 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1341
1366
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1342
1367
|
reject: @escaping RCTPromiseRejectBlock
|
|
1343
1368
|
) {
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1369
|
+
sessionsLock.lock()
|
|
1370
|
+
let cancellable = observers.removeValue(forKey: observerID)
|
|
1371
|
+
sessionsLock.unlock()
|
|
1372
|
+
cancellable?.cancel()
|
|
1347
1373
|
resolve(nil)
|
|
1348
1374
|
}
|
|
1349
1375
|
|
|
@@ -1501,15 +1527,11 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1501
1527
|
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1502
1528
|
reject: @escaping RCTPromiseRejectBlock
|
|
1503
1529
|
) {
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
resolve(try client.pendingChangeCount())
|
|
1510
|
-
} catch {
|
|
1511
|
-
rejectWithError(reject, error)
|
|
1512
|
-
}
|
|
1530
|
+
submitDatabaseOperation(
|
|
1531
|
+
resolve: resolve,
|
|
1532
|
+
reject: reject,
|
|
1533
|
+
operation: { client in try client.pendingChangeCount() }
|
|
1534
|
+
)
|
|
1513
1535
|
}
|
|
1514
1536
|
|
|
1515
1537
|
@objc
|
|
@@ -1517,15 +1539,13 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1517
1539
|
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1518
1540
|
reject: @escaping RCTPromiseRejectBlock
|
|
1519
1541
|
) {
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
rejectWithError(reject, error)
|
|
1528
|
-
}
|
|
1542
|
+
submitDatabaseOperation(
|
|
1543
|
+
resolve: resolve,
|
|
1544
|
+
reject: reject,
|
|
1545
|
+
operation: { client in
|
|
1546
|
+
try self.encodeBridgeJSON(self.statusPayload(client.getSyncStatus(), client: client))
|
|
1547
|
+
}
|
|
1548
|
+
)
|
|
1529
1549
|
}
|
|
1530
1550
|
|
|
1531
1551
|
@objc
|
|
@@ -1533,16 +1553,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1533
1553
|
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1534
1554
|
reject: @escaping RCTPromiseRejectBlock
|
|
1535
1555
|
) {
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
rejectWithError(reject, error)
|
|
1545
|
-
}
|
|
1556
|
+
submitDatabaseOperation(
|
|
1557
|
+
resolve: resolve,
|
|
1558
|
+
reject: reject,
|
|
1559
|
+
operation: { client in
|
|
1560
|
+
let payload = try client.inspectPendingMutations().map(self.pendingMutationPayload)
|
|
1561
|
+
return try self.encodeBridgeJSON(payload)
|
|
1562
|
+
}
|
|
1563
|
+
)
|
|
1546
1564
|
}
|
|
1547
1565
|
|
|
1548
1566
|
@objc
|
|
@@ -1550,16 +1568,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1550
1568
|
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1551
1569
|
reject: @escaping RCTPromiseRejectBlock
|
|
1552
1570
|
) {
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
rejectWithError(reject, error)
|
|
1562
|
-
}
|
|
1571
|
+
submitDatabaseOperation(
|
|
1572
|
+
resolve: resolve,
|
|
1573
|
+
reject: reject,
|
|
1574
|
+
operation: { client in
|
|
1575
|
+
let payload = try client.inspectRetainedMutations().map(self.pendingMutationPayload)
|
|
1576
|
+
return try self.encodeBridgeJSON(payload)
|
|
1577
|
+
}
|
|
1578
|
+
)
|
|
1563
1579
|
}
|
|
1564
1580
|
|
|
1565
1581
|
@objc
|
|
@@ -1567,16 +1583,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1567
1583
|
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1568
1584
|
reject: @escaping RCTPromiseRejectBlock
|
|
1569
1585
|
) {
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
rejectWithError(reject, error)
|
|
1579
|
-
}
|
|
1586
|
+
submitDatabaseOperation(
|
|
1587
|
+
resolve: resolve,
|
|
1588
|
+
reject: reject,
|
|
1589
|
+
operation: { client in
|
|
1590
|
+
let payload = try client.inspectRetainedMutationRecords().map(self.retainedMutationPayload)
|
|
1591
|
+
return try self.encodeBridgeJSON(payload)
|
|
1592
|
+
}
|
|
1593
|
+
)
|
|
1580
1594
|
}
|
|
1581
1595
|
|
|
1582
1596
|
@objc
|
|
@@ -1584,16 +1598,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1584
1598
|
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1585
1599
|
reject: @escaping RCTPromiseRejectBlock
|
|
1586
1600
|
) {
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
rejectWithError(reject, error)
|
|
1596
|
-
}
|
|
1601
|
+
submitDatabaseOperation(
|
|
1602
|
+
resolve: resolve,
|
|
1603
|
+
reject: reject,
|
|
1604
|
+
operation: { client in
|
|
1605
|
+
let payload = try client.inspectRejectedMutations().map(self.rejectedMutationPayload)
|
|
1606
|
+
return try self.encodeBridgeJSON(payload)
|
|
1607
|
+
}
|
|
1608
|
+
)
|
|
1597
1609
|
}
|
|
1598
1610
|
|
|
1599
1611
|
@objc
|
|
@@ -1601,16 +1613,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1601
1613
|
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1602
1614
|
reject: @escaping RCTPromiseRejectBlock
|
|
1603
1615
|
) {
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
rejectWithError(reject, error)
|
|
1613
|
-
}
|
|
1616
|
+
submitDatabaseOperation(
|
|
1617
|
+
resolve: resolve,
|
|
1618
|
+
reject: reject,
|
|
1619
|
+
operation: { client in
|
|
1620
|
+
let payload = try client.inspectRejectedMutationRecords().map(self.retainedRejectionPayload)
|
|
1621
|
+
return try self.encodeBridgeJSON(payload)
|
|
1622
|
+
}
|
|
1623
|
+
)
|
|
1614
1624
|
}
|
|
1615
1625
|
|
|
1616
1626
|
/// Reads client state, retained details, and the requested application rows
|
|
@@ -1621,38 +1631,36 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1621
1631
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1622
1632
|
reject: @escaping RCTPromiseRejectBlock
|
|
1623
1633
|
) {
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
+
submitDatabaseOperation(
|
|
1635
|
+
resolve: resolve,
|
|
1636
|
+
reject: reject,
|
|
1637
|
+
operation: { client in
|
|
1638
|
+
let statements = try self.bridgeStatements(rowStatements)
|
|
1639
|
+
var rows: [Row] = []
|
|
1640
|
+
let snapshot = try SynchroInspection(client: client).captureSnapshot(maximumRecords: 512) { _, transaction in
|
|
1641
|
+
for statement in statements {
|
|
1642
|
+
rows += try transaction.query(statement.sql, params: statement.params)
|
|
1643
|
+
}
|
|
1634
1644
|
}
|
|
1645
|
+
let inspection: [String: Any] = [
|
|
1646
|
+
"client_state": self.clientStatePayload(snapshot.capture),
|
|
1647
|
+
"migration_journal": try snapshot.capture.migrationJournal.map {
|
|
1648
|
+
try JSONSerialization.jsonObject(with: JSONEncoder().encode($0))
|
|
1649
|
+
} ?? NSNull(),
|
|
1650
|
+
"migration_journal_truncated": snapshot.capture.migrationJournalTruncated,
|
|
1651
|
+
"physical_schema": try JSONSerialization.jsonObject(with: JSONEncoder().encode(snapshot.capture.physicalSchema)),
|
|
1652
|
+
"physical_schema_truncated": snapshot.capture.physicalSchemaTruncated,
|
|
1653
|
+
"accepted_mutation_outcomes": snapshot.capture.acceptedMutationOutcomes,
|
|
1654
|
+
"accepted_mutation_outcomes_truncated": snapshot.capture.acceptedMutationOutcomesTruncated,
|
|
1655
|
+
"retained_mutations": snapshot.retainedMutations.map { $0.map(self.retainedMutationPayload) } ?? NSNull(),
|
|
1656
|
+
"rejected_mutations": snapshot.rejectedMutations.map { $0.map(self.retainedRejectionPayload) } ?? NSNull(),
|
|
1657
|
+
]
|
|
1658
|
+
return [
|
|
1659
|
+
"inspection": try self.encodeBridgeJSON(inspection),
|
|
1660
|
+
"applicationRows": self.rowsToBridgeRows(rows),
|
|
1661
|
+
]
|
|
1635
1662
|
}
|
|
1636
|
-
|
|
1637
|
-
"client_state": clientStatePayload(snapshot.capture),
|
|
1638
|
-
"migration_journal": try snapshot.capture.migrationJournal.map {
|
|
1639
|
-
try JSONSerialization.jsonObject(with: JSONEncoder().encode($0))
|
|
1640
|
-
} ?? NSNull(),
|
|
1641
|
-
"migration_journal_truncated": snapshot.capture.migrationJournalTruncated,
|
|
1642
|
-
"physical_schema": try JSONSerialization.jsonObject(with: JSONEncoder().encode(snapshot.capture.physicalSchema)),
|
|
1643
|
-
"physical_schema_truncated": snapshot.capture.physicalSchemaTruncated,
|
|
1644
|
-
"accepted_mutation_outcomes": snapshot.capture.acceptedMutationOutcomes,
|
|
1645
|
-
"accepted_mutation_outcomes_truncated": snapshot.capture.acceptedMutationOutcomesTruncated,
|
|
1646
|
-
"retained_mutations": snapshot.retainedMutations.map { $0.map(retainedMutationPayload) } ?? NSNull(),
|
|
1647
|
-
"rejected_mutations": snapshot.rejectedMutations.map { $0.map(retainedRejectionPayload) } ?? NSNull(),
|
|
1648
|
-
]
|
|
1649
|
-
resolve([
|
|
1650
|
-
"inspection": try encodeBridgeJSON(inspection),
|
|
1651
|
-
"applicationRows": rowsToBridgeRows(rows),
|
|
1652
|
-
])
|
|
1653
|
-
} catch {
|
|
1654
|
-
rejectWithError(reject, error)
|
|
1655
|
-
}
|
|
1663
|
+
)
|
|
1656
1664
|
}
|
|
1657
1665
|
|
|
1658
1666
|
/// Reads one record's row metadata and every rebuild receipt. The inspection snapshot bounds
|
|
@@ -1664,46 +1672,44 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1664
1672
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1665
1673
|
reject: @escaping RCTPromiseRejectBlock
|
|
1666
1674
|
) {
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1675
|
+
submitDatabaseOperation(
|
|
1676
|
+
resolve: resolve,
|
|
1677
|
+
reject: reject,
|
|
1678
|
+
operation: { client in
|
|
1679
|
+
let inspection = SynchroInspection(client: client)
|
|
1680
|
+
let metadata: Any = try inspection.rowMetadata(
|
|
1681
|
+
tableName: tableName,
|
|
1682
|
+
recordID: recordID
|
|
1683
|
+
).map { value in
|
|
1684
|
+
[
|
|
1685
|
+
"table_name": value.tableName,
|
|
1686
|
+
"record_id": value.recordID,
|
|
1687
|
+
"server_version": value.serverVersion,
|
|
1688
|
+
"row_checksum": value.rowChecksum ?? NSNull(),
|
|
1689
|
+
] as [String: Any]
|
|
1690
|
+
} ?? NSNull()
|
|
1691
|
+
let receipts = try inspection.rebuildReceipts().map { value in
|
|
1692
|
+
[
|
|
1693
|
+
"rebuild_id_fingerprint": value.rebuildIDFingerprint,
|
|
1694
|
+
"page_count": value.pageCount,
|
|
1695
|
+
"returned_record_count": value.returnedRecordCount,
|
|
1696
|
+
"request_chain_expected": value.requestChainExpected,
|
|
1697
|
+
"request_chain_observed": value.requestChainObserved,
|
|
1698
|
+
"record_identities_hex": value.recordIdentitiesHex,
|
|
1699
|
+
"received_row_checksums": value.receivedRowChecksums,
|
|
1700
|
+
"computed_row_checksums": value.computedRowChecksums,
|
|
1701
|
+
"computed_scope_checksum": value.computedScopeChecksum ?? NSNull(),
|
|
1702
|
+
"final_scope_checksum": value.finalScopeChecksum ?? NSNull(),
|
|
1703
|
+
"stored_scope_checksum": value.storedScopeChecksum ?? NSNull(),
|
|
1704
|
+
"local_scope_checksum": value.localScopeChecksum ?? NSNull(),
|
|
1705
|
+
] as [String: Any]
|
|
1706
|
+
}
|
|
1707
|
+
return try self.encodeBridgeJSON([
|
|
1708
|
+
"row_metadata": metadata,
|
|
1709
|
+
"rebuild_receipts": receipts,
|
|
1710
|
+
])
|
|
1699
1711
|
}
|
|
1700
|
-
|
|
1701
|
-
"row_metadata": metadata,
|
|
1702
|
-
"rebuild_receipts": receipts,
|
|
1703
|
-
]))
|
|
1704
|
-
} catch {
|
|
1705
|
-
rejectWithError(reject, error)
|
|
1706
|
-
}
|
|
1712
|
+
)
|
|
1707
1713
|
}
|
|
1708
1714
|
|
|
1709
1715
|
@objc
|
|
@@ -1808,16 +1814,14 @@ public class SynchroModuleImpl: NSObject {
|
|
|
1808
1814
|
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
1809
1815
|
reject: @escaping RCTPromiseRejectBlock
|
|
1810
1816
|
) {
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
rejectWithError(reject, error)
|
|
1820
|
-
}
|
|
1817
|
+
submitDatabaseOperation(
|
|
1818
|
+
resolve: resolve,
|
|
1819
|
+
reject: reject,
|
|
1820
|
+
operation: { client in
|
|
1821
|
+
try client.clearRejectedMutations()
|
|
1822
|
+
return nil
|
|
1823
|
+
}
|
|
1824
|
+
)
|
|
1821
1825
|
}
|
|
1822
1826
|
|
|
1823
1827
|
// MARK: - Helpers
|