Skip to content

Commit fc9c657

Browse files
authored
Merge pull request #1029 from supabase-community/remove-atomicfu
Remove atomicfu, migrate Atomic lists/maps, coroutine improvements
2 parents dca2d87 + 696cd63 commit fc9c657

File tree

25 files changed

+222
-242
lines changed

25 files changed

+222
-242
lines changed

Auth/src/commonMain/kotlin/io/github/jan/supabase/auth/Auth.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ import io.github.jan.supabase.plugins.CustomSerializationPlugin
2828
import io.github.jan.supabase.plugins.MainPlugin
2929
import io.github.jan.supabase.plugins.SupabasePluginProvider
3030
import io.ktor.client.plugins.HttpRequestTimeoutException
31+
import kotlinx.coroutines.currentCoroutineContext
3132
import kotlinx.coroutines.ensureActive
3233
import kotlinx.coroutines.flow.SharedFlow
3334
import kotlinx.coroutines.flow.StateFlow
3435
import kotlinx.serialization.json.JsonObject
35-
import kotlin.coroutines.coroutineContext
3636

3737
/**
3838
* Plugin to interact with the Supabase Auth API
@@ -479,7 +479,7 @@ val SupabaseClient.auth: Auth
479479
private suspend fun Auth.tryToGetUser(jwt: String) = try {
480480
retrieveUser(jwt)
481481
} catch (e: Exception) {
482-
coroutineContext.ensureActive()
482+
currentCoroutineContext().ensureActive()
483483
Auth.logger.e(e) { "Couldn't retrieve user using your custom jwt token. If you use the project secret ignore this message" }
484484
null
485485
}

Auth/src/commonMain/kotlin/io/github/jan/supabase/auth/AuthImpl.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import kotlinx.coroutines.CoroutineScope
4343
import kotlinx.coroutines.Job
4444
import kotlinx.coroutines.SupervisorJob
4545
import kotlinx.coroutines.cancel
46+
import kotlinx.coroutines.currentCoroutineContext
4647
import kotlinx.coroutines.delay
4748
import kotlinx.coroutines.ensureActive
4849
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -61,7 +62,6 @@ import kotlinx.serialization.json.encodeToJsonElement
6162
import kotlinx.serialization.json.jsonObject
6263
import kotlinx.serialization.json.jsonPrimitive
6364
import kotlinx.serialization.json.put
64-
import kotlin.coroutines.coroutineContext
6565
import kotlin.time.Clock
6666
import kotlin.time.Duration.Companion.seconds
6767

@@ -480,7 +480,7 @@ internal class AuthImpl(
480480
clearSession()
481481
}
482482
} catch (e: Exception) {
483-
coroutineContext.ensureActive()
483+
currentCoroutineContext().ensureActive()
484484
Auth.logger.e(e) { "Couldn't reach Supabase. Either the address doesn't exist or the network might not be on. Retrying in ${config.retryDelay}..." }
485485
updateStatus(RefreshFailureCause.NetworkError(e))
486486
delay(config.retryDelay)

Auth/src/commonMain/kotlin/io/github/jan/supabase/auth/CodeVerifierCache.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.github.jan.supabase.auth
22

3-
import kotlinx.atomicfu.AtomicRef
4-
import kotlinx.atomicfu.atomic
3+
import kotlin.concurrent.atomics.AtomicReference
54

65
/**
76
* A cache for the code verifier used in the PKCE flow.
@@ -26,22 +25,22 @@ interface CodeVerifierCache {
2625
}
2726

2827
/**
29-
* A [CodeVerifierCache] that uses the [AtomicRef] API.
28+
* A [CodeVerifierCache] that uses the [AtomicReference] API.
3029
*/
3130
class MemoryCodeVerifierCache(codeVerifier: String? = null): CodeVerifierCache {
3231

33-
private var codeVerifier by atomic(codeVerifier)
32+
private val codeVerifier = AtomicReference(codeVerifier)
3433

3534
override suspend fun saveCodeVerifier(codeVerifier: String) {
36-
this.codeVerifier = codeVerifier
35+
this.codeVerifier.store(codeVerifier)
3736
}
3837

3938
override suspend fun loadCodeVerifier(): String? {
40-
return codeVerifier
39+
return codeVerifier.load()
4140
}
4241

4342
override suspend fun deleteCodeVerifier() {
44-
codeVerifier = null
43+
codeVerifier.store(null)
4544
}
4645

4746
}

Auth/src/commonMain/kotlin/io/github/jan/supabase/auth/SessionManager.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package io.github.jan.supabase.auth
22

33
import io.github.jan.supabase.auth.user.UserSession
4-
import kotlinx.atomicfu.AtomicRef
5-
import kotlinx.atomicfu.atomic
4+
import kotlin.concurrent.atomics.AtomicReference
65

76
/**
87
* Represents the session manager. Used for saving and restoring the session from storage
@@ -27,22 +26,22 @@ interface SessionManager {
2726
}
2827

2928
/**
30-
* A [SessionManager] that uses the [AtomicRef] API.
29+
* A [SessionManager] that uses the [AtomicReference] API.
3130
*/
3231
class MemorySessionManager(session: UserSession? = null): SessionManager {
3332

34-
private var session by atomic(session)
33+
private val session = AtomicReference(session)
3534

3635
override suspend fun saveSession(session: UserSession) {
37-
this.session = session
36+
this.session.store(session)
3837
}
3938

4039
override suspend fun loadSession(): UserSession? {
41-
return session
40+
return session.load()
4241
}
4342

4443
override suspend fun deleteSession() {
45-
session = null
44+
session.store(null)
4645
}
4746

4847
}

Auth/src/commonTest/kotlin/AuthTest.kt

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ import io.github.jan.supabase.SupabaseClientBuilder
33
import io.github.jan.supabase.auth.Auth
44
import io.github.jan.supabase.auth.MemorySessionManager
55
import io.github.jan.supabase.auth.auth
6-
import io.github.jan.supabase.auth.minimalConfig
76
import io.github.jan.supabase.auth.event.AuthEvent
8-
import io.github.jan.supabase.auth.minimalSettings
7+
import io.github.jan.supabase.auth.minimalConfig
98
import io.github.jan.supabase.auth.providers.Github
109
import io.github.jan.supabase.auth.status.RefreshFailureCause
1110
import io.github.jan.supabase.auth.status.SessionSource
@@ -45,10 +44,9 @@ class AuthTest {
4544
val client = createMockedSupabaseClient(
4645
configuration = {
4746
install(Auth) {
48-
minimalSettings(
49-
sessionManager = sessionManager,
50-
autoLoadFromStorage = true
51-
)
47+
minimalConfig()
48+
this.sessionManager = sessionManager
49+
autoLoadFromStorage = true
5250
}
5351
}
5452
)
@@ -80,10 +78,9 @@ class AuthTest {
8078
val client = createMockedSupabaseClient(
8179
configuration = {
8280
install(Auth) {
83-
minimalSettings(
84-
sessionManager = sessionManager,
85-
autoSaveToStorage = true
86-
)
81+
minimalConfig()
82+
this.sessionManager = sessionManager
83+
autoSaveToStorage = true
8784
}
8885
}
8986
)
@@ -103,9 +100,8 @@ class AuthTest {
103100
val newSession = userSession()
104101
val client = createMockedSupabaseClient(configuration = {
105102
install(Auth) {
106-
minimalSettings(
107-
alwaysAutoRefresh = true
108-
)
103+
minimalConfig()
104+
alwaysAutoRefresh = true
109105
}
110106
}) {
111107
respondJson(newSession)
@@ -126,11 +122,10 @@ class AuthTest {
126122
val newSession = userSession()
127123
val client = createMockedSupabaseClient(configuration = {
128124
install(Auth) {
129-
minimalSettings(
130-
autoLoadFromStorage = false,
131-
alwaysAutoRefresh = false,
132-
autoSaveToStorage = false
133-
)
125+
minimalConfig()
126+
autoLoadFromStorage = false
127+
alwaysAutoRefresh = false
128+
autoSaveToStorage = false
134129
}
135130
}) {
136131
respondJson(newSession)
@@ -153,9 +148,8 @@ class AuthTest {
153148
val newSession = userSession()
154149
val client = createMockedSupabaseClient(configuration = {
155150
install(Auth) {
156-
minimalSettings(
157-
alwaysAutoRefresh = true
158-
)
151+
minimalConfig()
152+
alwaysAutoRefresh = true
159153
}
160154
defaultLogLevel = LogLevel.DEBUG
161155
}) {
@@ -180,9 +174,8 @@ class AuthTest {
180174
val newSession = userSession()
181175
val client = createMockedSupabaseClient(configuration = {
182176
install(Auth) {
183-
minimalSettings(
184-
alwaysAutoRefresh = true
185-
)
177+
minimalConfig()
178+
alwaysAutoRefresh = true
186179
}
187180
defaultLogLevel = LogLevel.DEBUG
188181
}) {
@@ -207,9 +200,8 @@ class AuthTest {
207200
val newSession = userSession()
208201
val client = createMockedSupabaseClient(configuration = {
209202
install(Auth) {
210-
minimalSettings(
211-
alwaysAutoRefresh = false
212-
)
203+
minimalConfig()
204+
alwaysAutoRefresh = false
213205
}
214206
defaultLogLevel = LogLevel.DEBUG
215207
}) {

Auth/src/commonTest/kotlin/UrlUtilsTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import io.github.jan.supabase.auth.event.AuthEvent
88
import io.github.jan.supabase.auth.exception.AuthErrorCode
99
import io.github.jan.supabase.auth.getFragmentParts
1010
import io.github.jan.supabase.auth.handledUrlParameterError
11-
import io.github.jan.supabase.auth.minimalSettings
11+
import io.github.jan.supabase.auth.minimalConfig
1212
import io.github.jan.supabase.auth.redirectTo
1313
import io.github.jan.supabase.auth.status.SessionStatus
1414
import io.github.jan.supabase.testing.createMockedSupabaseClient
@@ -77,7 +77,7 @@ class UrlUtilsTest {
7777
val supabase = createMockedSupabaseClient(
7878
configuration = {
7979
install(Auth) {
80-
minimalSettings()
80+
minimalConfig()
8181
}
8282
}
8383
)
@@ -102,7 +102,7 @@ class UrlUtilsTest {
102102
val supabase = createMockedSupabaseClient(
103103
configuration = {
104104
install(Auth) {
105-
minimalSettings()
105+
minimalConfig()
106106
}
107107
}
108108
)

Auth/src/settingsMain/kotlin/io/github/jan/supabase/auth/SettingsSessionManager.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ import com.russhwolf.settings.Settings
55
import com.russhwolf.settings.coroutines.toSuspendSettings
66
import io.github.jan.supabase.auth.user.UserSession
77
import io.github.jan.supabase.logging.e
8+
import kotlinx.coroutines.currentCoroutineContext
89
import kotlinx.coroutines.ensureActive
9-
import kotlinx.serialization.encodeToString
1010
import kotlinx.serialization.json.Json
1111
import kotlinx.serialization.json.JsonBuilder
12-
import kotlin.coroutines.coroutineContext
1312

1413
private val settingsJson = Json {
1514
encodeDefaults = true
@@ -56,7 +55,7 @@ class SettingsSessionManager(
5655
return try {
5756
json.decodeFromString(session)
5857
} catch(e: Exception) {
59-
coroutineContext.ensureActive()
58+
currentCoroutineContext().ensureActive()
6059
Auth.logger.e(e) { "Failed to load session" }
6160
null
6261
}

Realtime/src/commonMain/kotlin/io/github/jan/supabase/realtime/CallbackManager.kt

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,27 @@ import io.github.jan.supabase.SupabaseSerializer
44
import io.github.jan.supabase.annotations.SupabaseInternal
55
import io.github.jan.supabase.collections.AtomicMutableList
66
import io.github.jan.supabase.serializer.KotlinXSerializer
7-
import kotlinx.atomicfu.atomic
87
import kotlinx.serialization.json.JsonObject
8+
import kotlin.concurrent.atomics.AtomicInt
9+
import kotlin.concurrent.atomics.AtomicReference
10+
import kotlin.concurrent.atomics.fetchAndIncrement
911

1012
@SupabaseInternal
1113
sealed interface CallbackManager {
1214

13-
fun triggerPostgresChange(ids: List<Long>, data: PostgresAction)
15+
fun triggerPostgresChange(ids: List<Int>, data: PostgresAction)
1416

1517
fun triggerBroadcast(event: String, data: JsonObject)
1618

1719
fun triggerPresenceDiff(joins: Map<String, Presence>, leaves: Map<String, Presence>)
1820

19-
fun addBroadcastCallback(event: String, callback: (JsonObject) -> Unit): Long
21+
fun addBroadcastCallback(event: String, callback: (JsonObject) -> Unit): Int
2022

21-
fun addPostgresCallback(filter: PostgresJoinConfig, callback: (PostgresAction) -> Unit): Long
23+
fun addPostgresCallback(filter: PostgresJoinConfig, callback: (PostgresAction) -> Unit): Int
2224

23-
fun addPresenceCallback(callback: (PresenceAction) -> Unit): Long
25+
fun addPresenceCallback(callback: (PresenceAction) -> Unit): Int
2426

25-
fun removeCallbackById(id: Long)
27+
fun removeCallbackById(id: Int)
2628

2729
fun setServerChanges(changes: List<PostgresJoinConfig>)
2830

@@ -34,29 +36,29 @@ internal class CallbackManagerImpl(
3436
private val serializer: SupabaseSerializer = KotlinXSerializer()
3537
) : CallbackManager {
3638

37-
private var nextId by atomic(0L)
38-
private var _serverChanges by atomic(listOf<PostgresJoinConfig>())
39-
val serverChanges: List<PostgresJoinConfig> get() = _serverChanges
39+
private val nextId = AtomicInt(0)
40+
private val _serverChanges = AtomicReference(listOf<PostgresJoinConfig>())
41+
val serverChanges: List<PostgresJoinConfig> get() = _serverChanges.load()
4042
private val callbacks = AtomicMutableList<RealtimeCallback<*>>()
4143

4244
override fun getCallbacks(): List<RealtimeCallback<*>> {
4345
return callbacks.toList()
4446
}
4547

46-
override fun addBroadcastCallback(event: String, callback: (JsonObject) -> Unit): Long {
47-
val id = nextId++
48+
override fun addBroadcastCallback(event: String, callback: (JsonObject) -> Unit): Int {
49+
val id = nextId.fetchAndIncrement()
4850
callbacks += RealtimeCallback.BroadcastCallback(callback, event, id)
4951
return id
5052
}
5153

52-
override fun addPostgresCallback(filter: PostgresJoinConfig, callback: (PostgresAction) -> Unit): Long {
53-
val id = nextId++
54+
override fun addPostgresCallback(filter: PostgresJoinConfig, callback: (PostgresAction) -> Unit): Int {
55+
val id = nextId.fetchAndIncrement()
5456
callbacks += RealtimeCallback.PostgresCallback(callback, filter, id)
5557
return id
5658
}
5759

58-
override fun triggerPostgresChange(ids: List<Long>, data: PostgresAction) {
59-
val filter = _serverChanges.filter { it.id in ids }
60+
override fun triggerPostgresChange(ids: List<Int>, data: PostgresAction) {
61+
val filter = serverChanges.filter { it.id in ids }
6062
val postgresCallbacks = callbacks.filterIsInstance<RealtimeCallback.PostgresCallback>()
6163
val callbacks =
6264
postgresCallbacks.filter { cc -> filter.any { sc -> cc.filter == sc } }
@@ -74,18 +76,18 @@ internal class CallbackManagerImpl(
7476
presenceCallbacks.forEach { it.callback(PresenceActionImpl(serializer, joins, leaves)) }
7577
}
7678

77-
override fun addPresenceCallback(callback: (PresenceAction) -> Unit): Long {
78-
val id = nextId++
79+
override fun addPresenceCallback(callback: (PresenceAction) -> Unit): Int {
80+
val id = nextId.fetchAndIncrement()
7981
callbacks += RealtimeCallback.PresenceCallback(callback, id)
8082
return id
8183
}
8284

83-
override fun removeCallbackById(id: Long) {
85+
override fun removeCallbackById(id: Int) {
8486
callbacks.indexOfFirst { it.id == id }.takeIf { it != -1 }?.let { callbacks.removeAt(it) }
8587
}
8688

8789
override fun setServerChanges(changes: List<PostgresJoinConfig>) {
88-
_serverChanges = changes
90+
_serverChanges.store(changes)
8991
}
9092

9193
}

0 commit comments

Comments
 (0)