Skip to content

Commit 73f1f00

Browse files
MozLandoGrisha Kruglov
and
Grisha Kruglov
committed
5751: update/subscribe push race workaround r=jonalmeida a=grigoryk Co-authored-by: Grisha Kruglov <[email protected]>
2 parents c7108ef + b47f24d commit 73f1f00

File tree

4 files changed

+31
-14
lines changed

4 files changed

+31
-14
lines changed

components/feature/push/src/main/java/mozilla/components/feature/push/AutoPushFeature.kt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ class AutoPushFeature(
9999
get() = preferences(context).getLong(LAST_VERIFIED, System.currentTimeMillis())
100100
set(value) = preferences(context).edit().putLong(LAST_VERIFIED, value).apply()
101101

102-
internal var job: Job = SupervisorJob()
103-
private val scope = CoroutineScope(coroutineContext) + job
102+
private val scope = CoroutineScope(coroutineContext) + SupervisorJob()
104103

105104
init {
106105
// If we have a token, initialize the rust component first.
@@ -132,9 +131,8 @@ class AutoPushFeature(
132131
service.stop()
133132

134133
DeliveryManager.with(connection) {
135-
job = scope.launch {
134+
scope.launch {
136135
unsubscribeAll()
137-
job.cancel()
138136
}
139137
}
140138

@@ -147,7 +145,7 @@ class AutoPushFeature(
147145
* each push type and notifies the subscribers.
148146
*/
149147
override fun onNewToken(newToken: String) {
150-
job = scope.launchAndTry {
148+
scope.launchAndTry {
151149
logger.info("Received a new registration token from push service.")
152150

153151
connection.updateToken(newToken)
@@ -173,7 +171,7 @@ class AutoPushFeature(
173171
logger.error("Unknown channelID: ${message.channelId}")
174172
return
175173
}
176-
job = scope.launchAndTry {
174+
scope.launchAndTry {
177175
DeliveryManager.with(connection) {
178176
logger.info("New push message decrypted.")
179177
val decrypted = decrypt(
@@ -229,7 +227,7 @@ class AutoPushFeature(
229227
*/
230228
fun subscribeForType(type: PushType) {
231229
DeliveryManager.with(connection) {
232-
job = scope.launchAndTry {
230+
scope.launchAndTry {
233231
val sub = subscribe(type.toChannelId()).toPushSubscription()
234232
subscriptionObservers.notifyObservers { onSubscriptionAvailable(sub) }
235233
}
@@ -246,7 +244,7 @@ class AutoPushFeature(
246244
*/
247245
fun unsubscribeForType(type: PushType) {
248246
DeliveryManager.with(connection) {
249-
job = scope.launchAndTry {
247+
scope.launchAndTry {
250248
unsubscribe(type.toChannelId())
251249
}
252250
}
@@ -257,7 +255,7 @@ class AutoPushFeature(
257255
*/
258256
fun subscribeAll() {
259257
DeliveryManager.with(connection) {
260-
job = scope.launchAndTry {
258+
scope.launchAndTry {
261259
PushType.values().forEach { type ->
262260
val sub = subscribe(type.toChannelId()).toPushSubscription()
263261
subscriptionObservers.notifyObservers { onSubscriptionAvailable(sub) }
@@ -290,7 +288,7 @@ class AutoPushFeature(
290288
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
291289
internal fun verifyActiveSubscriptions() {
292290
DeliveryManager.with(connection) {
293-
job = scope.launchAndTry {
291+
scope.launchAndTry {
294292
val notifyObservers = verifyConnection()
295293

296294
if (notifyObservers) {

components/feature/push/src/main/java/mozilla/components/feature/push/Connection.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import androidx.annotation.GuardedBy
88
import androidx.annotation.VisibleForTesting
99
import mozilla.appservices.push.BridgeType
1010
import mozilla.appservices.push.PushAPI
11+
import mozilla.appservices.push.PushError
1112
import mozilla.appservices.push.PushManager
1213
import mozilla.appservices.push.SubscriptionResponse
1314
import java.io.Closeable
1415
import java.util.Locale
16+
import java.util.UUID
1517

1618
/**
1719
* An interface that wraps the [PushAPI].
@@ -81,7 +83,23 @@ internal class RustPushConnection(
8183
)
8284
return true
8385
}
84-
return pushApi.update(token)
86+
// This call will fail if we haven't 'subscribed' yet.
87+
return try {
88+
pushApi.update(token)
89+
} catch (e: PushError) {
90+
// Once we get GeneralError, let's catch that instead:
91+
// https://github.com/mozilla/application-services/issues/2541
92+
val fakeChannelId = UUID.nameUUIDFromBytes("fake".toByteArray()).toString().replace("-", "")
93+
// It's possible that we have a race (on a first run) between 'subscribing' and setting a token.
94+
// 'update' expects that we've called 'subscribe' (which would obtain a 'uaid' from an autopush
95+
// server), which we need to have in order to call 'update' on the library.
96+
// In https://github.com/mozilla/application-services/issues/2490 this will be fixed, and we
97+
// can clean up this work-around.
98+
pushApi.subscribe(fakeChannelId)
99+
100+
// If this fails again, give up - it seems like a legit failure that we should re-throw.
101+
pushApi.update(token)
102+
}
85103
}
86104

87105
@GuardedBy("this")

components/feature/push/src/test/java/mozilla/components/feature/push/AutoPushFeatureTest.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import mozilla.components.support.test.whenever
3030
import org.junit.Assert.assertEquals
3131
import org.junit.Assert.assertNotNull
3232
import org.junit.Assert.assertNull
33-
import org.junit.Assert.assertTrue
3433
import org.junit.Before
3534
import org.junit.Test
3635
import org.junit.runner.RunWith
@@ -98,13 +97,12 @@ class AutoPushFeatureTest {
9897
val connection: PushConnection = mock()
9998
whenever(connection.isInitialized()).thenReturn(true)
10099

101-
val feature = spy(AutoPushFeature(testContext, service, mock(), coroutineContext, connection)).also {
100+
AutoPushFeature(testContext, service, mock(), coroutineContext, connection).also {
102101
it.shutdown()
103102
}
104103

105104
verify(service).stop()
106105
verify(connection).unsubscribeAll()
107-
assertTrue(feature.job.isCancelled)
108106
}
109107

110108
@Test

components/feature/push/src/test/java/mozilla/components/feature/push/RustPushConnectionTest.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package mozilla.components.feature.push
66

77
import kotlinx.coroutines.runBlocking
88
import mozilla.appservices.push.PushAPI
9+
import mozilla.components.support.test.any
910
import mozilla.components.support.test.eq
1011
import mozilla.components.support.test.mock
1112
import org.junit.Assert.assertFalse
@@ -16,6 +17,7 @@ import org.junit.Ignore
1617
import org.junit.Test
1718
import org.mockito.ArgumentMatchers.nullable
1819
import org.mockito.Mockito.anyString
20+
import org.mockito.Mockito.never
1921
import org.mockito.Mockito.verify
2022

2123
class RustPushConnectionTest {
@@ -44,6 +46,7 @@ class RustPushConnectionTest {
4446
connection.updateToken("123")
4547
}
4648

49+
verify(api, never()).subscribe(any(), any(), any())
4750
verify(api).update(anyString())
4851
}
4952

0 commit comments

Comments
 (0)