@@ -7,6 +7,7 @@ import com.segment.analytics.kotlin.core.platform.Timeline
7
7
import com.segment.analytics.kotlin.core.platform.plugins.ContextPlugin
8
8
import com.segment.analytics.kotlin.core.platform.plugins.SegmentDestination
9
9
import com.segment.analytics.kotlin.core.platform.plugins.StartupQueue
10
+ import com.segment.analytics.kotlin.core.platform.plugins.UserInfoPlugin
10
11
import com.segment.analytics.kotlin.core.platform.plugins.logger.SegmentLog
11
12
import com.segment.analytics.kotlin.core.platform.plugins.logger.log
12
13
import kotlinx.coroutines.*
@@ -19,6 +20,7 @@ import kotlinx.serialization.json.jsonObject
19
20
import kotlinx.serialization.serializer
20
21
import sovran.kotlin.Store
21
22
import sovran.kotlin.Subscriber
23
+ import java.util.*
22
24
import java.util.concurrent.Executors
23
25
import kotlin.reflect.KClass
24
26
@@ -52,6 +54,8 @@ open class Analytics protected constructor(
52
54
)
53
55
}
54
56
57
+ internal lateinit var userInfo: UserInfo
58
+
55
59
companion object {
56
60
var debugLogsEnabled: Boolean = false
57
61
set(value) {
@@ -75,6 +79,7 @@ open class Analytics protected constructor(
75
79
* Public constructor of Analytics.
76
80
* @property configuration configuration that analytics can use
77
81
*/
82
+ @OptIn(ExperimentalCoroutinesApi ::class )
78
83
constructor (configuration: Configuration ) : this (configuration,
79
84
object : CoroutineConfiguration {
80
85
override val store = Store ()
@@ -94,11 +99,14 @@ open class Analytics protected constructor(
94
99
add(SegmentLog ())
95
100
add(StartupQueue ())
96
101
add(ContextPlugin ())
102
+ add(UserInfoPlugin ())
97
103
98
104
// Setup store
99
105
analyticsScope.launch(analyticsDispatcher) {
100
106
store.also {
101
- it.provide(UserInfo .defaultState(storage))
107
+ // load memory with initial value
108
+ userInfo = UserInfo .defaultState(storage)
109
+ it.provide(userInfo)
102
110
it.provide(System .defaultState(configuration, storage))
103
111
104
112
// subscribe to store after state is provided
@@ -523,8 +531,11 @@ open class Analytics protected constructor(
523
531
* user logs out
524
532
*/
525
533
fun reset () {
534
+ val newAnonymousId = UUID .randomUUID().toString()
535
+ userInfo = UserInfo (newAnonymousId, null , null )
536
+
526
537
analyticsScope.launch(analyticsDispatcher) {
527
- store.dispatch(UserInfo .ResetAction (), UserInfo ::class )
538
+ store.dispatch(UserInfo .ResetAction (newAnonymousId ), UserInfo ::class )
528
539
timeline.applyClosure {
529
540
(it as ? EventPlugin )?.reset()
530
541
}
@@ -540,6 +551,7 @@ open class Analytics protected constructor(
540
551
* CoroutineDispatchers and ExecutorService instances so they allow the container to shutdown
541
552
* properly.
542
553
*/
554
+ @OptIn(ExperimentalCoroutinesApi ::class )
543
555
fun shutdown () {
544
556
(analyticsDispatcher as CloseableCoroutineDispatcher ).close()
545
557
(networkIODispatcher as CloseableCoroutineDispatcher ).close()
@@ -549,47 +561,44 @@ open class Analytics protected constructor(
549
561
}
550
562
551
563
/* *
552
- * Retrieve the userId registered by a previous `identify` call in a blocking way.
553
- * Note: this method invokes `runBlocking` internal, it's not recommended to be used
554
- * in coroutines.
564
+ * Retrieve the userId registered by a previous `identify` call.
555
565
*/
556
- @BlockingApi
557
- fun userId (): String? = runBlocking {
558
- userIdAsync()
566
+ fun userId (): String? {
567
+ return userInfo.userId
559
568
}
560
569
561
570
/* *
562
571
* Retrieve the userId registered by a previous `identify` call
563
572
*/
564
- suspend fun userIdAsync (): String? {
565
- val userInfo = store.currentState(UserInfo ::class )
566
- return userInfo?.userId
573
+ @Deprecated(
574
+ " This function no longer serves a purpose and internally calls `userId()`." ,
575
+ ReplaceWith (" userId()" )
576
+ )
577
+ fun userIdAsync (): String? {
578
+ return userId()
567
579
}
568
580
569
581
/* *
570
- * Retrieve the traits registered by a previous `identify` call in a blocking way.
571
- * Note: this method invokes `runBlocking` internal, it's not recommended to be used
572
- * in coroutines.
582
+ * Retrieve the traits registered by a previous `identify` call.
573
583
*/
574
- @BlockingApi
575
- fun traits (): JsonObject ? = runBlocking {
576
- traitsAsync()
584
+ fun traits (): JsonObject ? {
585
+ return userInfo.traits
577
586
}
578
587
579
588
/* *
580
589
* Retrieve the traits registered by a previous `identify` call
581
590
*/
582
- suspend fun traitsAsync (): JsonObject ? {
583
- val userInfo = store.currentState(UserInfo ::class )
584
- return userInfo?.traits
591
+ @Deprecated(
592
+ " This function no longer serves a purpose and internally calls `traits()`." ,
593
+ ReplaceWith (" traits()" )
594
+ )
595
+ fun traitsAsync (): JsonObject ? {
596
+ return traits()
585
597
}
586
598
587
599
/* *
588
600
* Retrieve the traits registered by a previous `identify` call in a blocking way.
589
- * Note: this method invokes `runBlocking` internal, it's not recommended to be used
590
- * in coroutines.
591
601
*/
592
- @BlockingApi
593
602
inline fun <reified T : Any > traits (deserializationStrategy : DeserializationStrategy <T > = Json .serializersModule.serializer()): T ? {
594
603
return traits()?.let {
595
604
decodeFromJsonElement(deserializationStrategy, it)
@@ -599,10 +608,12 @@ open class Analytics protected constructor(
599
608
/* *
600
609
* Retrieve the traits registered by a previous `identify` call
601
610
*/
602
- suspend inline fun <reified T : Any > traitsAsync (deserializationStrategy : DeserializationStrategy <T > = Json .serializersModule.serializer()): T ? {
603
- return traitsAsync()?.let {
604
- decodeFromJsonElement(deserializationStrategy, it)
605
- }
611
+ @Deprecated(
612
+ " This function no longer serves a purpose and internally calls `traits(deserializationStrategy: DeserializationStrategy<T>)`." ,
613
+ ReplaceWith (" traits(deserializationStrategy: DeserializationStrategy<T>)" )
614
+ )
615
+ inline fun <reified T : Any > traitsAsync (deserializationStrategy : DeserializationStrategy <T > = Json .serializersModule.serializer()): T ? {
616
+ return traits(deserializationStrategy)
606
617
}
607
618
608
619
/* *
@@ -624,21 +635,21 @@ open class Analytics protected constructor(
624
635
}
625
636
626
637
/* *
627
- * Retrieve the anonymousId in a blocking way.
628
- * Note: this method invokes `runBlocking` internal, it's not recommended to be used
629
- * in coroutines.
638
+ * Retrieve the anonymousId.
630
639
*/
631
- @BlockingApi
632
- fun anonymousId (): String = runBlocking {
633
- anonymousIdAsync()
640
+ fun anonymousId (): String {
641
+ return userInfo.anonymousId
634
642
}
635
643
636
644
/* *
637
645
* Retrieve the anonymousId
638
646
*/
639
- suspend fun anonymousIdAsync (): String {
640
- val userInfo = store.currentState(UserInfo ::class )
641
- return userInfo?.anonymousId ? : " "
647
+ @Deprecated(
648
+ " This function no longer serves a purpose and internally calls `anonymousId()`." ,
649
+ ReplaceWith (" anonymousId()" )
650
+ )
651
+ fun anonymousIdAsync (): String {
652
+ return anonymousId()
642
653
}
643
654
644
655
/* *
@@ -679,4 +690,4 @@ internal fun isAndroid(): Boolean {
679
690
} catch (e: ClassNotFoundException ) {
680
691
false
681
692
}
682
- }
693
+ }
0 commit comments