diff --git a/settings.gradle.kts b/settings.gradle.kts index be17148..139e338 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,6 +22,7 @@ include("ts-web:ts-web-coroutine") include("ts-database") include("ts-database:ts-mongodb") include("ts-database:ts-mongodb:ts-mongodb-spring") +include("ts-database:ts-redis") //include("web", "aop", "database", "utils", "utils:xml", "utils:async-http", "web:netty-web") //include("socket", "socket:socket-async") //include("AsyncSocket") diff --git a/ts-core/src/main/kotlin/cn/tursom/core/ScheduledExecutorPool.kt b/ts-core/src/main/kotlin/cn/tursom/core/ScheduledExecutorPool.kt new file mode 100644 index 0000000..be89dc0 --- /dev/null +++ b/ts-core/src/main/kotlin/cn/tursom/core/ScheduledExecutorPool.kt @@ -0,0 +1,41 @@ +package cn.tursom.core + +import java.util.concurrent.* +import java.util.concurrent.atomic.AtomicInteger + +class ScheduledExecutorPool( + private val threadCount: Int = Runtime.getRuntime().availableProcessors() * 2, + private val threadFactory: ThreadFactory = Executors.defaultThreadFactory(), +) { + private val scheduledExecutorQueue = ConcurrentLinkedDeque<Pair<Thread, ScheduledExecutorService>>() + private var initCount = AtomicInteger() + + init { + initOne() + } + + private fun initOne() { + if (initCount.incrementAndGet() < threadCount) { + val executor: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor { + threadFactory.newThread(it) + } + val countDownLatch = CountDownLatch(1) + executor.execute { + scheduledExecutorQueue.addFirst(Thread.currentThread() to executor) + countDownLatch.countDown() + } + countDownLatch.await(3, TimeUnit.SECONDS) + } else { + initCount.decrementAndGet() + } + } + + fun get(): Pair<Thread, ScheduledExecutorService> { + if (initCount.get() < threadCount) { + initOne() + } + val pair = scheduledExecutorQueue.poll() + scheduledExecutorQueue.add(pair) + return pair + } +} \ No newline at end of file diff --git a/ts-core/ts-log/build.gradle.kts b/ts-core/ts-log/build.gradle.kts index 8dd694c..379c050 100644 --- a/ts-core/ts-log/build.gradle.kts +++ b/ts-core/ts-log/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } dependencies { - implementation(project(":")) + implementation(project(":ts-core")) api(group = "org.slf4j", name = "slf4j-api", version = "1.7.29") api(group = "ch.qos.logback", name = "logback-core", version = "1.2.3") api(group = "ch.qos.logback", name = "logback-classic", version = "1.2.3") diff --git a/ts-core/ts-log/src/main/kotlin/cn/tursom/log/Slf4j.kt b/ts-core/ts-log/src/main/kotlin/cn/tursom/log/Slf4j.kt index e6bc0b6..1cec382 100644 --- a/ts-core/ts-log/src/main/kotlin/cn/tursom/log/Slf4j.kt +++ b/ts-core/ts-log/src/main/kotlin/cn/tursom/log/Slf4j.kt @@ -2,7 +2,7 @@ package cn.tursom.log import org.slf4j.Logger -interface Slf4j : TrySlf4j { +interface Slf4j : TrySlf4j, Logger { override val log: Logger override val logger get() = log override val sfl4j get() = log diff --git a/ts-core/ts-log/src/main/kotlin/cn/tursom/log/impl/Slf4jImpl.kt b/ts-core/ts-log/src/main/kotlin/cn/tursom/log/impl/Slf4jImpl.kt index f35ce1a..4bf8d70 100644 --- a/ts-core/ts-log/src/main/kotlin/cn/tursom/log/impl/Slf4jImpl.kt +++ b/ts-core/ts-log/src/main/kotlin/cn/tursom/log/impl/Slf4jImpl.kt @@ -1,13 +1,14 @@ package cn.tursom.log.impl +import cn.tursom.core.getCallerClassName import cn.tursom.log.Slf4j import org.slf4j.Logger import org.slf4j.LoggerFactory -import sun.reflect.Reflection import kotlin.reflect.KClass import kotlin.reflect.jvm.jvmName -open class Slf4jImpl( +open class Slf4jImpl constructor( + @field:Transient override val log: Logger, ) : Slf4j, Logger by log { constructor(name: String? = null) : this(LoggerFactory.getLogger(name ?: loggerName)) @@ -27,20 +28,8 @@ open class Slf4jImpl( companion object { private val thisClassName = listOf(this::class.java.name.dropLast(10), this::class.java.name) private val loggerName: String - get() = getCallerClassName() ?: throw UnsupportedOperationException() - - private fun getCallerClassName(): String? { - var clazz: Class<*>? - var callStackDepth = 1 - do { - @Suppress("DEPRECATION") - clazz = Reflection.getCallerClass(callStackDepth++) - if (clazz?.name !in thisClassName) { - break - } - } while (clazz != null) - return clazz?.name - } + get() = getCallerClassName(thisClassName)?.substringBefore('$') + ?: throw UnsupportedOperationException() inline fun getLogger(name: String): Logger = LoggerFactory.getLogger(name) diff --git a/ts-database/ts-mongodb/src/main/kotlin/cn/tursom/database/mongodb/MongoUtil.kt b/ts-database/ts-mongodb/src/main/kotlin/cn/tursom/database/mongodb/MongoUtil.kt index 19bc5e0..11cf2f5 100644 --- a/ts-database/ts-mongodb/src/main/kotlin/cn/tursom/database/mongodb/MongoUtil.kt +++ b/ts-database/ts-mongodb/src/main/kotlin/cn/tursom/database/mongodb/MongoUtil.kt @@ -79,7 +79,7 @@ object MongoUtil { private fun Map<*, *>.convert(): Document { val doc = Document() - forEach { any, u -> + forEach { (any, u) -> any ?: return@forEach doc[any.toString()] = u.convert() ?: return@forEach } diff --git a/ts-database/ts-redis/build.gradle.kts b/ts-database/ts-redis/build.gradle.kts new file mode 100644 index 0000000..5655897 --- /dev/null +++ b/ts-database/ts-redis/build.gradle.kts @@ -0,0 +1,34 @@ +plugins { + kotlin("jvm") + `maven-publish` +} + +dependencies { + api(project(":")) + implementation(project(":ts-core")) + implementation(project(":ts-core:ts-log")) + api(group = "redis.clients", name = "jedis", version = "3.3.0") +} + +@kotlin.Suppress("UNCHECKED_CAST") +(rootProject.ext["excludeTest"] as (Project, TaskContainer) -> Unit)(project, tasks) + +tasks.register("install") { + finalizedBy(tasks["publishToMavenLocal"]) +} + +publishing { + publications { + create<MavenPublication>("maven") { + groupId = project.group.toString() + artifactId = project.name + version = project.version.toString() + + from(components["java"]) + try { + artifact(tasks["sourcesJar"]) + } catch (e: Exception) { + } + } + } +} diff --git a/ts-database/ts-redis/src/main/kotlin/cn/tursom/database/redis/AsyncJedis.kt b/ts-database/ts-redis/src/main/kotlin/cn/tursom/database/redis/AsyncJedis.kt new file mode 100644 index 0000000..06e7ce4 --- /dev/null +++ b/ts-database/ts-redis/src/main/kotlin/cn/tursom/database/redis/AsyncJedis.kt @@ -0,0 +1,1695 @@ +package cn.tursom.database.redis + +import cn.tursom.core.ScheduledExecutorPool +import cn.tursom.core.uncheckedCast +import cn.tursom.log.Slf4j +import cn.tursom.log.impl.Slf4jImpl +import redis.clients.jedis.* +import redis.clients.jedis.commands.ProtocolCommand +import redis.clients.jedis.params.GeoRadiusParam +import redis.clients.jedis.params.SetParams +import redis.clients.jedis.params.ZAddParams +import redis.clients.jedis.params.ZIncrByParams +import java.io.Closeable +import java.util.concurrent.ConcurrentLinkedDeque +import java.util.concurrent.ScheduledExecutorService +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.locks.ReentrantLock +import kotlin.concurrent.withLock +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine + +/** + * 将Jedis的pipeline封装成协程操作的类 + * Jedis的pipeline可以在巨量(十万以上)并发时提供极高(6至7倍)的吞吐量,这对提高系统并发非常有帮助 + */ +@Suppress("unused", "SpellCheckingInspection", "MemberVisibilityCanBePrivate", "CanBeParameter") +class AsyncJedis( + val jedisPool: JedisPool, + @Volatile + var syncDelay: Long = SYNC_DELAY, + var maxDelayCount: Int = MAX_DELAY_COUNT, + val syncCycle: Long = 1000, +) : Closeable { + companion object : Slf4j by Slf4jImpl() { + const val SYNC_DELAY = 0L + const val MAX_DELAY_COUNT = 1000 + + fun Pipeline.getPipelinedResponseLength(): Int = getPipelinedResponseLength.invoke(this).uncheckedCast() + + private val threadId = AtomicInteger(0) + private val threadPool = ScheduledExecutorPool { + val thread = Thread(it) + thread.name = "AsyncJedisWorker-${threadId.incrementAndGet()}" + thread.isDaemon = true + thread + } + private val responseSet = Response::class.java.getDeclaredField("set").apply { + isAccessible = true + } + private val getPipelinedResponseLength = + Queable::class.java.getDeclaredMethod("getPipelinedResponseLength").apply { + isAccessible = true + } + private val Response<*>.set: Boolean get() = responseSet[this].uncheckedCast() + private val pipelineClientField = MultiKeyPipelineBase::class.java.getDeclaredField("client").apply { + isAccessible = true + } + private val Pipeline.client get() = pipelineClientField.get(this).uncheckedCast<Client>() + } + + private val syncThread: Thread + private val syncExecutor: ScheduledExecutorService + private val workExecutor: ScheduledExecutorService + private val taskLock = ReentrantLock() + private val pipelines = ConcurrentLinkedDeque<Pipeline>() + private val tasks = ConcurrentLinkedDeque<() -> Boolean>() + private val handleRequest = AtomicInteger(0) + + init { + val workThreadAndExecutor = threadPool.get() + syncThread = workThreadAndExecutor.first + syncExecutor = workThreadAndExecutor.second + workExecutor = syncExecutor + //workExecutor = threadPool.get().second + pipelines.add(jedisPool.resource.pipelined()) + } + + private val updateSyncDelayFuture = + syncExecutor.scheduleWithFixedDelay(::updateSyncDelay, 100, 100, TimeUnit.MILLISECONDS) + private val scheduledFuture = + syncExecutor.scheduleWithFixedDelay(::sync, syncCycle, syncCycle, TimeUnit.MILLISECONDS) + private val syncing = AtomicBoolean(false) + + override fun close() { + syncNow() + scheduledFuture.cancel(false) + updateSyncDelayFuture.cancel(true) + } + + /** + * 通知AsyncJedis进行管道数据刷新同步,非阻塞 + */ + fun sync() { + // 判断是否有正在运行中的任务 + if (tasks.isEmpty() && pipelines.none { pipeline -> pipeline.getPipelinedResponseLength() != 0 }) { + if (Thread.currentThread() == syncThread) { + syncing.set(false) + } + return + } + // 判断当前线程是否是工作线程 + // 管道的同步是线程不安全的代码,只能在单线程中运行 + if (Thread.currentThread() != syncThread) { + // 判断是否已经有同步任务存在 + if (syncing.compareAndSet(false, true)) { + // 提交同步请求 + syncExecutor.execute(::sync) + } + return + } + // 计算正在提交的任务数是否超过缓冲上限 + if (syncDelay != 0L && pipelines.sumOf { pipeline -> pipeline.getPipelinedResponseLength() } < maxDelayCount) { + // 没有超过缓冲上限,则延迟后进行刷新 + syncExecutor.schedule(::syncNow, syncDelay, TimeUnit.SECONDS) + } else { + // 已经超过缓冲上限,马上进行刷新 + syncNow() + } + } + + /** + * 立即进行数据同步操作 + * 线程不安全,只能在工作线程中运行 + */ + private fun syncNow() { + trace("sync now ${Thread.currentThread().name} ${syncThread.name} ${Thread.currentThread() == syncThread} ${pipelines.size}") + // 如果当前线程不是工作线程,则向工作线程提交任务 + if (Thread.currentThread() != syncThread) { + trace("current thread is not work thread") + syncExecutor.execute(::syncNow) + return + } + taskLock.withLock { + debug("sync get lock ${Thread.currentThread().name} ${syncThread.name} ${Thread.currentThread() == syncThread} ${pipelines.size}") + try { + val resource = jedisPool.resource + pipelines.addFirst(resource.pipelined()) + resource.close() + val iterator = pipelines.iterator() + iterator.next() + // 遍历管道列表,同步数据 + iterator.forEach { pipeline -> + debug( + "AsyncJedis command syncing, pipeline remain {}, tasks size: {} ", + pipeline.getPipelinedResponseLength(), + tasks.size + ) + pipeline.sync() + debug("pipeline sync finished, remain {}", pipeline.getPipelinedResponseLength()) + // 如果所有数据皆已同步 + if (pipeline.getPipelinedResponseLength() == 0) { + iterator.remove() + pipeline.close() + } + } + } catch (e: Exception) { + error("an exception caused on pipeline sync", e) + } + } + //workExecutor.execute { + // 遍历任务列表,清除已完成的任务 + val notHandledTasks = ArrayList<() -> Boolean>() + var task = tasks.poll() + while (task != null) { + debug("task {} handle", task) + if (!task()) { + notHandledTasks.add(task) + } + task = tasks.poll() + } + tasks.addAll(notHandledTasks) + + debug("sync finished") + syncing.set(false) + //} + } + + private var lowerTime = 0 + private fun updateSyncDelay() { + val handleRequest = handleRequest.getAndSet(0) + if (handleRequest > 10000) { + syncDelay = 5 + lowerTime = 0 + } else { + if (++lowerTime > 10) { + syncDelay = 0 + } + } + //println("${ThreadLocalSimpleDateFormat.cn.format(System.currentTimeMillis())} handle request per second: $handleRequest, sync delay: $syncDelay") + } + + suspend operator fun <T> invoke(action: (Pipeline) -> Response<T>): T { + return suspendCoroutine { cont -> + taskLock.withLock { + val pipeline = pipelines.first + val response = action(pipeline) + tasks.add { + if (response.set) { + handleRequest.incrementAndGet() + cont.resume(response.get()) + true + } else { + false + } + } + sync() + } + } + } + + operator fun <T> invoke(action: (Pipeline) -> Response<T>, onComplete: (T) -> Unit) { + taskLock.withLock { + val pipeline = pipelines.first + val response = action(pipeline) + tasks.add { + if (response.set) { + handleRequest.incrementAndGet() + onComplete(response.get()) + true + } else { + false + } + } + sync() + } + } + + suspend fun append(key: String, value: String): Long? = invoke { + it.append(key, value) + } + + suspend fun append(key: ByteArray, value: ByteArray): Long? = invoke { + it.append(key, value) + } + + suspend fun blpop(key: String): List<String>? = invoke { + it.blpop(key) + } + + suspend fun brpop(key: String): List<String>? = invoke { + it.blpop(key) + } + + suspend fun blpop(key: ByteArray): List<ByteArray>? = invoke { + it.blpop(key) + } + + suspend fun brpop(key: ByteArray): List<ByteArray>? = invoke { + it.blpop(key) + } + + suspend fun decr(key: String): Long? = invoke { + it.decr(key) + } + + suspend fun decr(key: ByteArray): Long? = invoke { + it.decr(key) + } + + suspend fun decrBy(key: String, decrement: Long): Long? = invoke { + it.decrBy(key, decrement) + } + + suspend fun decrBy(key: ByteArray, decrement: Long): Long? = invoke { + it.decrBy(key, decrement) + } + + suspend fun del(key: String): Long? = invoke { + it.del(key) + } + + suspend fun del(key: ByteArray): Long? = invoke { + it.del(key) + } + + suspend fun unlink(key: String): Long? = invoke { + it.unlink(key) + } + + suspend fun unlink(key: ByteArray): Long? = invoke { + it.unlink(key) + } + + suspend fun echo(string: String): String? = invoke { + it.echo(string) + } + + suspend fun echo(string: ByteArray): ByteArray? = invoke { + it.echo(string) + } + + suspend fun exists(key: String): Boolean? = invoke { + it.exists(key) + } + + suspend fun exists(key: ByteArray): Boolean? = invoke { + it.exists(key) + } + + suspend fun expire(key: String, seconds: Int): Long? = invoke { + it.expire(key, seconds) + } + + suspend fun expire(key: ByteArray, seconds: Int): Long? = invoke { + it.expire(key, seconds) + } + + suspend fun expireAt(key: String, unixTime: Long): Long? = invoke { + it.expireAt(key, unixTime) + } + + suspend fun expireAt(key: ByteArray, unixTime: Long): Long? = invoke { + it.expireAt(key, unixTime) + } + + suspend fun get(key: String): String? = invoke { + it.get(key) + } + + suspend fun get(key: ByteArray): ByteArray? = invoke { + it.get(key) + } + + suspend fun getbit(key: String, offset: Long): Boolean? = invoke { + it.getbit(key, offset) + } + + suspend fun getbit(key: ByteArray, offset: Long): Boolean? = invoke { + it.getbit(key, offset) + } + + suspend fun bitpos(key: String, value: Boolean): Long? = invoke { + it.bitpos(key, value) + } + + suspend fun bitpos(key: String, value: Boolean, params: BitPosParams): Long? = invoke { + it.bitpos(key, value, params) + } + + suspend fun bitpos(key: ByteArray, value: Boolean): Long? = invoke { + it.bitpos(key, value) + } + + suspend fun bitpos(key: ByteArray, value: Boolean, params: BitPosParams): Long? = invoke { + it.bitpos(key, value, params) + } + + suspend fun getrange(key: String, startOffset: Long, endOffset: Long): String? = invoke { + it.getrange(key, startOffset, endOffset) + } + + suspend fun getSet(key: String, value: String): String? = invoke { + it.getSet(key, value) + } + + suspend fun getSet(key: ByteArray, value: ByteArray): ByteArray? = invoke { + it.getSet(key, value) + } + + suspend fun getrange(key: ByteArray, startOffset: Long, endOffset: Long): ByteArray? = invoke { + it.getrange(key, startOffset, endOffset) + } + + suspend fun hdel(key: String, vararg field: String): Long? = invoke { + it.hdel(key, *field) + } + + suspend fun hdel(key: ByteArray, vararg field: ByteArray): Long? = invoke { + it.hdel(key, *field) + } + + suspend fun hexists(key: String, field: String): Boolean? = invoke { + it.hexists(key, field) + } + + suspend fun hexists(key: ByteArray, field: ByteArray): Boolean? = invoke { + it.hexists(key, field) + } + + suspend fun hget(key: String, field: String): String? = invoke { + it.hget(key, field) + } + + suspend fun hget(key: ByteArray, field: ByteArray): ByteArray? = invoke { + it.hget(key, field) + } + + suspend fun hgetAll(key: String): Map<String, String>? = invoke { + it.hgetAll(key) + } + + suspend fun hgetAll(key: ByteArray): Map<ByteArray, ByteArray>? = invoke { + it.hgetAll(key) + } + + suspend fun hincrBy(key: String, field: String, value: Long): Long? = invoke { + it.hincrBy(key, field, value) + } + + suspend fun hincrBy(key: ByteArray, field: ByteArray, value: Long): Long? = invoke { + it.hincrBy(key, field, value) + } + + suspend fun hkeys(key: String): Set<String>? = invoke { + it.hkeys(key) + } + + suspend fun hkeys(key: ByteArray): Set<ByteArray>? = invoke { + it.hkeys(key) + } + + suspend fun hlen(key: String): Long? = invoke { + it.hlen(key) + } + + suspend fun hlen(key: ByteArray): Long? = invoke { + it.hlen(key) + } + + suspend fun hmget(key: String, vararg fields: String): List<String>? = invoke { + it.hmget(key, *fields) + } + + suspend fun hmget(key: ByteArray, vararg fields: ByteArray): List<ByteArray>? = invoke { + it.hmget(key, *fields) + } + + suspend fun hmset(key: String, hash: Map<String, String>): String? = invoke { + it.hmset(key, hash) + } + + suspend fun hmset(key: ByteArray, hash: Map<ByteArray, ByteArray>): String? = invoke { + it.hmset(key, hash) + } + + suspend fun hset(key: String, field: String, value: String): Long? = invoke { + it.hset(key, field, value) + } + + suspend fun hset(key: ByteArray, field: ByteArray, value: ByteArray): Long? = invoke { + it.hset(key, field, value) + } + + suspend fun hset(key: String, hash: Map<String, String>): Long? = invoke { + it.hset(key, hash) + } + + suspend fun hset(key: ByteArray, hash: Map<ByteArray, ByteArray>): Long? = invoke { + it.hset(key, hash) + } + + suspend fun hsetnx(key: String, field: String, value: String): Long? = invoke { + it.hsetnx(key, field, value) + } + + suspend fun hsetnx(key: ByteArray, field: ByteArray, value: ByteArray): Long? = invoke { + it.hsetnx(key, field, value) + } + + suspend fun hvals(key: String): List<String>? = invoke { + it.hvals(key) + } + + suspend fun hvals(key: ByteArray): List<ByteArray>? = invoke { + it.hvals(key) + } + + suspend fun incr(key: String): Long? = invoke { + it.incr(key) + } + + suspend fun incr(key: ByteArray): Long? = invoke { + it.incr(key) + } + + suspend fun incrBy(key: String, increment: Long): Long? = invoke { + it.incrBy(key, increment) + } + + suspend fun incrBy(key: ByteArray, increment: Long): Long? = invoke { + it.incrBy(key, increment) + } + + suspend fun lindex(key: String, index: Long): String? = invoke { + it.lindex(key, index) + } + + suspend fun lindex(key: ByteArray, index: Long): ByteArray? = invoke { + it.lindex(key, index) + } + + suspend fun linsert(key: String, where: ListPosition, pivot: String, value: String): Long? = invoke { + it.linsert(key, where, pivot, value) + } + + suspend fun linsert(key: ByteArray, where: ListPosition, pivot: ByteArray, value: ByteArray): Long? = invoke { + it.linsert(key, where, pivot, value) + } + + suspend fun llen(key: String): Long? = invoke { + it.llen(key) + } + + suspend fun llen(key: ByteArray): Long? = invoke { + it.llen(key) + } + + suspend fun lpop(key: String): String? = invoke { + it.lpop(key) + } + + suspend fun lpop(key: ByteArray): ByteArray? = invoke { + it.lpop(key) + } + + suspend fun lpush(key: String, vararg string: String): Long? = invoke { + it.lpush(key, *string) + } + + suspend fun lpush(key: ByteArray, vararg string: ByteArray): Long? = invoke { + it.lpush(key, *string) + } + + suspend fun lpushx(key: String, vararg string: String): Long? = invoke { + it.lpushx(key, *string) + } + + suspend fun lpushx(key: ByteArray, vararg bytes: ByteArray): Long? = invoke { + it.lpushx(key, *bytes) + } + + suspend fun lrange(key: String, start: Long, stop: Long): List<String>? = invoke { + it.lrange(key, start, stop) + } + + suspend fun lrange(key: ByteArray, start: Long, stop: Long): List<ByteArray>? = invoke { + it.lrange(key, start, stop) + } + + suspend fun lrem(key: String, count: Long, value: String): Long? = invoke { + it.lrem(key, count, value) + } + + suspend fun lrem(key: ByteArray, count: Long, value: ByteArray): Long? = invoke { + it.lrem(key, count, value) + } + + suspend fun lset(key: String, index: Long, value: String): String? = invoke { + it.lset(key, index, value) + } + + suspend fun lset(key: ByteArray, index: Long, value: ByteArray): String? = invoke { + it.lset(key, index, value) + } + + suspend fun ltrim(key: String, start: Long, stop: Long): String? = invoke { + it.ltrim(key, start, stop) + } + + suspend fun ltrim(key: ByteArray, start: Long, stop: Long): String? = invoke { + it.ltrim(key, start, stop) + } + + suspend fun move(key: String, dbIndex: Int): Long? = invoke { + it.move(key, dbIndex) + } + + suspend fun move(key: ByteArray, dbIndex: Int): Long? = invoke { + it.move(key, dbIndex) + } + + suspend fun persist(key: String): Long? = invoke { + it.persist(key) + } + + suspend fun persist(key: ByteArray): Long? = invoke { + it.persist(key) + } + + suspend fun rpop(key: String): String? = invoke { + it.rpop(key) + } + + suspend fun rpop(key: ByteArray): ByteArray? = invoke { + it.rpop(key) + } + + suspend fun rpush(key: String, vararg string: String): Long? = invoke { + it.rpush(key, *string) + } + + suspend fun rpush(key: ByteArray, vararg string: ByteArray): Long? = invoke { + it.rpush(key, *string) + } + + suspend fun rpushx(key: String, vararg string: String): Long? = invoke { + it.rpushx(key, *string) + } + + suspend fun rpushx(key: ByteArray, vararg string: ByteArray): Long? = invoke { + it.rpushx(key, *string) + } + + suspend fun sadd(key: String, vararg member: String): Long? = invoke { + it.sadd(key, *member) + } + + suspend fun sadd(key: ByteArray, vararg member: ByteArray): Long? = invoke { + it.sadd(key, *member) + } + + suspend fun scard(key: String): Long? = invoke { + it.scard(key) + } + + suspend fun scard(key: ByteArray): Long? = invoke { + it.scard(key) + } + + suspend fun set(key: String, value: String): String? = invoke { + it.set(key, value) + } + + suspend fun set(key: ByteArray, value: ByteArray): String? = invoke { + it.set(key, value) + } + + suspend fun set(key: String, value: String, params: SetParams): String? = invoke { + it.set(key, value, params) + } + + suspend fun set(key: ByteArray, value: ByteArray, params: SetParams): String? = invoke { + it.set(key, value, params) + } + + suspend fun setbit(key: String, offset: Long, value: Boolean): Boolean? = invoke { + it.setbit(key, offset, value) + } + + suspend fun setbit(key: ByteArray, offset: Long, value: ByteArray): Boolean? = invoke { + it.setbit(key, offset, value) + } + + suspend fun setex(key: String, seconds: Int, value: String): String? = invoke { + it.setex(key, seconds, value) + } + + suspend fun setex(key: ByteArray, seconds: Int, value: ByteArray): String? = invoke { + it.setex(key, seconds, value) + } + + suspend fun setnx(key: String, value: String): Long? = invoke { + it.setnx(key, value) + } + + suspend fun setnx(key: ByteArray, value: ByteArray): Long? = invoke { + it.setnx(key, value) + } + + suspend fun setrange(key: String, offset: Long, value: String): Long? = invoke { + it.setrange(key, offset, value) + } + + suspend fun setrange(key: ByteArray, offset: Long, value: ByteArray): Long? = invoke { + it.setrange(key, offset, value) + } + + suspend fun sismember(key: String, member: String): Boolean? = invoke { + it.sismember(key, member) + } + + suspend fun sismember(key: ByteArray, member: ByteArray): Boolean? = invoke { + it.sismember(key, member) + } + + suspend fun smembers(key: String): Set<String>? = invoke { + it.smembers(key) + } + + suspend fun smembers(key: ByteArray): Set<ByteArray>? = invoke { + it.smembers(key) + } + + suspend fun sort(key: String): List<String>? = invoke { + it.sort(key) + } + + suspend fun sort(key: ByteArray): List<ByteArray>? = invoke { + it.sort(key) + } + + suspend fun sort(key: String, sortingParameters: SortingParams): List<String>? = invoke { + it.sort(key, sortingParameters) + } + + suspend fun sort(key: ByteArray, sortingParameters: SortingParams): List<ByteArray>? = invoke { + it.sort(key, sortingParameters) + } + + suspend fun spop(key: String): String? = invoke { + it.spop(key) + } + + suspend fun spop(key: String, count: Long): Set<String>? = invoke { + it.spop(key, count) + } + + suspend fun spop(key: ByteArray): ByteArray? = invoke { + it.spop(key) + } + + suspend fun spop(key: ByteArray, count: Long): Set<ByteArray>? = invoke { + it.spop(key, count) + } + + suspend fun srandmember(key: String): String? = invoke { + it.srandmember(key) + } + + suspend fun srandmember(key: String, count: Int): List<String>? = invoke { + it.srandmember(key, count) + } + + suspend fun srandmember(key: ByteArray): ByteArray? = invoke { + it.srandmember(key) + } + + suspend fun srandmember(key: ByteArray, count: Int): List<ByteArray>? = invoke { + it.srandmember(key, count) + } + + suspend fun srem(key: String, vararg member: String): Long? = invoke { + it.srem(key, *member) + } + + suspend fun srem(key: ByteArray, vararg member: ByteArray): Long? = invoke { + it.srem(key, *member) + } + + suspend fun strlen(key: String): Long? = invoke { + it.strlen(key) + } + + suspend fun strlen(key: ByteArray): Long? = invoke { + it.strlen(key) + } + + suspend fun substr(key: String, start: Int, end: Int): String? = invoke { + it.substr(key, start, end) + } + + suspend fun substr(key: ByteArray, start: Int, end: Int): String? = invoke { + it.substr(key, start, end) + } + + suspend fun touch(key: String): Long? = invoke { + it.touch(key) + } + + suspend fun touch(key: ByteArray): Long? = invoke { + it.touch(key) + } + + suspend fun ttl(key: String): Long? = invoke { + it.ttl(key) + } + + suspend fun ttl(key: ByteArray): Long? = invoke { + it.ttl(key) + } + + suspend fun type(key: String): String? = invoke { + it.type(key) + } + + suspend fun type(key: ByteArray): String? = invoke { + it.type(key) + } + + suspend fun zadd(key: String, score: Double, member: String): Long? = invoke { + it.zadd(key, score, member) + } + + suspend fun zadd(key: String, score: Double, member: String, params: ZAddParams): Long? = invoke { + it.zadd(key, score, member, params) + } + + suspend fun zadd(key: String, scoreMembers: Map<String, Double>): Long? = invoke { + it.zadd(key, scoreMembers) + } + + suspend fun zadd(key: String, scoreMembers: Map<String, Double>, params: ZAddParams): Long? = invoke { + it.zadd(key, scoreMembers, params) + } + + suspend fun zadd(key: ByteArray, score: Double, member: ByteArray): Long? = invoke { + it.zadd(key, score, member) + } + + suspend fun zadd(key: ByteArray, score: Double, member: ByteArray, params: ZAddParams): Long? = invoke { + it.zadd(key, score, member, params) + } + + suspend fun zadd(key: ByteArray, scoreMembers: Map<ByteArray, Double>): Long? = invoke { + it.zadd(key, scoreMembers) + } + + suspend fun zadd(key: ByteArray, scoreMembers: Map<ByteArray, Double>, params: ZAddParams): Long? = invoke { + it.zadd(key, scoreMembers, params) + } + + suspend fun zcard(key: String): Long? = invoke { + it.zcard(key) + } + + suspend fun zcard(key: ByteArray): Long? = invoke { + it.zcard(key) + } + + suspend fun zcount(key: String, min: Double, max: Double): Long? = invoke { + it.zcount(key, min, max) + } + + suspend fun zcount(key: String, min: String, max: String): Long? = invoke { + it.zcount(key, min, max) + } + + suspend fun zcount(key: ByteArray, min: Double, max: Double): Long? = invoke { + it.zcount(key, min, max) + } + + suspend fun zcount(key: ByteArray, min: ByteArray, max: ByteArray): Long? = invoke { + it.zcount(key, min, max) + } + + suspend fun zincrby(key: String, increment: Double, member: String): Double? = invoke { + it.zincrby(key, increment, member) + } + + suspend fun zincrby(key: String, increment: Double, member: String, params: ZIncrByParams): Double? = invoke { + it.zincrby(key, increment, member, params) + } + + suspend fun zincrby(key: ByteArray, increment: Double, member: ByteArray): Double? = invoke { + it.zincrby(key, increment, member) + } + + suspend fun zincrby(key: ByteArray, increment: Double, member: ByteArray, params: ZIncrByParams): Double? = invoke { + it.zincrby(key, increment, member, params) + } + + suspend fun zrange(key: String, start: Long, stop: Long): Set<String>? = invoke { + it.zrange(key, start, stop) + } + + suspend fun zrange(key: ByteArray, start: Long, stop: Long): Set<ByteArray>? = invoke { + it.zrange(key, start, stop) + } + + suspend fun zrangeByScore(key: String, min: Double, max: Double): Set<String>? = invoke { + it.zrangeByScore(key, min, max) + } + + suspend fun zrangeByScore(key: ByteArray, min: Double, max: Double): Set<ByteArray>? = invoke { + it.zrangeByScore(key, min, max) + } + + suspend fun zrangeByScore(key: String, min: String, max: String): Set<String>? = invoke { + it.zrangeByScore(key, min, max) + } + + suspend fun zrangeByScore(key: ByteArray, min: ByteArray, max: ByteArray): Set<ByteArray>? = invoke { + it.zrangeByScore(key, min, max) + } + + suspend fun zrangeByScore( + key: String, min: Double, max: Double, offset: Int, + count: Int, + ): Set<String>? = invoke { + it.zrangeByScore(key, min, max, offset, count) + } + + suspend fun zrangeByScore( + key: String, min: String, max: String, offset: Int, + count: Int, + ): Set<String>? = invoke { + it.zrangeByScore(key, min, max, offset, count) + } + + suspend fun zrangeByScore( + key: ByteArray, min: Double, max: Double, offset: Int, + count: Int, + ): Set<ByteArray>? = invoke { + it.zrangeByScore(key, min, max, offset, count) + } + + suspend fun zrangeByScore( + key: ByteArray, min: ByteArray, max: ByteArray, offset: Int, + count: Int, + ): Set<ByteArray>? = invoke { + it.zrangeByScore(key, min, max, offset, count) + } + + suspend fun zrangeByScoreWithScores(key: String, min: Double, max: Double): Set<Tuple>? = invoke { + it.zrangeByScoreWithScores(key, min, max) + } + + suspend fun zrangeByScoreWithScores(key: String, min: String, max: String): Set<Tuple>? = invoke { + it.zrangeByScoreWithScores(key, min, max) + } + + suspend fun zrangeByScoreWithScores(key: ByteArray, min: Double, max: Double): Set<Tuple>? = invoke { + it.zrangeByScoreWithScores(key, min, max) + } + + suspend fun zrangeByScoreWithScores(key: ByteArray, min: ByteArray, max: ByteArray): Set<Tuple>? = invoke { + it.zrangeByScoreWithScores(key, min, max) + } + + suspend fun zrangeByScoreWithScores( + key: String, min: Double, max: Double, + offset: Int, count: Int, + ): Set<Tuple>? = invoke { + it.zrangeByScoreWithScores(key, min, max, offset, count) + } + + suspend fun zrangeByScoreWithScores( + key: String, min: String, max: String, + offset: Int, count: Int, + ): Set<Tuple>? = invoke { + it.zrangeByScoreWithScores(key, min, max, offset, count) + } + + suspend fun zrangeByScoreWithScores( + key: ByteArray, min: Double, max: Double, + offset: Int, count: Int, + ): Set<Tuple>? = invoke { + it.zrangeByScoreWithScores(key, min, max, offset, count) + } + + suspend fun zrangeByScoreWithScores( + key: ByteArray, min: ByteArray, max: ByteArray, + offset: Int, count: Int, + ): Set<Tuple>? = invoke { + it.zrangeByScoreWithScores(key, min, max, offset, count) + } + + suspend fun zrevrangeByScore(key: String, max: Double, min: Double): Set<String>? = invoke { + it.zrevrangeByScore(key, max, min) + } + + suspend fun zrevrangeByScore(key: ByteArray, max: Double, min: Double): Set<ByteArray>? = invoke { + it.zrevrangeByScore(key, max, min) + } + + suspend fun zrevrangeByScore(key: String, max: String, min: String): Set<String>? = invoke { + it.zrevrangeByScore(key, max, min) + } + + suspend fun zrevrangeByScore(key: ByteArray, max: ByteArray, min: ByteArray): Set<ByteArray>? = invoke { + it.zrevrangeByScore(key, max, min) + } + + suspend fun zrevrangeByScore( + key: String, max: Double, min: Double, offset: Int, + count: Int, + ): Set<String>? = invoke { + it.zrevrangeByScore(key, max, min, offset, count) + } + + suspend fun zrevrangeByScore( + key: String, max: String, min: String, offset: Int, + count: Int, + ): Set<String>? = invoke { + it.zrevrangeByScore(key, max, min, offset, count) + } + + suspend fun zrevrangeByScore( + key: ByteArray, max: Double, min: Double, offset: Int, + count: Int, + ): Set<ByteArray>? = invoke { + it.zrevrangeByScore(key, max, min, offset, count) + } + + suspend fun zrevrangeByScore( + key: ByteArray, max: ByteArray, min: ByteArray, offset: Int, + count: Int, + ): Set<ByteArray>? = invoke { + it.zrevrangeByScore(key, max, min, offset, count) + } + + suspend fun zrevrangeByScoreWithScores(key: String, max: Double, min: Double): Set<Tuple>? = invoke { + it.zrevrangeByScoreWithScores(key, max, min) + } + + suspend fun zrevrangeByScoreWithScores(key: String, max: String, min: String): Set<Tuple>? = invoke { + it.zrevrangeByScoreWithScores(key, max, min) + } + + suspend fun zrevrangeByScoreWithScores(key: ByteArray, max: Double, min: Double): Set<Tuple>? = invoke { + it.zrevrangeByScoreWithScores(key, max, min) + } + + suspend fun zrevrangeByScoreWithScores(key: ByteArray, max: ByteArray, min: ByteArray): Set<Tuple>? = invoke { + it.zrevrangeByScoreWithScores(key, max, min) + } + + suspend fun zrevrangeByScoreWithScores( + key: String, max: Double, min: Double, + offset: Int, count: Int, + ): Set<Tuple>? = invoke { + it.zrevrangeByScoreWithScores(key, max, min, offset, count) + } + + suspend fun zrevrangeByScoreWithScores( + key: String, max: String, min: String, + offset: Int, count: Int, + ): Set<Tuple>? = invoke { + it.zrevrangeByScoreWithScores(key, max, min, offset, count) + } + + suspend fun zrevrangeByScoreWithScores( + key: ByteArray, max: Double, min: Double, + offset: Int, count: Int, + ): Set<Tuple>? = invoke { + it.zrevrangeByScoreWithScores(key, max, min, offset, count) + } + + suspend fun zrevrangeByScoreWithScores( + key: ByteArray, max: ByteArray, min: ByteArray, + offset: Int, count: Int, + ): Set<Tuple>? = invoke { + it.zrevrangeByScoreWithScores(key, max, min, offset, count) + } + + suspend fun zrangeWithScores(key: String, start: Long, stop: Long): Set<Tuple>? = invoke { + it.zrangeWithScores(key, start, stop) + } + + suspend fun zrangeWithScores(key: ByteArray, start: Long, stop: Long): Set<Tuple>? = invoke { + it.zrangeWithScores(key, start, stop) + } + + suspend fun zrank(key: String, member: String): Long? = invoke { + it.zrank(key, member) + } + + suspend fun zrank(key: ByteArray, member: ByteArray): Long? = invoke { + it.zrank(key, member) + } + + suspend fun zrem(key: String, vararg members: String): Long? = invoke { + it.zrem(key, *members) + } + + suspend fun zrem(key: ByteArray, vararg members: ByteArray): Long? = invoke { + it.zrem(key, *members) + } + + suspend fun zremrangeByRank(key: String, start: Long, stop: Long): Long? = invoke { + it.zremrangeByRank(key, start, stop) + } + + suspend fun zremrangeByRank(key: ByteArray, start: Long, stop: Long): Long? = invoke { + it.zremrangeByRank(key, start, stop) + } + + suspend fun zremrangeByScore(key: String, min: Double, max: Double): Long? = invoke { + it.zremrangeByScore(key, min, max) + } + + suspend fun zremrangeByScore(key: String, min: String, max: String): Long? = invoke { + it.zremrangeByScore(key, min, max) + } + + suspend fun zremrangeByScore(key: ByteArray, min: Double, max: Double): Long? = invoke { + it.zremrangeByScore(key, min, max) + } + + suspend fun zremrangeByScore(key: ByteArray, min: ByteArray, max: ByteArray): Long? = invoke { + it.zremrangeByScore(key, min, max) + } + + suspend fun zrevrange(key: String, start: Long, stop: Long): Set<String>? = invoke { + it.zrevrange(key, start, stop) + } + + suspend fun zrevrange(key: ByteArray, start: Long, stop: Long): Set<ByteArray>? = invoke { + it.zrevrange(key, start, stop) + } + + suspend fun zrevrangeWithScores(key: String, start: Long, stop: Long): Set<Tuple>? = invoke { + it.zrevrangeWithScores(key, start, stop) + } + + suspend fun zrevrangeWithScores(key: ByteArray, start: Long, stop: Long): Set<Tuple>? = invoke { + it.zrevrangeWithScores(key, start, stop) + } + + suspend fun zrevrank(key: String, member: String): Long? = invoke { + it.zrevrank(key, member) + } + + suspend fun zrevrank(key: ByteArray, member: ByteArray): Long? = invoke { + it.zrevrank(key, member) + } + + suspend fun zscore(key: String, member: String): Double? = invoke { + it.zscore(key, member) + } + + suspend fun zscore(key: ByteArray, member: ByteArray): Double? = invoke { + it.zscore(key, member) + } + + suspend fun zpopmax(key: String): Tuple? = invoke { + it.zpopmax(key) + } + + suspend fun zpopmax(key: ByteArray): Tuple? = invoke { + it.zpopmax(key) + } + + suspend fun zpopmax(key: String, count: Int): Set<Tuple>? = invoke { + it.zpopmax(key, count) + } + + suspend fun zpopmax(key: ByteArray, count: Int): Set<Tuple>? = invoke { + it.zpopmax(key, count) + } + + suspend fun zpopmin(key: String): Tuple? = invoke { + it.zpopmin(key) + } + + suspend fun zpopmin(key: ByteArray): Tuple? = invoke { + it.zpopmin(key) + } + + suspend fun zpopmin(key: ByteArray, count: Int): Set<Tuple>? = invoke { + it.zpopmin(key, count) + } + + suspend fun zpopmin(key: String, count: Int): Set<Tuple>? = invoke { + it.zpopmin(key, count) + } + + suspend fun zlexcount(key: ByteArray, min: ByteArray, max: ByteArray): Long? = invoke { + it.zlexcount(key, min, max) + } + + suspend fun zlexcount(key: String, min: String, max: String): Long? = invoke { + it.zlexcount(key, min, max) + } + + suspend fun zrangeByLex(key: ByteArray, min: ByteArray, max: ByteArray): Set<ByteArray>? = invoke { + it.zrangeByLex(key, min, max) + } + + suspend fun zrangeByLex(key: String, min: String, max: String): Set<String>? = invoke { + it.zrangeByLex(key, min, max) + } + + suspend fun zrangeByLex( + key: ByteArray, min: ByteArray, max: ByteArray, + offset: Int, count: Int, + ): Set<ByteArray>? = invoke { + it.zrangeByLex(key, min, max, offset, count) + } + + suspend fun zrangeByLex( + key: String, min: String, max: String, + offset: Int, count: Int, + ): Set<String>? = invoke { + it.zrangeByLex(key, min, max, offset, count) + } + + suspend fun zrevrangeByLex(key: ByteArray, max: ByteArray, min: ByteArray): Set<ByteArray>? = invoke { + it.zrevrangeByLex(key, max, min) + } + + suspend fun zrevrangeByLex(key: String, max: String, min: String): Set<String>? = invoke { + it.zrevrangeByLex(key, max, min) + } + + suspend fun zrevrangeByLex( + key: ByteArray, max: ByteArray, min: ByteArray, + offset: Int, count: Int, + ): Set<ByteArray>? = invoke { + it.zrevrangeByLex(key, max, min, offset, count) + } + + suspend fun zrevrangeByLex( + key: String, max: String, min: String, + offset: Int, count: Int, + ): Set<String>? = invoke { + it.zrevrangeByLex(key, max, min, offset, count) + } + + suspend fun zremrangeByLex(key: ByteArray, min: ByteArray, max: ByteArray): Long? = invoke { + it.zremrangeByLex(key, min, max) + } + + suspend fun zremrangeByLex(key: String, min: String, max: String): Long? = invoke { + it.zremrangeByLex(key, min, max) + } + + suspend fun bitcount(key: String): Long? = invoke { + it.bitcount(key) + } + + suspend fun bitcount(key: String, start: Long, end: Long): Long? = invoke { + it.bitcount(key, start, end) + } + + suspend fun bitcount(key: ByteArray): Long? = invoke { + it.bitcount(key) + } + + suspend fun bitcount(key: ByteArray, start: Long, end: Long): Long? = invoke { + it.bitcount(key, start, end) + } + + suspend fun dump(key: String): ByteArray? = invoke { + it.dump(key) + } + + suspend fun dump(key: ByteArray): ByteArray? = invoke { + it.dump(key) + } + + suspend fun migrate( + host: String, port: Int, + key: String, destinationDb: Int, timeout: Int, + ): String? = invoke { + it.migrate(host, port, key, destinationDb, timeout) + } + + suspend fun migrate( + host: String, port: Int, + key: ByteArray, destinationDb: Int, timeout: Int, + ): String? = invoke { + it.migrate(host, port, key, destinationDb, timeout) + } + + suspend fun objectRefcount(key: String): Long? = invoke { + it.objectRefcount(key) + } + + suspend fun objectRefcount(key: ByteArray): Long? = invoke { + it.objectRefcount(key) + } + + suspend fun objectEncoding(key: String): String? = invoke { + it.objectEncoding(key) + } + + suspend fun objectEncoding(key: ByteArray): ByteArray? = invoke { + it.objectEncoding(key) + } + + suspend fun objectIdletime(key: String): Long? = invoke { + it.objectIdletime(key) + } + + suspend fun objectIdletime(key: ByteArray): Long? = invoke { + it.objectIdletime(key) + } + + suspend fun objectFreq(key: ByteArray): Long? = invoke { + it.objectFreq(key) + } + + suspend fun objectFreq(key: String): Long? = invoke { + it.objectFreq(key) + } + + suspend fun pexpire(key: String, milliseconds: Long): Long? = invoke { + it.pexpire(key, milliseconds) + } + + suspend fun pexpire(key: ByteArray, milliseconds: Long): Long? = invoke { + it.pexpire(key, milliseconds) + } + + suspend fun pexpireAt(key: String, millisecondsTimestamp: Long): Long? = invoke { + it.pexpireAt(key, millisecondsTimestamp) + } + + suspend fun pexpireAt(key: ByteArray, millisecondsTimestamp: Long): Long? = invoke { + it.pexpireAt(key, millisecondsTimestamp) + } + + suspend fun pttl(key: String): Long? = invoke { + it.pttl(key) + } + + suspend fun pttl(key: ByteArray): Long? = invoke { + it.pttl(key) + } + + suspend fun restore(key: String, ttl: Int, serializedValue: ByteArray): String? = invoke { + it.restore(key, ttl, serializedValue) + } + + suspend fun restore(key: ByteArray, ttl: Int, serializedValue: ByteArray): String? = invoke { + it.restore(key, ttl, serializedValue) + } + + suspend fun restoreReplace(key: String, ttl: Int, serializedValue: ByteArray): String? = invoke { + it.restoreReplace(key, ttl, serializedValue) + } + + suspend fun restoreReplace(key: ByteArray, ttl: Int, serializedValue: ByteArray): String? = invoke { + it.restoreReplace(key, ttl, serializedValue) + } + + suspend fun incrByFloat(key: String, increment: Double): Double? = invoke { + it.incrByFloat(key, increment) + } + + suspend fun incrByFloat(key: ByteArray, increment: Double): Double? = invoke { + it.incrByFloat(key, increment) + } + + suspend fun psetex(key: String, milliseconds: Long, value: String): String? = invoke { + it.psetex(key, milliseconds, value) + } + + suspend fun psetex(key: ByteArray, milliseconds: Long, value: ByteArray): String? = invoke { + it.psetex(key, milliseconds, value) + } + + suspend fun hincrByFloat(key: String, field: String, increment: Double): Double? = invoke { + it.hincrByFloat(key, field, increment) + } + + suspend fun hincrByFloat(key: ByteArray, field: ByteArray, increment: Double): Double? = invoke { + it.hincrByFloat(key, field, increment) + } + + suspend fun pfadd(key: ByteArray, vararg elements: ByteArray): Long? = invoke { + it.pfadd(key, *elements) + } + + suspend fun pfcount(key: ByteArray): Long? = invoke { + it.pfcount(key) + } + + suspend fun pfadd(key: String, vararg elements: String): Long? = invoke { + it.pfadd(key, *elements) + } + + suspend fun pfcount(key: String): Long? = invoke { + it.pfcount(key) + } + + suspend fun geoadd(key: ByteArray, longitude: Double, latitude: Double, member: ByteArray): Long? = invoke { + it.geoadd(key, longitude, latitude, member) + } + + suspend fun geoadd(key: ByteArray, memberCoordinateMap: Map<ByteArray, GeoCoordinate>): Long? = invoke { + it.geoadd(key, memberCoordinateMap) + } + + suspend fun geoadd(key: String, longitude: Double, latitude: Double, member: String): Long? = invoke { + it.geoadd(key, longitude, latitude, member) + } + + suspend fun geoadd(key: String, memberCoordinateMap: Map<String, GeoCoordinate>): Long? = invoke { + it.geoadd(key, memberCoordinateMap) + } + + suspend fun geodist(key: ByteArray, member1: ByteArray, member2: ByteArray): Double? = invoke { + it.geodist(key, member1, member2) + } + + suspend fun geodist(key: ByteArray, member1: ByteArray, member2: ByteArray, unit: GeoUnit): Double? = invoke { + it.geodist(key, member1, member2, unit) + } + + suspend fun geodist(key: String, member1: String, member2: String): Double? = invoke { + it.geodist(key, member1, member2) + } + + suspend fun geodist(key: String, member1: String, member2: String, unit: GeoUnit): Double? = invoke { + it.geodist(key, member1, member2, unit) + } + + suspend fun geohash(key: ByteArray, vararg members: ByteArray): List<ByteArray>? = invoke { + it.geohash(key, *members) + } + + suspend fun geohash(key: String, vararg members: String): List<String>? = invoke { + it.geohash(key, *members) + } + + suspend fun geopos(key: ByteArray, vararg members: ByteArray): List<GeoCoordinate>? = invoke { + it.geopos(key, *members) + } + + suspend fun geopos(key: String, vararg members: String): List<GeoCoordinate>? = invoke { + it.geopos(key, *members) + } + + suspend fun georadius( + key: ByteArray, longitude: Double, latitude: Double, + radius: Double, unit: GeoUnit, + ): List<GeoRadiusResponse>? = invoke { + it.georadius(key, longitude, latitude, radius, unit) + } + + suspend fun georadiusReadonly( + key: ByteArray, longitude: Double, latitude: Double, + radius: Double, unit: GeoUnit, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusReadonly(key, longitude, latitude, radius, unit) + } + + suspend fun georadius( + key: ByteArray, longitude: Double, latitude: Double, + radius: Double, unit: GeoUnit, param: GeoRadiusParam, + ): List<GeoRadiusResponse>? = invoke { + it.georadius(key, longitude, latitude, radius, unit, param) + } + + suspend fun georadiusReadonly( + key: ByteArray, longitude: Double, latitude: Double, + radius: Double, unit: GeoUnit, param: GeoRadiusParam, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusReadonly(key, longitude, latitude, radius, unit, param) + } + + suspend fun georadius( + key: String, longitude: Double, latitude: Double, + radius: Double, unit: GeoUnit, + ): List<GeoRadiusResponse>? = invoke { + it.georadius(key, longitude, latitude, radius, unit) + } + + suspend fun georadiusReadonly( + key: String, longitude: Double, latitude: Double, + radius: Double, unit: GeoUnit, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusReadonly(key, longitude, latitude, radius, unit) + } + + suspend fun georadius( + key: String, longitude: Double, latitude: Double, + radius: Double, unit: GeoUnit, param: GeoRadiusParam, + ): List<GeoRadiusResponse>? = invoke { + it.georadius(key, longitude, latitude, radius, unit, param) + } + + suspend fun georadiusReadonly( + key: String, longitude: Double, latitude: Double, + radius: Double, unit: GeoUnit, param: GeoRadiusParam, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusReadonly(key, longitude, latitude, radius, unit, param) + } + + suspend fun georadiusByMember( + key: ByteArray, member: ByteArray, + radius: Double, unit: GeoUnit, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusByMember(key, member, radius, unit) + } + + suspend fun georadiusByMemberReadonly( + key: ByteArray, member: ByteArray, + radius: Double, unit: GeoUnit, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusByMemberReadonly(key, member, radius, unit) + } + + suspend fun georadiusByMember( + key: ByteArray, member: ByteArray, + radius: Double, unit: GeoUnit, param: GeoRadiusParam, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusByMember(key, member, radius, unit, param) + } + + suspend fun georadiusByMemberReadonly( + key: ByteArray, member: ByteArray, + radius: Double, unit: GeoUnit, param: GeoRadiusParam, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusByMemberReadonly(key, member, radius, unit, param) + } + + suspend fun georadiusByMember( + key: String, member: String, + radius: Double, unit: GeoUnit, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusByMember(key, member, radius, unit) + } + + suspend fun georadiusByMemberReadonly( + key: String, member: String, + radius: Double, unit: GeoUnit, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusByMemberReadonly(key, member, radius, unit) + } + + suspend fun georadiusByMember( + key: String, member: String, + radius: Double, unit: GeoUnit, param: GeoRadiusParam, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusByMember(key, member, radius, unit, param) + } + + suspend fun georadiusByMemberReadonly( + key: String, member: String, + radius: Double, unit: GeoUnit, param: GeoRadiusParam, + ): List<GeoRadiusResponse>? = invoke { + it.georadiusByMemberReadonly(key, member, radius, unit, param) + } + + suspend fun bitfield(key: String, vararg elements: String): List<Long>? = invoke { + it.bitfield(key, *elements) + } + + suspend fun bitfield(key: ByteArray, vararg elements: ByteArray): List<Long>? = invoke { + it.bitfield(key, *elements) + } + + suspend fun bitfieldReadonly(key: ByteArray, vararg arguments: ByteArray): List<Long>? = invoke { + it.bitfieldReadonly(key, *arguments) + } + + suspend fun bitfieldReadonly(key: String, vararg arguments: String): List<Long>? = invoke { + it.bitfieldReadonly(key, *arguments) + } + + suspend fun hstrlen(key: String, field: String): Long? = invoke { + it.hstrlen(key, field) + } + + suspend fun hstrlen(key: ByteArray, field: ByteArray): Long? = invoke { + it.hstrlen(key, field) + } + + suspend fun xadd(key: String, id: StreamEntryID, hash: Map<String, String>) = + xadd(key, id, hash, Long.MAX_VALUE, true) + + suspend fun xadd(key: ByteArray, id: ByteArray, hash: Map<ByteArray, ByteArray>) = + xadd(key, id, hash, Long.MAX_VALUE, true) + + suspend fun xadd( + key: String, + id: StreamEntryID, + hash: Map<String, String>, + maxLen: Long, + approximateLength: Boolean, + ): StreamEntryID? = invoke { + it.xadd(key, id, hash, maxLen, approximateLength) + } + + suspend fun xadd( + key: ByteArray, + id: ByteArray, + hash: Map<ByteArray, ByteArray>, + maxLen: Long, + approximateLength: Boolean, + ): ByteArray? = invoke { + it.xadd(key, id, hash, maxLen, approximateLength) + } + + suspend fun xlen(key: String): Long? = invoke { + it.xlen(key) + } + + suspend fun xlen(key: ByteArray): Long? = invoke { + it.xlen(key) + } + + suspend fun xrange(key: String, start: StreamEntryID, end: StreamEntryID, count: Int): List<StreamEntry>? = invoke { + it.xrange(key, start, end, count) + } + + suspend fun xrange(key: ByteArray, start: ByteArray, end: ByteArray, count: Int): List<ByteArray>? = invoke { + it.xrange(key, start, end, count) + } + + suspend fun xrevrange(key: String, end: StreamEntryID, start: StreamEntryID, count: Int): List<StreamEntry>? = + invoke { + it.xrevrange(key, start, end, count) + } + + suspend fun xrevrange(key: ByteArray, end: ByteArray, start: ByteArray, count: Int): List<ByteArray>? = invoke { + it.xrevrange(key, start, end, count) + } + + suspend fun xack(key: String, group: String, vararg ids: StreamEntryID): Long? = invoke { + it.xack(key, group, *ids) + } + + suspend fun xack(key: ByteArray, group: ByteArray, vararg ids: ByteArray): Long? = invoke { + it.xack(key, group, *ids) + } + + suspend fun xgroupCreate(key: String, groupname: String, id: StreamEntryID, makeStream: Boolean): String? = invoke { + it.xgroupCreate(key, groupname, id, makeStream) + } + + suspend fun xgroupCreate(key: ByteArray, groupname: ByteArray, id: ByteArray, makeStream: Boolean): String? = + invoke { + it.xgroupCreate(key, groupname, id, makeStream) + } + + suspend fun xgroupSetID(key: String, groupname: String, id: StreamEntryID): String? = invoke { + it.xgroupSetID(key, groupname, id) + } + + suspend fun xgroupSetID(key: ByteArray, groupname: ByteArray, id: ByteArray): String? = invoke { + it.xgroupSetID(key, groupname, id) + } + + suspend fun xgroupDestroy(key: String, groupname: String): Long? = invoke { + it.xgroupDestroy(key, groupname) + } + + suspend fun xgroupDestroy(key: ByteArray, groupname: ByteArray): Long? = invoke { + it.xgroupDestroy(key, groupname) + } + + suspend fun xgroupDelConsumer(key: String, groupname: String, consumername: String): Long? = invoke { + it.xgroupDelConsumer(key, groupname, consumername) + } + + suspend fun xgroupDelConsumer(key: ByteArray, groupname: ByteArray, consumername: ByteArray): Long? = invoke { + it.xgroupDelConsumer(key, groupname, consumername) + } + + suspend fun xpending( + key: String, + groupname: String, + start: StreamEntryID, + end: StreamEntryID, + count: Int, + consumername: String, + ): List<StreamPendingEntry>? = invoke { + it.xpending(key, groupname, start, end, count, consumername) + } + + suspend fun xpending( + key: ByteArray, + groupname: ByteArray, + start: ByteArray, + end: ByteArray, + count: Int, + consumername: ByteArray, + ): List<StreamPendingEntry>? = invoke { + it.xpending(key, groupname, start, end, count, consumername) + } + + suspend fun xdel(key: String, vararg ids: StreamEntryID): Long? = invoke { + it.xdel(key, *ids) + } + + suspend fun xdel(key: ByteArray, vararg ids: ByteArray): Long? = invoke { + it.xdel(key, *ids) + } + + suspend fun xtrim(key: String, maxLen: Long, approximateLength: Boolean): Long? = invoke { + it.xtrim(key, maxLen, approximateLength) + } + + suspend fun xtrim(key: ByteArray, maxLen: Long, approximateLength: Boolean): Long? = invoke { + it.xtrim(key, maxLen, approximateLength) + } + + suspend fun xclaim( + key: String, group: String, consumername: String, minIdleTime: Long, + newIdleTime: Long, retries: Int, force: Boolean, vararg ids: StreamEntryID, + ): List<StreamEntry>? = invoke { + it.xclaim(key, group, consumername, minIdleTime, newIdleTime, retries, force, *ids) + } + + suspend fun xclaim( + key: ByteArray, group: ByteArray, consumername: ByteArray, minIdleTime: Long, + newIdleTime: Long, retries: Int, force: Boolean, vararg ids: ByteArray, + ): List<ByteArray>? = invoke { + it.xclaim(key, group, consumername, minIdleTime, newIdleTime, retries, force, *ids) + } + + suspend fun sendCommand(sampleKey: String, cmd: ProtocolCommand, vararg args: String): Any? = invoke { + it.sendCommand(sampleKey, cmd, *args) + } + + suspend fun sendCommand(sampleKey: ByteArray, cmd: ProtocolCommand, vararg args: ByteArray): Any? = invoke { + it.sendCommand(sampleKey, cmd, *args) + } +} diff --git a/utils/src/main/kotlin/cn/tursom/utils/AsyncIterator.kt b/utils/src/main/kotlin/cn/tursom/utils/AsyncIterator.kt deleted file mode 100644 index 99bc7c6..0000000 --- a/utils/src/main/kotlin/cn/tursom/utils/AsyncIterator.kt +++ /dev/null @@ -1,20 +0,0 @@ -package cn.tursom.utils - -interface AsyncIterator<T> { - /** - * Returns the next element in the iteration. - */ - suspend operator fun next(): T - - /** - * Returns `true` if the iteration has more elements. - */ - suspend operator fun hasNext(): Boolean -} - -suspend inline fun <T> AsyncIterator<T>.forEach(action: (T) -> Unit) { - while (hasNext()) { - val element = next() - action(element) - } -} \ No newline at end of file diff --git a/utils/src/main/kotlin/cn/tursom/utils/GsonDataTypeAdaptor.kt b/utils/src/main/kotlin/cn/tursom/utils/GsonDataTypeAdaptor.kt deleted file mode 100644 index 82ccca6..0000000 --- a/utils/src/main/kotlin/cn/tursom/utils/GsonDataTypeAdaptor.kt +++ /dev/null @@ -1,86 +0,0 @@ -package cn.tursom.utils - -import cn.tursom.core.cast -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import com.google.gson.TypeAdapter -import com.google.gson.TypeAdapterFactory -import com.google.gson.internal.LinkedTreeMap -import com.google.gson.reflect.TypeToken -import com.google.gson.stream.JsonReader -import com.google.gson.stream.JsonToken -import com.google.gson.stream.JsonWriter - -class GsonDataTypeAdaptor internal constructor(private val gson: Gson) : TypeAdapter<Map<String, Any>?>() { - override fun write(out: JsonWriter, value: Map<String, Any>?) { - if (value == null) { - out.nullValue() - return - } - out.beginObject() - value.forEach { (t, u) -> - out.name(t) - System.err.println(u) - gson.getAdapter(Any::class.java).write(out, u) - } - out.endObject() - } - - override fun read(`in`: JsonReader): Map<String, Any> = readInternal(`in`).cast() - - private fun readInternal(`in`: JsonReader): Any? { - return when (`in`.peek()) { - JsonToken.BEGIN_ARRAY -> { - val list: MutableList<Any?> = ArrayList() - `in`.beginArray() - while (`in`.hasNext()) { - list.add(readInternal(`in`)) - } - `in`.endArray() - list - } - JsonToken.BEGIN_OBJECT -> { - val map: MutableMap<String, Any?> = LinkedTreeMap() - `in`.beginObject() - while (`in`.hasNext()) { - map[`in`.nextName()] = readInternal(`in`) - } - `in`.endObject() - map - } - JsonToken.STRING -> `in`.nextString() - JsonToken.NUMBER -> { - //将其作为一个字符串读取出来 - val numberStr: String = `in`.nextString() - //返回的numberStr不会为null - if (numberStr.contains(".") || numberStr.contains("e") - || numberStr.contains("E") - ) { - numberStr.toDouble() - } else numberStr.toLong() - } - JsonToken.BOOLEAN -> `in`.nextBoolean() - JsonToken.NULL -> { - `in`.nextNull() - null - } - else -> throw IllegalStateException() - } - } - - companion object { - val FACTORY: TypeAdapterFactory = object : - TypeAdapterFactory { - override fun <T> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? { - return if (type.rawType == Map::class.java) { - GsonDataTypeAdaptor(gson).cast() - } else null - } - } - - val gson = GsonBuilder() - .registerTypeAdapterFactory(FACTORY) - .create() - } - -} \ No newline at end of file