DataMigrationInitializer.kt
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.datastore.core
/**
* Returns an initializer function created from a list of DataMigrations.
*/
internal class DataMigrationInitializer<T>() {
companion object {
/**
* Creates an initializer from DataMigrations for use with DataStore.
*
* @param migrations A list of migrations that will be included in the initializer.
* @return The initializer which includes the data migrations returned from the factory
* functions.
*/
fun <T> getInitializer(migrations: List<DataMigration<T>>):
suspend (api: InitializerApi<T>) -> Unit = { api ->
runMigrations(migrations, api)
}
private suspend fun <T> runMigrations(
migrations: List<DataMigration<T>>,
api: InitializerApi<T>
) {
val cleanUps = mutableListOf<suspend () -> Unit>()
api.updateData { startingData ->
migrations.fold(startingData) { data, migration ->
if (migration.shouldMigrate(data)) {
cleanUps.add { migration.cleanUp() }
migration.migrate(data)
} else {
data
}
}
}
var cleanUpFailure: Throwable? = null
cleanUps.forEach { cleanUp ->
try {
cleanUp()
} catch (exception: Throwable) {
if (cleanUpFailure == null) {
cleanUpFailure = exception
} else {
cleanUpFailure!!.addSuppressed(exception)
}
}
}
// If we encountered a failure on cleanup, throw it.
cleanUpFailure?.let { throw it }
}
}
}