Module: Clickwrap::Identifier
- Defined in:
- lib/clickwrap/identifier.rb
Overview
Event identifiers.
Clickwrap events use ULIDs (https://github.com/ulid/spec): 26 Crockford base32 characters, the first ten encoding milliseconds since the Unix epoch. They sort lexicographically in creation order, which keeps evidence exports and index scans in a sensible sequence, and they carry no host database sequence a reader could use to count unrelated records.
The embedded timestamp is a convenience for ordering. It is not the
evidentiary time: that is recorded_at_by_server on the event, recorded
from the application server's clock and described as exactly that.
Constant Summary collapse
- ENCODING =
"0123456789ABCDEFGHJKMNPQRSTVWXYZ"- ENCODING_LENGTH =
32- TIME_LENGTH =
10- RANDOM_LENGTH =
16- LENGTH =
TIME_LENGTH + RANDOM_LENGTH
- PATTERN =
/\A[0-7][#{ENCODING}]{25}\z/
Class Method Summary collapse
-
.generate(moment = Time.now) ⇒ Object
Returns a new ULID.
-
.time_from(value) ⇒ Object
Returns the Time encoded in the identifier, or nil when it is not a ULID.
- .valid?(value) ⇒ Boolean
Class Method Details
.generate(moment = Time.now) ⇒ Object
Returns a new ULID. moment is accepted so tests and importers can
produce deterministic, correctly ordered identifiers.
Identifiers generated within the same millisecond increment instead of re-randomizing, so a batch of events captured together still sorts in the order it was written. That matters for exports and for reading a lifecycle chain by identifier alone.
37 38 39 |
# File 'lib/clickwrap/identifier.rb', line 37 def generate(moment = Time.now) MUTEX.synchronize { monotonic_ulid(encode_time(moment)) } end |
.time_from(value) ⇒ Object
Returns the Time encoded in the identifier, or nil when it is not a ULID. Callers must not treat this as the recorded server time.
47 48 49 50 51 52 53 54 55 |
# File 'lib/clickwrap/identifier.rb', line 47 def time_from(value) return nil unless valid?(value) milliseconds = value.to_s[0, TIME_LENGTH].each_char.reduce(0) do |total, char| (total * ENCODING_LENGTH) + ENCODING.index(char) end Time.at(milliseconds / 1000.0).utc end |
.valid?(value) ⇒ Boolean
41 42 43 |
# File 'lib/clickwrap/identifier.rb', line 41 def valid?(value) PATTERN.match?(value.to_s) end |