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.
main
Greyson Parrelli 2022-12-15 15:17:25 -05:00 zatwierdzone przez Cody Henthorne
rodzic 3ce5a7da67
commit 10f78d5daa
4 zmienionych plików z 39 dodań i 35 usunięć

Wyświetl plik

@ -51,25 +51,25 @@ class SpinnerApplicationContext : ApplicationContext() {
Spinner.init(
this,
mapOf(
"Device" to "${Build.MODEL} (Android ${Build.VERSION.RELEASE}, API ${Build.VERSION.SDK_INT})",
"Package" to "$packageName (${AppSignatureUtil.getAppSignature(this)})",
"App Version" to "${BuildConfig.VERSION_NAME} (${BuildConfig.CANONICAL_VERSION_CODE}, ${BuildConfig.GIT_HASH})",
"Profile Name" to (if (SignalStore.account().isRegistered) Recipient.self().profileName.toString() else "none"),
"E164" to (SignalStore.account().e164 ?: "none"),
"ACI" to (SignalStore.account().aci?.toString() ?: "none"),
"PNI" to (SignalStore.account().pni?.toString() ?: "none"),
Spinner.KEY_ENVIRONMENT to BuildConfig.FLAVOR_environment.uppercase(Locale.US)
"Device" to { "${Build.MODEL} (Android ${Build.VERSION.RELEASE}, API ${Build.VERSION.SDK_INT})" },
"Package" to { "$packageName (${AppSignatureUtil.getAppSignature(this)})" },
"App Version" to { "${BuildConfig.VERSION_NAME} (${BuildConfig.CANONICAL_VERSION_CODE}, ${BuildConfig.GIT_HASH})" },
"Profile Name" to { (if (SignalStore.account().isRegistered) Recipient.self().profileName.toString() else "none") },
"E164" to { SignalStore.account().e164 ?: "none" },
"ACI" to { SignalStore.account().aci?.toString() ?: "none" },
"PNI" to { SignalStore.account().pni?.toString() ?: "none" },
Spinner.KEY_ENVIRONMENT to { BuildConfig.FLAVOR_environment.uppercase(Locale.US) }
),
linkedMapOf(
"signal" to DatabaseConfig(
db = SignalDatabase.rawDatabase,
db = { SignalDatabase.rawDatabase },
columnTransformers = listOf(MessageBitmaskColumnTransformer, GV2Transformer, GV2UpdateTransformer, IsStoryTransformer, TimestampTransformer, ProfileKeyCredentialTransformer)
),
"jobmanager" to DatabaseConfig(db = JobDatabase.getInstance(this).sqlCipherDatabase),
"keyvalue" to DatabaseConfig(db = KeyValueDatabase.getInstance(this).sqlCipherDatabase),
"megaphones" to DatabaseConfig(db = MegaphoneDatabase.getInstance(this).sqlCipherDatabase),
"localmetrics" to DatabaseConfig(db = LocalMetricsDatabase.getInstance(this).sqlCipherDatabase),
"logs" to DatabaseConfig(db = LogDatabase.getInstance(this).sqlCipherDatabase),
"jobmanager" to DatabaseConfig(db = { JobDatabase.getInstance(this).sqlCipherDatabase }),
"keyvalue" to DatabaseConfig(db = { KeyValueDatabase.getInstance(this).sqlCipherDatabase }),
"megaphones" to DatabaseConfig(db = { MegaphoneDatabase.getInstance(this).sqlCipherDatabase }),
"localmetrics" to DatabaseConfig(db = { LocalMetricsDatabase.getInstance(this).sqlCipherDatabase }),
"logs" to DatabaseConfig(db = { LogDatabase.getInstance(this).sqlCipherDatabase }),
),
linkedMapOf(
StorageServicePlugin.PATH to StorageServicePlugin()

Wyświetl plik

@ -20,10 +20,10 @@ class MainActivity : AppCompatActivity() {
Spinner.init(
application,
mapOf(
"Name" to "${Build.MODEL} (API ${Build.VERSION.SDK_INT})",
"Package" to packageName
"Name" to { "${Build.MODEL} (API ${Build.VERSION.SDK_INT})" },
"Package" to { packageName }
),
mapOf("main" to Spinner.DatabaseConfig(db = db)),
mapOf("main" to Spinner.DatabaseConfig(db = { db })),
emptyMap()
)
}

Wyświetl plik

@ -18,7 +18,7 @@ object Spinner {
private lateinit var server: SpinnerServer
fun init(application: Application, deviceInfo: Map<String, String>, databases: Map<String, DatabaseConfig>, plugins: Map<String, Plugin>) {
fun init(application: Application, deviceInfo: Map<String, () -> String>, databases: Map<String, DatabaseConfig>, plugins: Map<String, Plugin>) {
try {
server = SpinnerServer(application, deviceInfo, databases, plugins)
server.start()
@ -91,7 +91,7 @@ object Spinner {
}
data class DatabaseConfig(
val db: SupportSQLiteDatabase,
val db: () -> SupportSQLiteDatabase,
val columnTransformers: List<ColumnTransformer> = emptyList()
)
}

Wyświetl plik

@ -28,7 +28,7 @@ import kotlin.math.min
*/
internal class SpinnerServer(
private val application: Application,
deviceInfo: Map<String, String>,
deviceInfo: Map<String, () -> String>,
private val databases: Map<String, DatabaseConfig>,
private val plugins: Map<String, Plugin>
) : NanoHTTPD(5000) {
@ -37,8 +37,8 @@ internal class SpinnerServer(
private val TAG = Log.tag(SpinnerServer::class.java)
}
private val deviceInfo: Map<String, String> = deviceInfo.filterKeys { !it.startsWith(Spinner.KEY_PREFIX) }
private val environment: String = deviceInfo[Spinner.KEY_ENVIRONMENT] ?: "UNKNOWN"
private val deviceInfo: Map<String, () -> String> = deviceInfo.filterKeys { !it.startsWith(Spinner.KEY_PREFIX) }
private val environment: String = deviceInfo[Spinner.KEY_ENVIRONMENT]?.let { it() } ?: "UNKNOWN"
private val handlebars: Handlebars = Handlebars(AssetTemplateLoader(application)).apply {
registerHelper("eq", ConditionalHelpers.eq)
@ -61,8 +61,8 @@ internal class SpinnerServer(
return when {
session.method == Method.GET && session.uri == "/css/main.css" -> newFileResponse("css/main.css", "text/css")
session.method == Method.GET && session.uri == "/js/main.js" -> newFileResponse("js/main.js", "text/javascript")
session.method == Method.GET && session.uri == "/" -> getIndex(dbParam, dbConfig.db)
session.method == Method.GET && session.uri == "/browse" -> getBrowse(dbParam, dbConfig.db)
session.method == Method.GET && session.uri == "/" -> getIndex(dbParam, dbConfig.db())
session.method == Method.GET && session.uri == "/browse" -> getBrowse(dbParam, dbConfig.db())
session.method == Method.POST && session.uri == "/browse" -> postBrowse(dbParam, dbConfig, session)
session.method == Method.GET && session.uri == "/query" -> getQuery(dbParam)
session.method == Method.POST && session.uri == "/query" -> postQuery(dbParam, dbConfig, session)
@ -98,7 +98,7 @@ internal class SpinnerServer(
"overview",
OverviewPageModel(
environment = environment,
deviceInfo = deviceInfo,
deviceInfo = deviceInfo.resolve(),
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
@ -115,7 +115,7 @@ internal class SpinnerServer(
"browse",
BrowsePageModel(
environment = environment,
deviceInfo = deviceInfo,
deviceInfo = deviceInfo.resolve(),
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
@ -130,7 +130,7 @@ internal class SpinnerServer(
var pageIndex: Int = session.parameters["pageIndex"]?.get(0)?.toInt() ?: 0
val action: String? = session.parameters["action"]?.get(0)
val rowCount = dbConfig.db.getTableRowCount(table)
val rowCount = dbConfig.db().getTableRowCount(table)
val pageCount = ceil(rowCount.toFloat() / pageSize.toFloat()).toInt()
when (action) {
@ -141,17 +141,17 @@ internal class SpinnerServer(
}
val query = "select * from $table limit $pageSize offset ${pageSize * pageIndex}"
val queryResult = dbConfig.db.query(query).use { it.toQueryResult(columnTransformers = dbConfig.columnTransformers) }
val queryResult = dbConfig.db().query(query).use { it.toQueryResult(columnTransformers = dbConfig.columnTransformers) }
return renderTemplate(
"browse",
BrowsePageModel(
environment = environment,
deviceInfo = deviceInfo,
deviceInfo = deviceInfo.resolve(),
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
tableNames = dbConfig.db.getTableNames(),
tableNames = dbConfig.db().getTableNames(),
table = table,
queryResult = queryResult,
pagingData = PagingData(
@ -171,7 +171,7 @@ internal class SpinnerServer(
"query",
QueryPageModel(
environment = environment,
deviceInfo = deviceInfo,
deviceInfo = deviceInfo.resolve(),
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
@ -193,7 +193,7 @@ internal class SpinnerServer(
"recent",
RecentPageModel(
environment = environment,
deviceInfo = deviceInfo,
deviceInfo = deviceInfo.resolve(),
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
@ -212,12 +212,12 @@ internal class SpinnerServer(
"query",
QueryPageModel(
environment = environment,
deviceInfo = deviceInfo,
deviceInfo = deviceInfo.resolve(),
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
query = rawQuery,
queryResult = dbConfig.db.query(query).use { it.toQueryResult(queryStartTimeNanos = startTimeNanos, columnTransformers = dbConfig.columnTransformers) }
queryResult = dbConfig.db().query(query).use { it.toQueryResult(queryStartTimeNanos = startTimeNanos, columnTransformers = dbConfig.columnTransformers) }
)
)
}
@ -227,7 +227,7 @@ internal class SpinnerServer(
"plugin",
PluginPageModel(
environment = environment,
deviceInfo = deviceInfo,
deviceInfo = deviceInfo.resolve(),
database = dbName,
databases = databases.keys.toList(),
plugins = plugins.values.toList(),
@ -389,6 +389,10 @@ internal class SpinnerServer(
return params[name]
}
private fun Map<String, () -> String>.resolve(): Map<String, String> {
return this.mapValues { entry -> entry.value() }.toMap()
}
interface PrefixPageData {
val environment: String
val deviceInfo: Map<String, String>