Skip to content

Conversation

@ChrisGoettfert
Copy link

Fix for GitHub Issue #304: Non-Deterministic Document Sorting

Summary

Successfully fixed the non-deterministic document sorting issue on the view-tournament page. Documents are now sorted alphabetically by name with lastModifiedAt as a tiebreaker, ensuring consistent ordering across all scenarios.


Problem Identified

Documents on the view-tournament page were being sorted by their id field (a GUID/PublicId) using localeCompare(). Since GUIDs are randomly generated, this resulted in non-deterministic ordering where documents could appear in different orders across:

  • Page refreshes
  • Different browsers
  • Different user sessions

Changes Made

view-tournament.component.ts

Updated the document sorting logic in two locations:

1. togglePage() method (lines 258-263)

Before:

this.documents.sort((a, b) => a.id.localeCompare(b.id));

After:

this.documents.sort((a, b) => {
  const nameComparison = a.name.localeCompare(b.name);
  if (nameComparison !== 0) {
    return nameComparison;
  }
  return new Date(a.lastModifiedAt).getTime() - new Date(b.lastModifiedAt).getTime();
});

2. reloadDocuments() method (lines 891-897)

Before:

this.documents.sort((a, b) => a.id.localeCompare(b.id));

After:

this.documents.sort((a, b) => {
  const nameComparison = a.name.localeCompare(b.name);
  if (nameComparison !== 0) {
    return nameComparison;
  }
  return new Date(a.lastModifiedAt).getTime() - new Date(b.lastModifiedAt).getTime();
});

Sorting Logic

The new sorting algorithm ensures deterministic ordering by:

  1. Primary Sort: Alphabetically by document name using localeCompare()
  2. Secondary Sort: By last modified timestamp (oldest to newest) when names are identical

This approach guarantees:

  • ✅ Consistent ordering across all browsers and sessions
  • ✅ Predictable document arrangement
  • ✅ Alphabetical organization for easy navigation
  • ✅ Stable sort for documents with identical names

Technical Details

DocumentDto Model

The DocumentDto interface (from the backend) contains:

  • id: PublicId (GUID) - Previously used for sorting
  • name: string - Now used as primary sort key
  • lastModifiedAt: DateTime - Now used as secondary sort key
  • type: DocumentType
  • tournamentId: PublicId
  • generationCount: number

Why This Fix Works

  1. Deterministic Primary Key: Document names are user-defined strings that remain stable, unlike auto-generated GUIDs
  2. Stable Tiebreaker: lastModifiedAt provides a consistent secondary sort for documents with identical names
  3. Locale-Aware: Using localeCompare() ensures proper alphabetical sorting across different languages and character sets
  4. Timestamp Precision: Converting dates to milliseconds ensures accurate chronological ordering

Documents on the view-tournament page are now sorted alphabetically by name with lastModifiedAt as a tiebreaker, ensuring consistent ordering across all scenarios. Previously, documents were sorted by GUID-based IDs which resulted in non-deterministic ordering.

… lastModifiedAt

Documents on the view-tournament page are now sorted alphabetically by name with lastModifiedAt as a tiebreaker, ensuring consistent ordering across all scenarios. Previously, documents were sorted by GUID-based IDs which resulted in non-deterministic ordering.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant