@@ -20,7 +20,6 @@ import com.powersync.sync.PriorityStatusEntry
20
20
import com.powersync.sync.SyncStatus
21
21
import com.powersync.sync.SyncStatusData
22
22
import com.powersync.sync.SyncStream
23
- import com.powersync.utils.ExclusiveMethodProvider
24
23
import com.powersync.utils.JsonParam
25
24
import com.powersync.utils.JsonUtil
26
25
import com.powersync.utils.throttle
@@ -35,6 +34,8 @@ import kotlinx.coroutines.flow.filter
35
34
import kotlinx.coroutines.flow.first
36
35
import kotlinx.coroutines.launch
37
36
import kotlinx.coroutines.runBlocking
37
+ import kotlinx.coroutines.sync.Mutex
38
+ import kotlinx.coroutines.sync.withLock
38
39
import kotlinx.datetime.Instant
39
40
import kotlinx.datetime.LocalDateTime
40
41
import kotlinx.datetime.TimeZone
@@ -57,8 +58,7 @@ internal class PowerSyncDatabaseImpl(
57
58
private val dbFilename : String ,
58
59
val logger : Logger = Logger ,
59
60
driver : PsSqlDriver = factory.createDriver(scope, dbFilename),
60
- ) : ExclusiveMethodProvider(),
61
- PowerSyncDatabase {
61
+ ) : PowerSyncDatabase {
62
62
companion object {
63
63
internal val streamConflictMessage =
64
64
"""
@@ -68,41 +68,33 @@ internal class PowerSyncDatabaseImpl(
68
68
This connection attempt will be queued and will only be executed after
69
69
currently connecting clients are disconnected.
70
70
""" .trimIndent()
71
-
72
- internal val multipleInstancesMessage =
73
- """
74
- Multiple PowerSync instances for the same database have been detected.
75
- This can cause unexpected results.
76
- Please check your PowerSync client instantiation logic if this is not intentional.
77
- """ .trimIndent()
78
-
79
- internal val instanceStore = ActiveInstanceStore ()
80
71
}
81
72
82
73
override val identifier = dbFilename
83
74
84
75
private val internalDb = InternalDatabaseImpl (driver, scope)
85
76
internal val bucketStorage: BucketStorage = BucketStorageImpl (internalDb, logger)
77
+ private val resource: ActiveDatabaseResource
78
+ private val clearResourceWhenDisposed: Any
79
+
86
80
var closed = false
87
81
88
82
/* *
89
83
* The current sync status.
90
84
*/
91
85
override val currentStatus: SyncStatus = SyncStatus ()
92
86
87
+ private val mutex = Mutex ()
93
88
private var syncStream: SyncStream ? = null
94
-
95
89
private var syncJob: Job ? = null
96
-
97
90
private var uploadJob: Job ? = null
98
91
99
92
init {
100
- val db = this
93
+ val res = ActiveDatabaseGroup .referenceDatabase(logger, identifier)
94
+ resource = res.first
95
+ clearResourceWhenDisposed = res.second
96
+
101
97
runBlocking {
102
- val isMultiple = instanceStore.registerAndCheckInstance(db)
103
- if (isMultiple) {
104
- logger.w { multipleInstancesMessage }
105
- }
106
98
val sqliteVersion = internalDb.queries.sqliteVersion().executeAsOne()
107
99
logger.d { " SQLiteVersion: $sqliteVersion " }
108
100
checkVersion()
@@ -126,10 +118,10 @@ internal class PowerSyncDatabaseImpl(
126
118
crudThrottleMs : Long ,
127
119
retryDelayMs : Long ,
128
120
params : Map <String , JsonParam ?>,
129
- ) = exclusiveMethod( " connect " ) {
130
- disconnect ()
121
+ ) = mutex.withLock {
122
+ disconnectInternal ()
131
123
132
- connect (
124
+ connectInternal (
133
125
SyncStream (
134
126
bucketStorage = bucketStorage,
135
127
connector = connector,
@@ -143,7 +135,7 @@ internal class PowerSyncDatabaseImpl(
143
135
}
144
136
145
137
@OptIn(FlowPreview ::class )
146
- internal fun connect (
138
+ internal fun connectInternal (
147
139
stream : SyncStream ,
148
140
crudThrottleMs : Long ,
149
141
) {
@@ -154,8 +146,7 @@ internal class PowerSyncDatabaseImpl(
154
146
syncJob =
155
147
scope.launch {
156
148
// Get a global lock for checking mutex maps
157
- val streamMutex =
158
- globalMutexFor(" streaming-$identifier " )
149
+ val streamMutex = resource.group.syncMutex
159
150
160
151
// Poke the streaming mutex to see if another client is using it
161
152
var obtainedLock = false
@@ -337,7 +328,9 @@ internal class PowerSyncDatabaseImpl(
337
328
}
338
329
}
339
330
340
- override suspend fun disconnect () {
331
+ override suspend fun disconnect () = mutex.withLock { disconnectInternal() }
332
+
333
+ private suspend fun disconnectInternal () {
341
334
if (syncJob != null && syncJob!! .isActive) {
342
335
syncJob?.cancelAndJoin()
343
336
}
@@ -431,13 +424,13 @@ internal class PowerSyncDatabaseImpl(
431
424
}
432
425
433
426
override suspend fun close () =
434
- exclusiveMethod( " close " ) {
427
+ mutex.withLock {
435
428
if (closed) {
436
- return @exclusiveMethod
429
+ return @withLock
437
430
}
438
- disconnect ()
431
+ disconnectInternal ()
439
432
internalDb.close()
440
- instanceStore.removeInstance( this )
433
+ resource.dispose( )
441
434
closed = true
442
435
}
443
436
0 commit comments