Skip to content

Instantly share code, notes, and snippets.

@satoshun
Created November 30, 2017 00:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save satoshun/de789799874769f3a2ec5c7310916266 to your computer and use it in GitHub Desktop.
Save satoshun/de789799874769f3a2ec5c7310916266 to your computer and use it in GitHub Desktop.
class UserRepository4(
original: UserDao
) {
private val withCache = cache(original::getUser)
private val withCache2 = cache(original::getUser2)
fun getUser(id: Int, name: String): Single<User> = withCache(id, name)
}
interface UserDao {
fun getUser(id: Int, name: String): Single<User> {
return Single.just(User(id, name))
.delay(500, TimeUnit.MILLISECONDS)
}
fun getUser2(id: Int, name: String, password: String): Single<User> {
if (password.isEmpty()) return Single.error(Exception())
return Single.just(User(id, name))
.delay(500, TimeUnit.MILLISECONDS)
}
}
fun <V1, V2, R> cache(invoker: Function2<V1, V2, Single<R>>): Function2<V1, V2, Single<R>> {
return CacheDecorator2(invoker)
}
fun <V1, V2, V3, R> cache(invoker: Function3<V1, V2, V3, Single<R>>): Function3<V1, V2, V3, Single<R>> {
return CacheDecorator3(invoker)
}
private typealias Function2CacheKey<A, B> = Pair<A, B>
private class CacheDecorator2<in V1, in V2, R>(
private val invoker: Function2<V1, V2, Single<R>>
) : Function2<V1, V2, Single<R>> {
private val cache = HashMap<Function2CacheKey<V1, V2>, R>()
override fun invoke(p1: V1, p2: V2): Single<R> {
val key = Function2CacheKey(p1, p2)
cache[key]?.let { return Single.just(it) }
return invoker(p1, p2).doOnSuccess { cache[key] = it }
}
}
private typealias Function3CacheKey<A, B, C> = Triple<A, B, C>
private class CacheDecorator3<in V1, in V2, in V3, R>(
private val invoker: Function3<V1, V2, V3, Single<R>>
) : Function3<V1, V2, V3, Single<R>> {
private val cache = HashMap<Function3CacheKey<V1, V2, V3>, R>()
override fun invoke(p1: V1, p2: V2, p3: V3): Single<R> {
val key = Function3CacheKey(p1, p2, p3)
cache[key]?.let { return Single.just(it) }
return invoker(p1, p2, p3).doOnSuccess { cache[key] = it }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment