Skip to content

ekjaisal/MonoLexID

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MonoLexID

GitHub Release License: BSD-3-Clause GitHub Stars Build

MonoLexID is a time-ordered and sortable Universally Unique Identifier (UUID) generator written in Object Pascal (Free Pascal), producing identifiers structurally compatible with the RFC 9562 UUIDv7 layout while privileging intra-millisecond monotonicity.

Generation Policy

  • Lexicographic Monotonicity: Identifiers are time-ordered at millisecond precision, ensuring natural sequential sorting, preventing index fragmentation and optimising database insertion performance.

  • Time Integrity: The generator privileges clock-dependent chronological truth. Should the system exhaust the sequence counter (4,096 allocations per millisecond) or detect a retrograde clock shift, generation is suspended via an adaptive spin/yield loop. It yields (pauses) until physical time advances, so that identifiers are not generated with a fictitious-future time.

  • Cryptographic Uniqueness: To preclude collisions in distributed environments, the remainder of the string payload is populated using OS-native, cryptographically secure pseudorandom number generators to minimise collision risk.

  • Fail-Closed Under Clock Rollback: MonoLexID is intentionally fail-closed under retrograde clock conditions. If the system clock is stepped backwards and remains so, generation will suspend until physical time catches up or the configurable spin timeout (MonoLexIDSpinTimeoutMS, default 5000 ms) is exceeded. Applications that require fail-open UUID generation under clock instability should not rely on MonoLexID’s time integrity guarantees.

Structure

MonoLexID generates a 36-character string (xxxxxxxx-xxxx-7xxx-xxxx-xxxxxxxxxxxx), which breaks down as follows:

  • Chars 1-8: UNIX Timestamp in Milliseconds (Part 1)
  • Char 9: Hyphen -
  • Chars 10-13: UNIX Timestamp in Milliseconds (Part 2)
  • Char 14: Hyphen -
  • Chars 15-18: Version Identifier (7) + 12-bit Sequence Counter
  • Char 19: Hyphen -
  • Chars 20-23: Variant Identifier (8, 9, a, or b) + Random Data
  • Char 24: Hyphen -
  • Chars 25-36: Secure Random Data

Usage

MonoLexID is contained entirely within a single unit with no external dependencies. To integrate it, download the latest version from the Releases page, include MonoLexID.pas in the project directory, and add it to the uses clause.

To generate a standard 36-character string format:

uses
  MonoLexID;

var
  NewID: String;
begin
  NewID := NewMonoLexID; 
end;

Alternatively, to retrieve the raw 16-byte array:

uses
  MonoLexID;

var
  RawBytes: TMonoLexIDBytes;
begin
  RawBytes := NewMonoLexIDBytes;
end;

Thread Safety Configuration

MonoLexID offers two concurrency modes.

Default: Per-Thread Monotonicity (threadvar mode)

State is managed per thread using threadvar. IDs generated on the same thread are strictly monotonic. IDs generated concurrently across different threads are individually monotonic per thread but are not guaranteed to be globally monotonic across threads. This mode has near-zero lock contention and is suitable for the vast majority of applications.

Global Monotonicity Mode (MONOLEXID_GLOBAL_MONOTONIC)

All threads share a single protected generator state, with strict process-local lexicographic monotonicity across every thread. It can be enabled by passing -dMONOLEXID_GLOBAL_MONOTONIC in the project compiler options or by adding {$DEFINE MONOLEXID_GLOBAL_MONOTONIC} at the top of MonoLexID.pas, as indicated in the comment block within the unit. This mode introduces a critical section per generation call and is recommended for distributed systems where global ordering across all threads is required.

Fork Safety

MonoLexID is safe for use in applications that fork. On POSIX systems, it registers a three-stage pthread_atfork handler that acquires all internal locks before the fork, releases them in the parent, and fully reinitialises the generator state, entropy source, and session nonce in the child. A PID-change detection fallback provides secondary protection. MonoLexIDReinitialize is available as an explicit application-callable reinitialisation for fork-aware applications that manage their own fork handlers.

Error Handling

MonoLexID provides both exception-raising and safe non-raising APIs.

Exception-raising (recommended for most use cases):

var
  NewID: String;
begin
  NewID := NewMonoLexID;
end;

Safe non-raising (recommended for critical or high-availability use cases):

var
  NewID: String;
begin
  if TryNewMonoLexID(NewID) then
    WriteLn('Generated ID: ', NewID)
  else
    WriteLn('Error: ', MonoLexIDGetLastError);
end;

Generation may fail under the following conditions: CSPRNG unavailability, /dev/urandom inaccessibility on POSIX systems, spin timeout exceeded due to severe clock instability, or subsystem initialisation failure. In all cases the failure reason is retrievable via MonoLexIDGetLastError.

Public API

Identifier Kind Description
NewMonoLexID function: String Generates a new ID as a 36-character string. Raises on failure.
TryNewMonoLexID function(out ID: String): Boolean Generates a new ID. Returns False on failure without raising.
NewMonoLexIDBytes function: TMonoLexIDBytes Generates a new ID as a raw 16-byte array. Raises on failure.
TryNewMonoLexIDBytes function(out IDBytes: TMonoLexIDBytes): Boolean Generates a new ID as bytes. Returns False on failure without raising.
MonoLexIDFlushState procedure Flushes unpersisted generator state via MonoLexIDSaveState if assigned. Safe to call at application shutdown.
MonoLexIDReinitialize function: Boolean Explicitly reinitialises the subsystem. Returns False and populates MonoLexIDInitError on failure. Useful after fork or following a failed initialisation.
MonoLexIDGetLastError function: String Returns the most recent error message from a failed Try call or persistence failure. Thread-safe.
MonoLexIDGetTimeMS var Pluggable time source. Defaults to the highest-resolution wall-clock available on the platform.
MonoLexIDYieldThread var Pluggable yield function called during spin waits. Defaults to SwitchToThread on Windows and Sleep(0) on POSIX.
MonoLexIDSaveState var Optional persistence callback. Called periodically and at flush. nil by default.
MonoLexIDLoadState var Optional state restoration callback. Called on generator initialisation. nil by default.
MonoLexIDInitError var String Populated with the reason if initialisation or reinitialisation fails.
MonoLexIDSpinTimeoutMS var Int64 Maximum wall-clock milliseconds any spin loop will wait before raising. Default 5000.
MonoLexIDVersionMajor/Minor/Patch const Integer Version constants.

Compatibility

MonoLexID compiles and runs on:

  • Windows (x86, x86-64)
  • Linux (x86, x86-64, ARM, ARM64, and all FPC 3.2.2 or later supported targets)
  • macOS (x86-64, ARM64)
  • Any POSIX platform supported by FPC 3.2.2 or later with /dev/urandom available

Acknowledgements

The project has benefited significantly from the assistance of Google’s Gemini 3.1 Pro and Anthropic’s Claude Sonnet 4.6 for collaborative ideation, code generation, refactoring, and debugging.

License

The project is under the BSD 3-Clause License and is provided “as-is”, without any warranties. Please see the LICENSE file for details.

About

Time-ordered and sortable UUID generator that privileges intra-millisecond monotonicity and produces UUIDv7-compatible identifiers

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

  •  

Contributors

Languages