Skip to content

Commit 10f78d5

Browse files
greyson-signalcody-signal
authored andcommitted
Change spinner to lazily read database stuff.
Otherwise you get into situations where Spinner will force DB accesses super early during Application#onCreate on the main thread, which can be bad when testing large DB migrations.
1 parent 3ce5a7d commit 10f78d5

File tree

4 files changed

+39
-35
lines changed

4 files changed

+39
-35
lines changed

app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,25 @@ class SpinnerApplicationContext : ApplicationContext() {
5151
Spinner.init(
5252
this,
5353
mapOf(
54-
"Device" to "${Build.MODEL} (Android ${Build.VERSION.RELEASE}, API ${Build.VERSION.SDK_INT})",
55-
"Package" to "$packageName (${AppSignatureUtil.getAppSignature(this)})",
56-
"App Version" to "${BuildConfig.VERSION_NAME} (${BuildConfig.CANONICAL_VERSION_CODE}, ${BuildConfig.GIT_HASH})",
57-
"Profile Name" to (if (SignalStore.account().isRegistered) Recipient.self().profileName.toString() else "none"),
58-
"E164" to (SignalStore.account().e164 ?: "none"),
59-
"ACI" to (SignalStore.account().aci?.toString() ?: "none"),
60-
"PNI" to (SignalStore.account().pni?.toString() ?: "none"),
61-
Spinner.KEY_ENVIRONMENT to BuildConfig.FLAVOR_environment.uppercase(Locale.US)
54+
"Device" to { "${Build.MODEL} (Android ${Build.VERSION.RELEASE}, API ${Build.VERSION.SDK_INT})" },
55+
"Package" to { "$packageName (${AppSignatureUtil.getAppSignature(this)})" },
56+
"App Version" to { "${BuildConfig.VERSION_NAME} (${BuildConfig.CANONICAL_VERSION_CODE}, ${BuildConfig.GIT_HASH})" },
57+
"Profile Name" to { (if (SignalStore.account().isRegistered) Recipient.self().profileName.toString() else "none") },
58+
"E164" to { SignalStore.account().e164 ?: "none" },
59+
"ACI" to { SignalStore.account().aci?.toString() ?: "none" },
60+
"PNI" to { SignalStore.account().pni?.toString() ?: "none" },
61+
Spinner.KEY_ENVIRONMENT to { BuildConfig.FLAVOR_environment.uppercase(Locale.US) }
6262
),
6363
linkedMapOf(
6464
"signal" to DatabaseConfig(
65-
db = SignalDatabase.rawDatabase,
65+
db = { SignalDatabase.rawDatabase },
6666
columnTransformers = listOf(MessageBitmaskColumnTransformer, GV2Transformer, GV2UpdateTransformer, IsStoryTransformer, TimestampTransformer, ProfileKeyCredentialTransformer)
6767
),
68-
"jobmanager" to DatabaseConfig(db = JobDatabase.getInstance(this).sqlCipherDatabase),
69-
"keyvalue" to DatabaseConfig(db = KeyValueDatabase.getInstance(this).sqlCipherDatabase),
70-
"megaphones" to DatabaseConfig(db = MegaphoneDatabase.getInstance(this).sqlCipherDatabase),
71-
"localmetrics" to DatabaseConfig(db = LocalMetricsDatabase.getInstance(this).sqlCipherDatabase),
72-
"logs" to DatabaseConfig(db = LogDatabase.getInstance(this).sqlCipherDatabase),
68+
"jobmanager" to DatabaseConfig(db = { JobDatabase.getInstance(this).sqlCipherDatabase }),
69+
"keyvalue" to DatabaseConfig(db = { KeyValueDatabase.getInstance(this).sqlCipherDatabase }),
70+
"megaphones" to DatabaseConfig(db = { MegaphoneDatabase.getInstance(this).sqlCipherDatabase }),
71+
"localmetrics" to DatabaseConfig(db = { LocalMetricsDatabase.getInstance(this).sqlCipherDatabase }),
72+
"logs" to DatabaseConfig(db = { LogDatabase.getInstance(this).sqlCipherDatabase }),
7373
),
7474
linkedMapOf(
7575
StorageServicePlugin.PATH to StorageServicePlugin()

spinner/app/src/main/java/org/signal/spinnertest/MainActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ class MainActivity : AppCompatActivity() {
2020
Spinner.init(
2121
application,
2222
mapOf(
23-
"Name" to "${Build.MODEL} (API ${Build.VERSION.SDK_INT})",
24-
"Package" to packageName
23+
"Name" to { "${Build.MODEL} (API ${Build.VERSION.SDK_INT})" },
24+
"Package" to { packageName }
2525
),
26-
mapOf("main" to Spinner.DatabaseConfig(db = db)),
26+
mapOf("main" to Spinner.DatabaseConfig(db = { db })),
2727
emptyMap()
2828
)
2929
}

spinner/lib/src/main/java/org/signal/spinner/Spinner.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object Spinner {
1818

1919
private lateinit var server: SpinnerServer
2020

21-
fun init(application: Application, deviceInfo: Map<String, String>, databases: Map<String, DatabaseConfig>, plugins: Map<String, Plugin>) {
21+
fun init(application: Application, deviceInfo: Map<String, () -> String>, databases: Map<String, DatabaseConfig>, plugins: Map<String, Plugin>) {
2222
try {
2323
server = SpinnerServer(application, deviceInfo, databases, plugins)
2424
server.start()
@@ -91,7 +91,7 @@ object Spinner {
9191
}
9292

9393
data class DatabaseConfig(
94-
val db: SupportSQLiteDatabase,
94+
val db: () -> SupportSQLiteDatabase,
9595
val columnTransformers: List<ColumnTransformer> = emptyList()
9696
)
9797
}

spinner/lib/src/main/java/org/signal/spinner/SpinnerServer.kt

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import kotlin.math.min
2828
*/
2929
internal class SpinnerServer(
3030
private val application: Application,
31-
deviceInfo: Map<String, String>,
31+
deviceInfo: Map<String, () -> String>,
3232
private val databases: Map<String, DatabaseConfig>,
3333
private val plugins: Map<String, Plugin>
3434
) : NanoHTTPD(5000) {
@@ -37,8 +37,8 @@ internal class SpinnerServer(
3737
private val TAG = Log.tag(SpinnerServer::class.java)
3838
}
3939

40-
private val deviceInfo: Map<String, String> = deviceInfo.filterKeys { !it.startsWith(Spinner.KEY_PREFIX) }
41-
private val environment: String = deviceInfo[Spinner.KEY_ENVIRONMENT] ?: "UNKNOWN"
40+
private val deviceInfo: Map<String, () -> String> = deviceInfo.filterKeys { !it.startsWith(Spinner.KEY_PREFIX) }
41+
private val environment: String = deviceInfo[Spinner.KEY_ENVIRONMENT]?.let { it() } ?: "UNKNOWN"
4242

4343
private val handlebars: Handlebars = Handlebars(AssetTemplateLoader(application)).apply {
4444
registerHelper("eq", ConditionalHelpers.eq)
@@ -61,8 +61,8 @@ internal class SpinnerServer(
6161
return when {
6262
session.method == Method.GET && session.uri == "/css/main.css" -> newFileResponse("css/main.css", "text/css")
6363
session.method == Method.GET && session.uri == "/js/main.js" -> newFileResponse("js/main.js", "text/javascript")
64-
session.method == Method.GET && session.uri == "/" -> getIndex(dbParam, dbConfig.db)
65-
session.method == Method.GET && session.uri == "/browse" -> getBrowse(dbParam, dbConfig.db)
64+
session.method == Method.GET && session.uri == "/" -> getIndex(dbParam, dbConfig.db())
65+
session.method == Method.GET && session.uri == "/browse" -> getBrowse(dbParam, dbConfig.db())
6666
session.method == Method.POST && session.uri == "/browse" -> postBrowse(dbParam, dbConfig, session)
6767
session.method == Method.GET && session.uri == "/query" -> getQuery(dbParam)
6868
session.method == Method.POST && session.uri == "/query" -> postQuery(dbParam, dbConfig, session)
@@ -98,7 +98,7 @@ internal class SpinnerServer(
9898
"overview",
9999
OverviewPageModel(
100100
environment = environment,
101-
deviceInfo = deviceInfo,
101+
deviceInfo = deviceInfo.resolve(),
102102
database = dbName,
103103
databases = databases.keys.toList(),
104104
plugins = plugins.values.toList(),
@@ -115,7 +115,7 @@ internal class SpinnerServer(
115115
"browse",
116116
BrowsePageModel(
117117
environment = environment,
118-
deviceInfo = deviceInfo,
118+
deviceInfo = deviceInfo.resolve(),
119119
database = dbName,
120120
databases = databases.keys.toList(),
121121
plugins = plugins.values.toList(),
@@ -130,7 +130,7 @@ internal class SpinnerServer(
130130
var pageIndex: Int = session.parameters["pageIndex"]?.get(0)?.toInt() ?: 0
131131
val action: String? = session.parameters["action"]?.get(0)
132132

133-
val rowCount = dbConfig.db.getTableRowCount(table)
133+
val rowCount = dbConfig.db().getTableRowCount(table)
134134
val pageCount = ceil(rowCount.toFloat() / pageSize.toFloat()).toInt()
135135

136136
when (action) {
@@ -141,17 +141,17 @@ internal class SpinnerServer(
141141
}
142142

143143
val query = "select * from $table limit $pageSize offset ${pageSize * pageIndex}"
144-
val queryResult = dbConfig.db.query(query).use { it.toQueryResult(columnTransformers = dbConfig.columnTransformers) }
144+
val queryResult = dbConfig.db().query(query).use { it.toQueryResult(columnTransformers = dbConfig.columnTransformers) }
145145

146146
return renderTemplate(
147147
"browse",
148148
BrowsePageModel(
149149
environment = environment,
150-
deviceInfo = deviceInfo,
150+
deviceInfo = deviceInfo.resolve(),
151151
database = dbName,
152152
databases = databases.keys.toList(),
153153
plugins = plugins.values.toList(),
154-
tableNames = dbConfig.db.getTableNames(),
154+
tableNames = dbConfig.db().getTableNames(),
155155
table = table,
156156
queryResult = queryResult,
157157
pagingData = PagingData(
@@ -171,7 +171,7 @@ internal class SpinnerServer(
171171
"query",
172172
QueryPageModel(
173173
environment = environment,
174-
deviceInfo = deviceInfo,
174+
deviceInfo = deviceInfo.resolve(),
175175
database = dbName,
176176
databases = databases.keys.toList(),
177177
plugins = plugins.values.toList(),
@@ -193,7 +193,7 @@ internal class SpinnerServer(
193193
"recent",
194194
RecentPageModel(
195195
environment = environment,
196-
deviceInfo = deviceInfo,
196+
deviceInfo = deviceInfo.resolve(),
197197
database = dbName,
198198
databases = databases.keys.toList(),
199199
plugins = plugins.values.toList(),
@@ -212,12 +212,12 @@ internal class SpinnerServer(
212212
"query",
213213
QueryPageModel(
214214
environment = environment,
215-
deviceInfo = deviceInfo,
215+
deviceInfo = deviceInfo.resolve(),
216216
database = dbName,
217217
databases = databases.keys.toList(),
218218
plugins = plugins.values.toList(),
219219
query = rawQuery,
220-
queryResult = dbConfig.db.query(query).use { it.toQueryResult(queryStartTimeNanos = startTimeNanos, columnTransformers = dbConfig.columnTransformers) }
220+
queryResult = dbConfig.db().query(query).use { it.toQueryResult(queryStartTimeNanos = startTimeNanos, columnTransformers = dbConfig.columnTransformers) }
221221
)
222222
)
223223
}
@@ -227,7 +227,7 @@ internal class SpinnerServer(
227227
"plugin",
228228
PluginPageModel(
229229
environment = environment,
230-
deviceInfo = deviceInfo,
230+
deviceInfo = deviceInfo.resolve(),
231231
database = dbName,
232232
databases = databases.keys.toList(),
233233
plugins = plugins.values.toList(),
@@ -389,6 +389,10 @@ internal class SpinnerServer(
389389
return params[name]
390390
}
391391

392+
private fun Map<String, () -> String>.resolve(): Map<String, String> {
393+
return this.mapValues { entry -> entry.value() }.toMap()
394+
}
395+
392396
interface PrefixPageData {
393397
val environment: String
394398
val deviceInfo: Map<String, String>

0 commit comments

Comments
 (0)