Coverage Summary for Class: SnowflakeIdGenerator (com.kotlinorm.beans.generator)

Class Class, % Method, % Branch, % Line, % Instruction, %
SnowflakeIdGenerator 100% (1/1) 100% (7/7) 80% (16/20) 86.7% (26/30) 92.9% (131/141)


 /**
  * Copyright 2022-2025 kronos-orm
  *
  * 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 com.kotlinorm.beans.generator
 
 import com.kotlinorm.interfaces.KIdGenerator
 
 object UUIDGenerator : KIdGenerator<String> {
     override fun nextId(): String = java.util.UUID.randomUUID().toString()
 }
 
 object SnowflakeIdGenerator : KIdGenerator<Long> {
     private const val SEQUENCE_BITS = 12
     private const val WORKER_ID_BITS = 5
     private const val DATACENTER_ID_BITS = 5
 
     private const val MAX_WORKER_ID = (1 shl WORKER_ID_BITS) - 1
     private const val MAX_DATACENTER_ID = (1 shl DATACENTER_ID_BITS) - 1
 
     private const val TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS
     private const val DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS
     private const val WORKER_ID_SHIFT = SEQUENCE_BITS
 
     private var sequence: Long = 0
     private var lastTimestamp: Long = -1
     private var _datacenterId: Long = 1
     private var _workerId: Long = 1
 
     /**
      * The unique id of the datacenter in which the application is running.
      * This value must be unique for each datacenter.
      *
      * The default value is 1.
      */
     @Suppress("MemberVisibilityCanBePrivate")
     var datacenterId
         get() = _datacenterId
         set(value) = run {
             require(value in 0..MAX_DATACENTER_ID) { "Datacenter id must be less than $MAX_DATACENTER_ID" }
             _datacenterId = value
         }
 
     /**
      * The unique id of the worker in which the application is running.
      * This value must be unique for each worker.
      *
      * The default value is 1.
      */
     @Suppress("MemberVisibilityCanBePrivate")
     var workerId
         get() = _workerId
         set(value) = run {
             require(value in 0..MAX_WORKER_ID) { "Worker id must be less than $MAX_WORKER_ID" }
             _workerId = value
         }
 
     @Synchronized
     override fun nextId(): Long {
         var timestamp = System.currentTimeMillis()
 
         if (timestamp < lastTimestamp) {
             throw IllegalStateException("Clock moved backwards. Refusing to generate id for ${lastTimestamp - timestamp} milliseconds.")
         }
 
         if (lastTimestamp == timestamp) {
             sequence = (sequence + 1) and (((1 shl SEQUENCE_BITS) - 1).toLong())
             if (sequence == 0L) {
                 timestamp = waitNextMillis(lastTimestamp)
             }
         } else {
             sequence = 0
         }
 
         lastTimestamp = timestamp
 
         return ((timestamp shl TIMESTAMP_LEFT_SHIFT) or
                 (datacenterId shl DATACENTER_ID_SHIFT) or
                 (workerId shl WORKER_ID_SHIFT) or
                 sequence)
     }
 
     private fun waitNextMillis(lastTimestamp: Long): Long {
         var timestamp = System.currentTimeMillis()
         while (timestamp <= lastTimestamp) {
             timestamp = System.currentTimeMillis()
         }
         return timestamp
     }
 }
 
 var customIdGenerator: KIdGenerator<*>? = null