feat: ID生成器を追加

This commit is contained in:
usbharu 2023-04-20 22:02:14 +09:00
parent 6151fd8a0a
commit 6bc01f6552
Signed by: usbharu
GPG Key ID: 6556747BF94EEBC8
4 changed files with 91 additions and 0 deletions

View File

@ -0,0 +1,5 @@
package dev.usbharu.hideout.service
interface IdGenerateService {
suspend fun generateId():Long
}

View File

@ -0,0 +1,47 @@
package dev.usbharu.hideout.service
import kotlinx.coroutines.delay
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.time.Instant
open class SnowflakeIdGenerateService(private val baseTime:Long) : IdGenerateService {
var lastTimeStamp: Long = -1
var sequenceId: Int = 0
val mutex = Mutex()
@Throws(IllegalStateException::class)
override suspend fun generateId(): Long {
return mutex.withLock {
var timestamp = getTime()
if (timestamp < lastTimeStamp) {
while (timestamp <= lastTimeStamp) {
delay(1L)
timestamp = getTime()
}
// throw IllegalStateException(" $lastTimeStamp $timestamp ${lastTimeStamp-timestamp} ")
}
if (timestamp == lastTimeStamp) {
sequenceId++
if (sequenceId >= 4096) {
while (timestamp <= lastTimeStamp) {
delay(1L)
timestamp = getTime()
}
sequenceId = 0
}
} else {
sequenceId = 0
}
lastTimeStamp = timestamp
return@withLock (timestamp - baseTime).shl(22).or(1L.shl(12)).or(sequenceId.toLong())
}
}
private fun getTime(): Long {
return Instant.now().toEpochMilli()
}
}

View File

@ -0,0 +1,4 @@
package dev.usbharu.hideout.service
// 2010-11-04T01:42:54.657
object TwitterSnowflakeIdGenerateService : SnowflakeIdGenerateService(1288834974657L)

View File

@ -0,0 +1,35 @@
package dev.usbharu.hideout.service
//import kotlinx.coroutines.NonCancellable.message
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class TwitterSnowflakeIdGenerateServiceTest {
@Test
fun noDuplicateTest() = runBlocking {
val mutex = Mutex()
val mutableListOf = mutableListOf<Long>()
coroutineScope {
repeat(500000) {
launch(Dispatchers.IO) {
val id = TwitterSnowflakeIdGenerateService.generateId()
mutex.withLock {
mutableListOf.add(id)
}
}
}
}
assertEquals(0, mutableListOf.size - mutableListOf.toSet().size)
}
}