main.app.cash.backfila.client.dynamodb.internal.DynamoDbBackend.kt Maven / Gradle / Ivy
package app.cash.backfila.client.dynamodb.internal
import app.cash.backfila.client.DeleteBy
import app.cash.backfila.client.Description
import app.cash.backfila.client.dynamodb.DynamoDbBackfill
import app.cash.backfila.client.dynamodb.ForDynamoDbBackend
import app.cash.backfila.client.parseDeleteByDate
import app.cash.backfila.client.spi.BackfilaParametersOperator
import app.cash.backfila.client.spi.BackfillBackend
import app.cash.backfila.client.spi.BackfillOperator
import app.cash.backfila.client.spi.BackfillRegistration
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper
import com.google.inject.Injector
import com.google.inject.TypeLiteral
import com.squareup.moshi.Types
import java.lang.reflect.ParameterizedType
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.reflect.KClass
import kotlin.reflect.full.findAnnotation
@Singleton
class DynamoDbBackend @Inject constructor(
private val injector: Injector,
@ForDynamoDbBackend private val backfills: MutableMap>>,
val dynamoDb: DynamoDBMapper,
val keyRangeCodec: DynamoDbKeyRangeCodec,
) : BackfillBackend {
/** Creates Backfill instances. Each backfill ID gets a new Backfill instance. */
private fun getBackfill(name: String): DynamoDbBackfill<*, *>? {
val backfillClass = backfills[name]
return if (backfillClass != null) {
injector.getInstance(backfillClass.java) as DynamoDbBackfill<*, *>
} else {
null
}
}
private fun createDynamoDbOperator(
backfill: DynamoDbBackfill,
) = DynamoDbBackfillOperator(
dynamoDb,
backfill,
BackfilaParametersOperator(parametersClass(backfill::class)),
keyRangeCodec,
)
override fun create(backfillName: String): BackfillOperator? {
val backfill = getBackfill(backfillName)
if (backfill != null) {
@Suppress("UNCHECKED_CAST") // We don't know the types statically, so fake them.
return createDynamoDbOperator(backfill as DynamoDbBackfill)
}
return null
}
override fun backfills(): Set {
return backfills.map {
BackfillRegistration(
name = it.key,
description = it.value.findAnnotation()?.text,
parametersClass = parametersClass(it.value as KClass>),
deleteBy = it.value.findAnnotation()?.parseDeleteByDate(),
)
}.toSet()
}
private fun parametersClass(backfillClass: KClass>): KClass {
// Like MyBackfill.
val thisType = TypeLiteral.get(backfillClass.java)
// Like DynamoDbBackfill.
val supertype = thisType.getSupertype(DynamoDbBackfill::class.java).type as ParameterizedType
// Like MyParameterClass
return (Types.getRawType(supertype.actualTypeArguments[1]) as Class).kotlin
}
}