use crate::id_generator_options::IdGeneratorOptions;
use crate::isnow_worker::ISnowWorker;
use crate::over_cost_action_arg::OverCostActionArg;
use std::sync::Mutex;
use std::thread::sleep;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
pub struct SnowWorkerM1 {
pub base_time: i64,
pub worker_id: u16,
pub worker_id_bit_length: u8,
pub seq_bit_length: u8,
pub max_seq_number: u32,
pub min_seq_number: u32,
pub top_over_cost_count: u32,
pub timestamp_shift: u8,
pub current_seq_number: u32,
pub last_time_tick: i64,
pub turn_back_time_tick: i64,
pub turn_back_index: u8,
pub is_over_cost: bool,
pub over_cost_count_in_one_term: u32,
pub lock: Mutex<()>,
}
impl SnowWorkerM1 {
pub fn new(options: &IdGeneratorOptions) -> Self {
let base_time = if options.base_time != 0 {
options.base_time
} else {
1582136402000
};
let worker_id_bit_length = if options.worker_id_bit_length == 0 {
6
} else {
options.worker_id_bit_length
};
let worker_id = options.worker_id;
let seq_bit_length = if options.seq_bit_length == 0 {
6
} else {
options.seq_bit_length
};
let max_seq_number = if options.max_seq_number == 0 {
(1 << seq_bit_length) - 1
} else {
options.max_seq_number
};
let min_seq_number = options.min_seq_number;
let top_over_cost_count = options.top_over_cost_count;
let timestamp_shift = worker_id_bit_length + seq_bit_length;
let current_seq_number = min_seq_number;
SnowWorkerM1 {
base_time,
worker_id,
worker_id_bit_length,
seq_bit_length,
max_seq_number,
min_seq_number,
top_over_cost_count,
timestamp_shift,
current_seq_number,
last_time_tick: 0,
turn_back_time_tick: 0,
turn_back_index: 0,
is_over_cost: false,
over_cost_count_in_one_term: 0,
lock: Mutex::new(()),
}
}
pub fn do_gen_id_action(&self, _arg: &OverCostActionArg) {
}
pub fn begin_over_cost_action(&self, _use_time_tick: i64) {
}
pub fn end_over_cost_action(&self, _use_time_tick: i64) {
}
pub fn begin_turn_back_action(&self, _use_time_tick: i64) {
}
pub fn end_turn_back_action(&self, _use_time_tick: i64) {
}
pub fn next_over_cost_id(&mut self) -> i64 {
let current_time_tick = self.get_current_time_tick();
if current_time_tick > self.last_time_tick {
self.last_time_tick = current_time_tick;
self.current_seq_number = self.min_seq_number;
self.is_over_cost = false;
self.over_cost_count_in_one_term = 0;
return self.calc_id(self.last_time_tick);
}
if self.over_cost_count_in_one_term >= self.top_over_cost_count {
self.last_time_tick = self.get_next_time_tick();
self.current_seq_number = self.min_seq_number;
self.is_over_cost = false;
self.over_cost_count_in_one_term = 0;
return self.calc_id(self.last_time_tick);
}
if self.current_seq_number > self.max_seq_number {
self.last_time_tick += 1;
self.current_seq_number = self.min_seq_number;
self.is_over_cost = true;
self.over_cost_count_in_one_term += 1;
return self.calc_id(self.last_time_tick);
}
self.calc_id(self.last_time_tick)
}
pub fn next_normal_id(&mut self) -> i64 {
let current_time_tick = self.get_current_time_tick();
if current_time_tick < self.last_time_tick {
if self.turn_back_time_tick < 1 {
self.turn_back_time_tick = self.last_time_tick - 1;
self.turn_back_index += 1;
if self.turn_back_index > 4 {
self.turn_back_index = 1;
}
self.begin_turn_back_action(self.turn_back_time_tick);
}
return self.calc_turn_back_id(self.turn_back_time_tick);
}
if self.turn_back_time_tick > 0 {
self.end_turn_back_action(self.turn_back_time_tick);
self.turn_back_time_tick = 0;
}
if current_time_tick > self.last_time_tick {
self.last_time_tick = current_time_tick;
self.current_seq_number = self.min_seq_number;
return self.calc_id(self.last_time_tick);
}
if self.current_seq_number > self.max_seq_number {
self.begin_over_cost_action(current_time_tick);
self.last_time_tick += 1;
self.current_seq_number = self.min_seq_number;
self.is_over_cost = true;
self.over_cost_count_in_one_term = 1;
return self.calc_id(self.last_time_tick);
}
self.calc_id(self.last_time_tick)
}
pub fn calc_id(&mut self, use_time_tick: i64) -> i64 {
let result = (use_time_tick << self.timestamp_shift)
+ (self.worker_id << self.seq_bit_length) as i64
+ self.current_seq_number as i64;
self.current_seq_number += 1;
result
}
pub fn calc_turn_back_id(&mut self, use_time_tick: i64) -> i64 {
let result = (use_time_tick << self.timestamp_shift)
+ (self.worker_id << self.seq_bit_length) as i64
+ self.turn_back_index as i64;
self.turn_back_time_tick -= 1;
result
}
pub fn get_current_time_tick(&self) -> i64 {
let millis = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis() as i64;
millis - self.base_time
}
fn next_id(&mut self) -> i64 {
if self.is_over_cost {
self.next_over_cost_id()
} else {
self.next_normal_id()
}
}
pub fn get_next_time_tick(&self) -> i64 {
let mut temp_time_tick = self.get_current_time_tick();
while temp_time_tick <= self.last_time_tick {
sleep(Duration::from_millis(1));
temp_time_tick = self.get_current_time_tick();
}
temp_time_tick
}
}
impl ISnowWorker for SnowWorkerM1 {
fn next_id(&mut self) -> i64 {
SnowWorkerM1::next_id(self)
}
}