Class: Protobuf::Nats::UUIDv7Helper
- Inherits:
-
Object
- Object
- Protobuf::Nats::UUIDv7Helper
- Defined in:
- lib/protobuf/nats/uuidv7_helper.rb
Class Method Summary collapse
-
.age_in_seconds(uuid, current_time: Time.now) ⇒ Float?
Calculate the age of a UUIDv7 in seconds Returns nil if the UUID cannot be parsed.
-
.extract_timestamp(uuid) ⇒ Time?
Extract the Unix timestamp (in seconds) from a UUIDv7 string Returns nil if the UUID cannot be parsed.
-
.generate ⇒ String
Generate a UUIDv7 string without a CSPRNG.
Class Method Details
.age_in_seconds(uuid, current_time: Time.now) ⇒ Float?
Calculate the age of a UUIDv7 in seconds Returns nil if the UUID cannot be parsed
52 53 54 55 56 57 |
# File 'lib/protobuf/nats/uuidv7_helper.rb', line 52 def self.age_in_seconds(uuid, current_time: Time.now) = (uuid) return nil unless current_time - end |
.extract_timestamp(uuid) ⇒ Time?
Extract the Unix timestamp (in seconds) from a UUIDv7 string Returns nil if the UUID cannot be parsed
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/protobuf/nats/uuidv7_helper.rb', line 32 def self.(uuid) return nil unless uuid.is_a?(String) # UUIDv7 format: first 48 bits (12 hex chars) are Unix timestamp in milliseconds # Remove dashes and extract the timestamp portion uuid_bytes = uuid.gsub('-', '') return nil if uuid_bytes.length < 12 = uuid_bytes[0...12].to_i(16) Time.at( / 1000.0) rescue => e nil end |
.generate ⇒ String
Generate a UUIDv7 string without a CSPRNG. Callers that only need a 48-bit millisecond timestamp prefix (so #age_in_seconds can report a value) plus enough randomness to stay unique among concurrent generators don’t need SecureRandom: its gen_random call dominated per-request CPU and garbage (measured ~6.8us/op and 4 GC-triggering allocations). A per-thread non-cryptographic Random halves both. The layout still matches RFC 9562 UUIDv7 (version 7 + RFC 4122 variant bits).
13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/protobuf/nats/uuidv7_helper.rb', line 13 def self.generate unix_ts_ms = ::Process.clock_gettime(::Process::CLOCK_REALTIME, :millisecond) & 0xffffffffffff rng = (::Thread.current[:pb_nats_uuid_rng] ||= ::Random.new) format( "%08x-%04x-%04x-%04x-%04x%08x", (unix_ts_ms >> 16) & 0xffffffff, # 32 high bits of the ms timestamp unix_ts_ms & 0xffff, # 16 low bits of the ms timestamp (0x7000 | rng.rand(0x1000)), # version 7 + 12 random bits (0x8000 | rng.rand(0x4000)), # RFC 4122 variant + 14 random bits rng.rand(0x10000), # 16 random bits rng.rand(0x100000000) # 32 random bits ) end |