36 lines
1.0 KiB
Python
36 lines
1.0 KiB
Python
from __future__ import annotations
|
|
|
|
import secrets
|
|
import threading
|
|
import time
|
|
from uuid import UUID
|
|
|
|
_lock = threading.Lock()
|
|
_last_millisecond = -1
|
|
_last_random = 0
|
|
_RANDOM_MASK = (1 << 74) - 1
|
|
|
|
|
|
def new_uuid7() -> UUID:
|
|
"""Return a process-monotonic RFC 9562 UUIDv7."""
|
|
global _last_millisecond, _last_random
|
|
with _lock:
|
|
millisecond = time.time_ns() // 1_000_000
|
|
if millisecond > _last_millisecond:
|
|
_last_millisecond = millisecond
|
|
_last_random = secrets.randbits(74)
|
|
else:
|
|
millisecond = _last_millisecond
|
|
_last_random = (_last_random + 1) & _RANDOM_MASK
|
|
if _last_random == 0:
|
|
_last_millisecond += 1
|
|
millisecond = _last_millisecond
|
|
random_a = (_last_random >> 62) & 0xFFF
|
|
random_b = _last_random & ((1 << 62) - 1)
|
|
integer = (millisecond & ((1 << 48) - 1)) << 80
|
|
integer |= 0x7 << 76
|
|
integer |= random_a << 64
|
|
integer |= 0b10 << 62
|
|
integer |= random_b
|
|
return UUID(int=integer)
|