@@ -3,22 +3,26 @@ package com.statsig.sdk
3
3
import com.google.gson.Gson
4
4
import com.google.gson.GsonBuilder
5
5
import com.google.gson.ToNumberPolicy
6
- import kotlinx.coroutines.CoroutineExceptionHandler
7
- import kotlinx.coroutines.CoroutineScope
8
- import kotlinx.coroutines.SupervisorJob
9
- import kotlinx.coroutines.cancel
10
- import kotlinx.coroutines.cancelAndJoin
6
+ import kotlinx.coroutines.*
11
7
import kotlinx.coroutines.future.future
12
- import kotlinx.coroutines.runBlocking
13
8
import kotlinx.coroutines.sync.Mutex
14
9
import kotlinx.coroutines.sync.withLock
15
10
import java.util.Collections.emptyMap
16
11
import java.util.concurrent.CompletableFuture
17
12
18
13
sealed class StatsigServer {
19
- internal abstract val errorBoundary: ErrorBoundary
14
+ internal abstract var errorBoundary: ErrorBoundary
15
+ abstract var initialized: Boolean
20
16
21
- @JvmSynthetic abstract suspend fun initialize ()
17
+ @JvmSynthetic abstract fun setup (
18
+ serverSecret : String ,
19
+ options : StatsigOptions ,
20
+ )
21
+
22
+ @JvmSynthetic abstract suspend fun initialize (
23
+ serverSecret : String ,
24
+ options : StatsigOptions ,
25
+ )
22
26
23
27
@JvmSynthetic abstract suspend fun checkGate (user : StatsigUser , gateName : String ): Boolean
24
28
@@ -105,7 +109,7 @@ sealed class StatsigServer {
105
109
metadata : Map <String , String >? = null,
106
110
)
107
111
108
- abstract fun initializeAsync (): CompletableFuture <Void ?>
112
+ abstract fun initializeAsync (serverSecret : String , options : StatsigOptions ): CompletableFuture <Void ?>
109
113
110
114
abstract fun checkGateAsync (user : StatsigUser , gateName : String ): CompletableFuture <Boolean >
111
115
abstract fun checkGateWithExposureLoggingDisabledAsync (user : StatsigUser , gateName : String ): CompletableFuture <Boolean >
@@ -169,42 +173,43 @@ sealed class StatsigServer {
169
173
170
174
@JvmStatic
171
175
@JvmOverloads
172
- fun create (
173
- serverSecret : String ,
174
- options : StatsigOptions = StatsigOptions (),
175
- ): StatsigServer = StatsigServerImpl (serverSecret, options)
176
+ fun create (): StatsigServer = StatsigServerImpl ()
176
177
}
177
178
}
178
179
179
- private class StatsigServerImpl (serverSecret : String , private val options : StatsigOptions ) :
180
+ private class StatsigServerImpl () :
180
181
StatsigServer () {
181
182
182
- init {
183
- if (serverSecret.isEmpty() || ! serverSecret.startsWith(" secret-" )) {
184
- throw StatsigUninitializedException (
185
- " Statsig Server SDKs must be initialized with a secret key" ,
186
- )
187
- }
188
- }
189
-
190
183
private val gson = GsonBuilder ().setObjectToNumberStrategy(ToNumberPolicy .LONG_OR_DOUBLE ).create()
191
184
192
- override val errorBoundary = ErrorBoundary (serverSecret, options)
193
- private val coroutineExceptionHandler =
194
- CoroutineExceptionHandler { _, ex ->
185
+ override lateinit var errorBoundary: ErrorBoundary
186
+ private lateinit var coroutineExceptionHandler: CoroutineExceptionHandler
187
+ private lateinit var statsigJob: CompletableJob
188
+ private lateinit var statsigScope: CoroutineScope
189
+ private lateinit var network: StatsigNetwork
190
+ private lateinit var logger: StatsigLogger
191
+ private lateinit var configEvaluator: Evaluator
192
+ private lateinit var diagnostics: Diagnostics
193
+ private var options: StatsigOptions = StatsigOptions ()
194
+ private val mutex = Mutex ()
195
+ private val statsigMetadata = StatsigMetadata .asMap()
196
+ override var initialized = false
197
+
198
+ override fun setup (serverSecret : String , options : StatsigOptions ) {
199
+ errorBoundary = ErrorBoundary (serverSecret, options)
200
+ coroutineExceptionHandler = CoroutineExceptionHandler { _, ex ->
195
201
// no-op - supervisor job should not throw when a child fails
196
202
errorBoundary.logException(" coroutineExceptionHandler" , ex)
197
203
}
198
- private val statsigJob = SupervisorJob ()
199
- private val statsigScope = CoroutineScope (statsigJob + coroutineExceptionHandler)
200
- private val mutex = Mutex ()
201
- private val statsigMetadata = StatsigMetadata .asMap()
202
- private val network = StatsigNetwork (serverSecret, options, statsigMetadata, errorBoundary)
203
- private var logger: StatsigLogger = StatsigLogger (statsigScope, network, statsigMetadata)
204
- private lateinit var configEvaluator: Evaluator
205
- private lateinit var diagnostics: Diagnostics
204
+ statsigJob = SupervisorJob ()
205
+ statsigScope = CoroutineScope (statsigJob + coroutineExceptionHandler)
206
+ network = StatsigNetwork (serverSecret, options, statsigMetadata, errorBoundary)
207
+ logger = StatsigLogger (statsigScope, network, statsigMetadata)
208
+ this .options = options
209
+ }
206
210
207
- override suspend fun initialize () {
211
+ override suspend fun initialize (serverSecret : String , options : StatsigOptions ) {
212
+ setup(serverSecret, options)
208
213
errorBoundary.capture(
209
214
" initialize" ,
210
215
{
@@ -218,6 +223,7 @@ private class StatsigServerImpl(serverSecret: String, private val options: Stats
218
223
configEvaluator =
219
224
Evaluator (network, options, statsigScope, errorBoundary, diagnostics)
220
225
configEvaluator.initialize()
226
+ initialized = true
221
227
endInitDiagnostics(isSDKInitialized())
222
228
}
223
229
},
@@ -472,6 +478,7 @@ private class StatsigServerImpl(serverSecret: String, private val options: Stats
472
478
configEvaluator.shutdown()
473
479
statsigJob.cancelAndJoin()
474
480
statsigScope.cancel()
481
+ initialized = false
475
482
}
476
483
}
477
484
@@ -503,9 +510,10 @@ private class StatsigServerImpl(serverSecret: String, private val options: Stats
503
510
}, { return @captureSync })
504
511
}
505
512
506
- override fun initializeAsync (): CompletableFuture <Void ?> {
513
+ override fun initializeAsync (serverSecret : String , options : StatsigOptions ): CompletableFuture <Void ?> {
514
+ setup(serverSecret, options)
507
515
return statsigScope.future {
508
- initialize()
516
+ initialize(serverSecret, options )
509
517
null
510
518
}
511
519
}
0 commit comments