Files
core/docs/IMPLEMENTATION_STATUS.md

5.5 KiB

Unique ID Prefixes & Entity Renaming - Implementation Status

Phase 1: ID Generation Infrastructure COMPLETE

Completed Files

  • /migrations/0009_id_sequences/up.sql - Creates id_sequences table
  • /migrations/0009_id_sequences/down.sql - Rollback script
  • /internal/idgen/generator.go - ID generation service
  • /internal/idgen/generator_test.go - Comprehensive tests

Verification

  • Migration applied successfully
  • All tests passing (including concurrency tests)
  • Manual verification complete - IDs generating correctly:
    • Customer: CR-0000003
    • Project: PJ-0000003
    • Asset: ME-0000004
    • Component: PT-0000047
    • Ticket: TT-0000002
    • Failure Event: FE-0000001

Phase 2: Dual-Write Period COMPLETE

Completed Files

  • /migrations/0010_add_string_ids/up.sql - Adds sid columns
  • /migrations/0010_add_string_ids/down.sql - Rollback script
  • Migration Applied - All existing data backfilled with formatted IDs
  • /internal/domain/registry.go - Updated all models (Customer, Project, Location, Lot, Asset, Component)
  • /internal/domain/tickets.go - Updated Ticket and TicketLink models
  • /internal/domain/failure_events.go - Updated FailureEvent model

All Repositories Updated with Dual-Write

  • /internal/repository/registry/customers.go - Dual-write implemented
  • /internal/repository/registry/projects.go - Dual-write implemented
  • /internal/repository/registry/locations.go - Dual-write implemented
  • /internal/repository/registry/lots.go - Dual-write implemented
  • /internal/repository/registry/assets.go - Dual-write implemented (handles nullable location_sid)
  • /internal/repository/registry/components.go - Dual-write implemented (handles nullable lot_sid)
  • /internal/repository/registry/installations.go - Query updated to SELECT sid columns
  • /internal/repository/tickets/tickets.go - Upsert and LinkToAsset updated
  • /internal/repository/failures/failures.go - Upsert updated (handles nullable asset_sid)

Verification Completed

  • Migration 0010 applied successfully
  • All existing data backfilled with formatted IDs (CR-0000001, PJ-0000001, etc.)
  • All code compiles without errors
  • Database schema verified with sid columns present

API Layer Status

  • ⚠️ Not required - User confirmed backwards compatibility not needed
  • New records will have both id (int) and sid (string) in JSON responses
  • Future work: Can transition API to use string IDs as primary identifiers

Phase 3: Entity Renaming NOT STARTED

Breaking changes - requires maintenance window

  • Rename tables: assetsmachines, componentsparts
  • Rename columns: asset_idmachine_id, component_idpart_id, asset_tagmachine_tag
  • Update all foreign keys
  • Rename Go types and files
  • Update API routes with redirects
  • Update UI templates

Phase 4: Switch to String IDs Primary NOT STARTED

Breaking changes - requires maintenance window

  • Drop integer id columns
  • Promote sid to id
  • Update all foreign keys
  • Remove dual-write logic

Phase 5: Cleanup NOT STARTED

  • Remove temporary columns/indexes
  • Remove deprecated routes
  • Optimize indexes

Pattern for Repository Updates

Each repository needs this pattern:

// 1. Add to imports
import "reanimator/internal/idgen"

// 2. Update struct
type XRepository struct {
    db    *sql.DB
    idgen *idgen.Generator
}

// 3. Update constructor
func NewXRepository(db *sql.DB) *XRepository {
    return &XRepository{
        db:    db,
        idgen: idgen.NewGenerator(db),
    }
}

// 4. Update Create() - example for projects
func (r *XRepository) Create(ctx context.Context, ...) (domain.X, error) {
    // Generate SID
    sid, err := r.idgen.Generate(ctx, idgen.EntityType)
    if err != nil {
        return domain.X{}, err
    }

    // Lookup foreign key SIDs (if needed)
    var foreignSID string
    err = r.db.QueryRowContext(ctx, `SELECT sid FROM foreign_table WHERE id = ?`, foreignID).Scan(&foreignSID)
    if err != nil {
        return domain.X{}, classifyError(err)
    }

    // INSERT with both id (auto-increment) and sid
    result, err := r.db.ExecContext(ctx,
        `INSERT INTO table (sid, foreign_id, foreign_sid, ...) VALUES (?, ?, ?, ...)`,
        sid, foreignID, foreignSID, ...,
    )
    // ... rest of create logic
}

// 5. Update all SELECT statements to include sid and *_sid columns
// 6. Update all Scan() calls to include the new fields

Next Steps

  1. Complete Phase 2 repository updates (7 more repositories)
  2. Update API layer to accept both ID formats
  3. Apply migration 0010
  4. Test dual-write functionality
  5. Verify both integer and string IDs work in API

Migration Commands

# Apply Phase 2 migration
docker exec -i reanimator-mariadb mariadb -u reanimator -preanimator reanimator < migrations/0010_add_string_ids/up.sql

# Rollback if needed
docker exec -i reanimator-mariadb mariadb -u reanimator -preanimator reanimator < migrations/0010_add_string_ids/down.sql

Testing After Phase 2

# Run all tests
go test ./...

# Test ID generation
go test ./internal/idgen/... -v

# Create a customer via API
curl -X POST http://localhost:9999/customers -d '{"name": "Test Corp"}'
# Should return: {"id": 4, "sid": "CR-0000004", ...}

# Verify database
docker exec -i reanimator-mariadb mariadb -u reanimator -preanimator reanimator -e "SELECT id, sid, name FROM customers LIMIT 5"