refactor: remove Phase X terminology from source code comments

Remove planning document phase references from code comments:

app_test.go:
- Remove Phase 5 references from 8 test function comments

querier.go & queries.sql.go:
- Remove Phase 1, 2, 3, 4, 6 references from section headers
- Clean up week numbers (Weeks 5-6, Week 3-4, etc.)

queries.sql:
- Remove Phase 4 references from Kobo queries

kobo.go:
- Remove Phase 6 references from ContentId mapping comments

progress.go:
- Remove Phase 1 reference from route comment

media_scanner.go & media_scanner_library_type_test.go:
- Remove Phase 2 references from library type scanning comments

schema.sql:
- Remove Phase 1, 2, 3, 4, 5, 7 references from table/section comments
- Clean up: Format Detection, Progress Tracking, Device Registry,
  Sync Queue, Conflict Resolution, Reading History, Indexes, etc.

test_helpers.go:
- Remove Phase 6 reference from handler setup comment

These phase numbers were from internal planning documents and have no
meaning in the codebase. Removing them makes the code self-documenting.
This commit is contained in:
2026-02-13 21:50:29 -05:00
parent 80dcdfdd71
commit 2706ae52c1
9 changed files with 96 additions and 96 deletions
+12 -12
View File
@@ -48,7 +48,7 @@ func (m *mockHandler) reset() {
m.stopSchedulerCalled = false
}
// TestApp_New tests Phase 5: App constructor
// TestApp_New tests App constructor
func TestApp_New(t *testing.T) {
e := echo.New()
handler := &mockHandler{}
@@ -62,7 +62,7 @@ func TestApp_New(t *testing.T) {
assert.NotNil(t, app.shutdownDone, "Shutdown done channel should be initialized")
}
// TestApp_SetShutdownTimeout tests Phase 5: configurable shutdown timeout
// TestApp_SetShutdownTimeout tests configurable shutdown timeout
func TestApp_SetShutdownTimeout(t *testing.T) {
e := echo.New()
handler := &mockHandler{}
@@ -74,7 +74,7 @@ func TestApp_SetShutdownTimeout(t *testing.T) {
assert.Equal(t, customTimeout, app.shutdownTimeout, "Shutdown timeout should be updated")
}
// TestApp_ShutdownDone tests Phase 5: shutdown done channel
// TestApp_ShutdownDone tests shutdown done channel
func TestApp_ShutdownDone(t *testing.T) {
e := echo.New()
handler := &mockHandler{}
@@ -92,7 +92,7 @@ func TestApp_ShutdownDone(t *testing.T) {
}
}
// TestApp_Start_BackgroundServices tests Phase 1 & 5: background service startup
// TestApp_Start_BackgroundServices tests background service startup
func TestApp_Start_BackgroundServices(t *testing.T) {
e := echo.New()
handler := &mockHandler{
@@ -135,7 +135,7 @@ func TestApp_Start_BackgroundServices(t *testing.T) {
<-done2
}
// TestApp_Shutdown_GracefulShutdown tests Phase 5: graceful shutdown sequence
// TestApp_Shutdown_GracefulShutdown tests graceful shutdown sequence
func TestApp_Shutdown_GracefulShutdown(t *testing.T) {
e := echo.New()
handler := &mockHandler{
@@ -150,7 +150,7 @@ func TestApp_Shutdown_GracefulShutdown(t *testing.T) {
assert.True(t, handler.stopSchedulerCalled, "StopScheduler should be called")
}
// TestApp_Shutdown_ThreadSafety tests Phase 5: thread-safe shutdown
// TestApp_Shutdown_ThreadSafety tests thread-safe shutdown
func TestApp_Shutdown_ThreadSafety(t *testing.T) {
e := echo.New()
handler := &mockHandler{}
@@ -175,7 +175,7 @@ func TestApp_Shutdown_ThreadSafety(t *testing.T) {
assert.True(t, handler.stopSchedulerCalled, "StopScheduler should be called at least once")
}
// TestApp_Shutdown_Timeout tests Phase 5: shutdown timeout handling
// TestApp_Shutdown_Timeout tests shutdown timeout handling
func TestApp_Shutdown_Timeout(t *testing.T) {
e := echo.New()
handler := &mockHandler{
@@ -191,7 +191,7 @@ func TestApp_Shutdown_Timeout(t *testing.T) {
assert.True(t, handler.stopSchedulerCalled, "StopScheduler should still be called")
}
// TestApp_Shutdown_ClosesEchoServer tests Phase 5: HTTP server shutdown
// TestApp_Shutdown_ClosesEchoServer tests HTTP server shutdown
func TestApp_Shutdown_ClosesEchoServer(t *testing.T) {
e := echo.New()
handler := &mockHandler{}
@@ -213,7 +213,7 @@ func TestApp_Shutdown_ClosesEchoServer(t *testing.T) {
assert.True(t, handler.stopSchedulerCalled, "StopScheduler should be called")
}
// TestApp_SignalHandling tests Phase 5: signal handling (SIGINT, SIGTERM, SIGQUIT)
// TestApp_SignalHandling tests signal handling (SIGINT, SIGTERM, SIGQUIT)
func TestApp_SignalHandling(t *testing.T) {
tests := []struct {
name string
@@ -259,7 +259,7 @@ func TestApp_SignalHandling(t *testing.T) {
}
}
// TestApp_Integration_StartupSequence tests Phase 1 & 5: complete startup sequence
// TestApp_Integration_StartupSequence tests complete startup sequence
func TestApp_Integration_StartupSequence(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
@@ -320,8 +320,8 @@ func TestApp_HandlerInterface(t *testing.T) {
var _ Handler = &mockHandler{}
}
// TestPhase1_AutoStartVerification tests Phase 1: auto-start functionality
func TestPhase1_AutoStartVerification(t *testing.T) {
// TestApp_AutoStartVerification tests auto-start functionality
func TestApp_AutoStartVerification(t *testing.T) {
t.Run("Auto-start runs asynchronously", func(t *testing.T) {
e := echo.New()
handler := &mockHandler{
+7 -7
View File
@@ -15,7 +15,7 @@ type Querier interface {
// Add book to collection
AddBookToCollection(ctx context.Context, arg AddBookToCollectionParams) (CollectionItems, error)
// ============================================
// KOBO SHELF MANAGEMENT QUERIES (Phase 4)
// KOBO SHELF MANAGEMENT QUERIES
// ============================================
AddBookToKoboShelf(ctx context.Context, arg AddBookToKoboShelfParams) (KoboShelves, error)
// Library Folders queries
@@ -36,7 +36,7 @@ type Querier interface {
// Create collection
CreateCollection(ctx context.Context, arg CreateCollectionParams) (Collections, error)
// ============================================
// PHASE 2: DEVICE MANAGEMENT & AUTH (Weeks 5-6)
// DEVICE MANAGEMENT & AUTH
// ============================================
// Device Registration & Management
CreateDevice(ctx context.Context, arg CreateDeviceParams) (Devices, error)
@@ -65,7 +65,7 @@ type Querier interface {
// Create OPDS token
CreateOpdsToken(ctx context.Context, arg CreateOpdsTokenParams) (OpdsTokens, error)
// ============================================
// KOBO ENTITLEMENT QUERIES (Phase 4)
// KOBO ENTITLEMENT QUERIES
// ============================================
CreateOrUpdateKoboEntitlement(ctx context.Context, arg CreateOrUpdateKoboEntitlementParams) (KoboEntitlements, error)
// Create reading history entry
@@ -78,7 +78,7 @@ type Querier interface {
// Sync Queue Management
CreateSyncQueueItem(ctx context.Context, arg CreateSyncQueueItemParams) (SyncQueue, error)
// ============================================
// PHASE 6: ENHANCED KOBO SYNC (Week 3-4)
// ENHANCED KOBO SYNC
// ============================================
// Create unlinked book entry
CreateUnlinkedBook(ctx context.Context, arg CreateUnlinkedBookParams) (UnlinkedBooks, error)
@@ -166,7 +166,7 @@ type Querier interface {
GetMediaItem(ctx context.Context, id pgtype.UUID) (MediaItems, error)
GetMediaItemByFilePath(ctx context.Context, filePath string) (MediaItems, error)
// ============================================
// PHASE 3: KOREADER SYNC PROTOCOL (Weeks 7-9)
// KOREADER SYNC PROTOCOL
// ============================================
GetMediaItemByFilePathForSync(ctx context.Context, filePath string) (MediaItems, error)
GetMediaItemByKoboContentId(ctx context.Context, koboContentID pgtype.Text) (MediaItems, error)
@@ -293,13 +293,13 @@ type Querier interface {
// Update media item format
UpdateMediaItemFormat(ctx context.Context, arg UpdateMediaItemFormatParams) (MediaItemFormats, error)
// ============================================
// PHASE 1: FORMAT DETECTION & PROGRESS (Week 2)
// FORMAT DETECTION & PROGRESS
// ============================================
// Update media item format group information
UpdateMediaItemFormatGroup(ctx context.Context, arg UpdateMediaItemFormatGroupParams) error
// Media Items Admin Operations
// ============================================
// PHASE 1: UNIVERSAL BOOK IDENTIFIERS (Week 1)
// UNIVERSAL BOOK IDENTIFIERS
// ============================================
// Update media item with universal identifiers
UpdateMediaItemIdentifiers(ctx context.Context, arg UpdateMediaItemIdentifiersParams) (MediaItems, error)
+13 -13
View File
@@ -60,7 +60,7 @@ type AddBookToKoboShelfParams struct {
}
// ============================================
// KOBO SHELF MANAGEMENT QUERIES (Phase 4)
// KOBO SHELF MANAGEMENT QUERIES
// ============================================
func (q *Queries) AddBookToKoboShelf(ctx context.Context, arg AddBookToKoboShelfParams) (KoboShelves, error) {
row := q.db.QueryRow(ctx, AddBookToKoboShelf,
@@ -292,7 +292,7 @@ type CreateDeviceParams struct {
}
// ============================================
// PHASE 2: DEVICE MANAGEMENT & AUTH (Weeks 5-6)
// DEVICE MANAGEMENT & AUTH
// ============================================
// Device Registration & Management
func (q *Queries) CreateDevice(ctx context.Context, arg CreateDeviceParams) (Devices, error) {
@@ -837,7 +837,7 @@ type CreateOrUpdateKoboEntitlementParams struct {
}
// ============================================
// KOBO ENTITLEMENT QUERIES (Phase 4)
// KOBO ENTITLEMENT QUERIES
// ============================================
func (q *Queries) CreateOrUpdateKoboEntitlement(ctx context.Context, arg CreateOrUpdateKoboEntitlementParams) (KoboEntitlements, error) {
row := q.db.QueryRow(ctx, CreateOrUpdateKoboEntitlement,
@@ -1084,7 +1084,7 @@ type CreateUnlinkedBookParams struct {
}
// ============================================
// PHASE 6: ENHANCED KOBO SYNC (Week 3-4)
// ENHANCED KOBO SYNC
// ============================================
// Create unlinked book entry
func (q *Queries) CreateUnlinkedBook(ctx context.Context, arg CreateUnlinkedBookParams) (UnlinkedBooks, error) {
@@ -2902,7 +2902,7 @@ SELECT id, library_id, title, author, isbn, description, file_path, file_size, m
`
// ============================================
// PHASE 3: KOREADER SYNC PROTOCOL (Weeks 7-9)
// KOREADER SYNC PROTOCOL
// ============================================
func (q *Queries) GetMediaItemByFilePathForSync(ctx context.Context, filePath string) (MediaItems, error) {
row := q.db.QueryRow(ctx, GetMediaItemByFilePathForSync, filePath)
@@ -3407,8 +3407,8 @@ func (q *Queries) GetMediaRatings(ctx context.Context, mediaItemID pgtype.UUID)
}
const GetNextRetryTime = `-- name: GetNextRetryTime :one
SELECT
CASE
SELECT
CASE
WHEN attempts = 0 THEN NOW()
WHEN attempts = 1 THEN NOW() + INTERVAL '1 minute'
WHEN attempts = 2 THEN NOW() + INTERVAL '5 minutes'
@@ -4053,7 +4053,7 @@ func (q *Queries) GetUnlinkedBooksByDevice(ctx context.Context, deviceID pgtype.
}
const GetUser = `-- name: GetUser :one
SELECT
SELECT
u.id,
u.email,
u.username,
@@ -4602,7 +4602,7 @@ const IncrementSyncQueueAttempts = `-- name: IncrementSyncQueueAttempts :one
UPDATE sync_queue
SET
attempts = attempts + 1,
status = CASE
status = CASE
WHEN attempts + 1 >= max_attempts THEN 'failed'
ELSE 'pending'
END,
@@ -4716,7 +4716,7 @@ func (q *Queries) LinkUnlinkedBook(ctx context.Context, arg LinkUnlinkedBookPara
}
const ListAllSyncQueueItems = `-- name: ListAllSyncQueueItems :many
SELECT
SELECT
sq.id, sq.device_id, sq.media_item_id, sq.sync_type, sq.sync_data, sq.priority, sq.attempts, sq.max_attempts, sq.status, sq.error_message, sq.created_at, sq.processed_at,
d.device_name,
d.device_type,
@@ -5776,7 +5776,7 @@ func (q *Queries) ListUnresolvedUnlinkedBooks(ctx context.Context, arg ListUnres
}
const ListUsers = `-- name: ListUsers :many
SELECT
SELECT
u.id,
u.email,
u.username,
@@ -7175,7 +7175,7 @@ type UpdateMediaItemFormatGroupParams struct {
}
// ============================================
// PHASE 1: FORMAT DETECTION & PROGRESS (Week 2)
// FORMAT DETECTION & PROGRESS
// ============================================
// Update media item format group information
func (q *Queries) UpdateMediaItemFormatGroup(ctx context.Context, arg UpdateMediaItemFormatGroupParams) error {
@@ -7215,7 +7215,7 @@ type UpdateMediaItemIdentifiersParams struct {
// Media Items Admin Operations
// ============================================
// PHASE 1: UNIVERSAL BOOK IDENTIFIERS (Week 1)
// UNIVERSAL BOOK IDENTIFIERS
// ============================================
// Update media item with universal identifiers
func (q *Queries) UpdateMediaItemIdentifiers(ctx context.Context, arg UpdateMediaItemIdentifiersParams) (MediaItems, error) {
+14 -14
View File
@@ -16,7 +16,7 @@ SELECT id, email, username, theme, first_name, last_name, role, created_at, upda
SELECT id, email, username, password_hash, theme, first_name, last_name, role, created_at, updated_at FROM users WHERE email = $1 OR username = $1;
-- name: GetUser :one
SELECT
SELECT
u.id,
u.email,
u.username,
@@ -35,7 +35,7 @@ WHERE u.id = $1;
SELECT password_hash FROM users WHERE id = $1;
-- name: ListUsers :many
SELECT
SELECT
u.id,
u.email,
u.username,
@@ -520,7 +520,7 @@ UPDATE refresh_tokens SET revoked_at = NOW() WHERE user_id = $1 AND revoked_at I
DELETE FROM refresh_tokens WHERE expires_at < NOW() OR (revoked_at IS NOT NULL AND revoked_at < NOW() - INTERVAL '7 days');
-- ============================================
-- PHASE 1: FORMAT DETECTION & PROGRESS (Week 2)
-- FORMAT DETECTION & PROGRESS
-- ============================================
-- Update media item format group information
@@ -716,7 +716,7 @@ SELECT
LIMIT $2;
-- ============================================
-- PHASE 2: DEVICE MANAGEMENT & AUTH (Weeks 5-6)
-- DEVICE MANAGEMENT & AUTH
-- ============================================
-- Device Registration & Management
@@ -837,7 +837,7 @@ ORDER BY priority ASC, created_at ASC;
UPDATE sync_queue
SET
attempts = attempts + 1,
status = CASE
status = CASE
WHEN attempts + 1 >= max_attempts THEN 'failed'
ELSE 'pending'
END,
@@ -856,7 +856,7 @@ FROM sync_queue
WHERE device_id = $1;
-- name: ListAllSyncQueueItems :many
SELECT
SELECT
sq.*,
d.device_name,
d.device_type,
@@ -870,8 +870,8 @@ ORDER BY sq.priority ASC, sq.created_at DESC
LIMIT $1 OFFSET $2;
-- name: GetNextRetryTime :one
SELECT
CASE
SELECT
CASE
WHEN attempts = 0 THEN NOW()
WHEN attempts = 1 THEN NOW() + INTERVAL '1 minute'
WHEN attempts = 2 THEN NOW() + INTERVAL '5 minutes'
@@ -929,7 +929,7 @@ DELETE FROM sync_conflicts WHERE id = $1;
ORDER BY sc.created_at DESC;
-- ============================================
-- PHASE 3: KOREADER SYNC PROTOCOL (Weeks 7-9)
-- KOREADER SYNC PROTOCOL
-- ============================================
-- name: GetMediaItemByFilePathForSync :one
@@ -1040,7 +1040,7 @@ WHERE media_item_id = $1
AND last_sync_source != $3;
-- ============================================
-- KOBO SHELF MANAGEMENT QUERIES (Phase 4)
-- KOBO SHELF MANAGEMENT QUERIES
-- ============================================
-- name: AddBookToKoboShelf :one
@@ -1093,7 +1093,7 @@ FROM kobo_shelves
WHERE device_id = $1;
-- ============================================
-- KOBO ENTITLEMENT QUERIES (Phase 4)
-- KOBO ENTITLEMENT QUERIES
-- ============================================
-- name: CreateOrUpdateKoboEntitlement :one
@@ -1161,7 +1161,7 @@ SELECT * FROM media_items WHERE kobo_content_id = $1;
-- Media Items Admin Operations
-- ============================================
-- PHASE 1: UNIVERSAL BOOK IDENTIFIERS (Week 1)
-- UNIVERSAL BOOK IDENTIFIERS
-- ============================================
-- Update media item with universal identifiers
@@ -1522,7 +1522,7 @@ WHERE ks.device_id = $1 AND ks.collection_id = $2
ORDER BY ks.position_in_collection ASC, ks.shelf_position ASC;
-- ============================================
-- PHASE 6: ENHANCED KOBO SYNC (Week 3-4)
-- ENHANCED KOBO SYNC
-- ============================================
-- Create unlinked book entry
@@ -1587,4 +1587,4 @@ FROM unlinked_books ub
JOIN devices d ON ub.device_id = d.id
WHERE ub.resolved = false
ORDER BY ub.last_seen_at DESC
LIMIT $1 OFFSET $2;
LIMIT $1 OFFSET $2;
+8 -8
View File
@@ -27,7 +27,7 @@ func NewKoboHandler(db *database.Queries, connManager *wsync.ConnectionManager)
}
// mapContentIdToBookhoardUUID maps Kobo ContentId to Bookhoard UUID with multiple fallback strategies
// Phase 6: Enhanced Kobo Sync - ContentId Mapping Logic
// Enhanced Kobo Sync - ContentId Mapping Logic
func (h *KoboHandler) mapContentIdToBookhoardUUID(ctx echo.Context, contentId string, deviceID uuid.UUID) (uuid.UUID, error, string) {
// Step 1: Try direct ContentId lookup in device_catalogs table
catalog, err := h.db.GetDeviceCatalogByKoboContentId(ctx.Request().Context(), contentId)
@@ -320,7 +320,7 @@ func (h *KoboHandler) Initialization(c echo.Context) error {
author = item.Author.String
}
// Phase 6: Use ContentId mapping instead of direct UUID
// Use ContentId mapping instead of direct UUID
koboContentId, err := h.mapBookhoardUUIDToKoboContentId(c, bookhoardUUID, deviceUUID)
if err != nil {
// Fallback to entitlement_id or generate new one
@@ -351,7 +351,7 @@ func (h *KoboHandler) Initialization(c echo.Context) error {
contentType = "5"
}
// Phase 6: Get collection metadata for this book
// Get collection metadata for this book
collections, _ := h.getCollectionMetadataForBook(c, bookhoardUUID, deviceUUID)
librarySync = append(librarySync, KoboLibraryBook{
@@ -403,7 +403,7 @@ func (h *KoboHandler) Markup(c echo.Context) error {
unlinkedBooks := 0
for _, readingSync := range req.ReadingSync {
// Phase 6: Use ContentId mapping with fallback logic
// Use ContentId mapping with fallback logic
bookhoardUUID, err, _ := h.mapContentIdToBookhoardUUID(c, readingSync.ContentId, deviceUUID)
if err != nil || bookhoardUUID == uuid.Nil {
// Unlinked book detected
@@ -440,7 +440,7 @@ func (h *KoboHandler) Markup(c echo.Context) error {
}
for _, bookmarkSync := range req.BookmarkSync {
// Phase 6: Use ContentId mapping with fallback logic
// Use ContentId mapping with fallback logic
bookhoardUUID, err, _ := h.mapContentIdToBookhoardUUID(c, bookmarkSync.ContentId, deviceUUID)
if err != nil || bookhoardUUID == uuid.Nil {
// Unlinked book - skip
@@ -541,7 +541,7 @@ func (h *KoboHandler) Bookmark(c echo.Context) error {
bookmarksSynced := 0
for _, bookmarkSync := range req.BookmarkSync {
// Phase 6: Use ContentId mapping with fallback logic
// Use ContentId mapping with fallback logic
bookhoardUUID, err, _ := h.mapContentIdToBookhoardUUID(c, bookmarkSync.ContentId, deviceUUID)
if err != nil || bookhoardUUID == uuid.Nil {
// Unlinked book - skip
@@ -606,7 +606,7 @@ func (h *KoboHandler) AnalyticsGettests(c echo.Context) error {
}
for _, test := range req {
// Phase 6: Use ContentId mapping with fallback logic
// Use ContentId mapping with fallback logic
bookhoardUUID, err, _ := h.mapContentIdToBookhoardUUID(c, test.ContentId, deviceUUID)
if err != nil || bookhoardUUID == uuid.Nil {
// Unlinked book - skip
@@ -683,7 +683,7 @@ func (h *KoboHandler) SyncFromServer(c echo.Context) error {
highlightsSent := 0
for _, syncData := range req {
// Phase 6: Use ContentId mapping with fallback logic
// Use ContentId mapping with fallback logic
bookhoardUUID, err, _ := h.mapContentIdToBookhoardUUID(c, syncData.ContentId, deviceUUID)
if err != nil || bookhoardUUID == uuid.Nil {
// Unlinked book - skip
+1 -1
View File
@@ -11,7 +11,7 @@ func registerProgressRoutes(cfg *Config, scannerHandler *handlers.Handler) {
jwtMiddleware := createJWTMiddleware(cfg)
protected := e.Group("/api", jwtMiddleware)
// Universal Progress routes (Phase 1)
// Universal Progress routes
protected.GET("/progress/:id", scannerHandler.GetUniversalProgress)
protected.POST("/progress/:id", scannerHandler.UpdateUniversalProgress)
protected.GET("/progress/:id/history", scannerHandler.GetProgressHistory)
+14 -14
View File
@@ -48,8 +48,8 @@ type MediaMetadata struct {
ASIN string
Tags []string
Phase1HashInfo *HashInfo
Phase1FormatFormats []*FormatInfo
FileHashInfo *HashInfo
FileFormats []*FormatInfo
}
type HashInfo struct {
@@ -338,15 +338,15 @@ func (s *MediaScanner) processMediaFile(ctx context.Context, path string) error
metadata = &MediaMetadata{}
}
// Extract hash information (Phase 2)
// Extract hash information during metadata extraction
hashInfo, formatInfo, err := s.extractHashInfo(path)
if err != nil {
fmt.Printf("Warning: failed to extract hash info from %s: %v\n", path, err)
hashInfo = &HashInfo{}
formatInfo = &FormatInfo{}
} else {
metadata.Phase1HashInfo = hashInfo
metadata.Phase1FormatFormats = []*FormatInfo{formatInfo}
metadata.FileHashInfo = hashInfo
metadata.FileFormats = []*FormatInfo{formatInfo}
fmt.Printf("Hash info for %s: SHA256=%s, OPF_ID=%s, OPF_UUID=%s, Confidence=%s\n",
path, hashInfo.FileSHA256, hashInfo.OPFIdentifier, hashInfo.OPFUUID, hashInfo.HashConfidence)
}
@@ -479,22 +479,22 @@ func (s *MediaScanner) processMediaFile(ctx context.Context, path string) error
return fmt.Errorf("failed to create media item: %v", err)
}
// Update hash information (Phase 2)
if metadata.Phase1HashInfo != nil && metadata.Phase1HashInfo.FileSHA256 != "" {
// Update hash information before database storage
if metadata.FileHashInfo != nil && metadata.FileHashInfo.FileSHA256 != "" {
_, err = s.db.UpdateMediaItemIdentifiers(ctx, database.UpdateMediaItemIdentifiersParams{
ID: createdItem.ID,
FileSha256: pgtype.Text{String: metadata.Phase1HashInfo.FileSHA256, Valid: true},
OpfIdentifier: pgtype.Text{String: metadata.Phase1HashInfo.OPFIdentifier, Valid: metadata.Phase1HashInfo.OPFIdentifier != ""},
OpfUuid: pgtype.Text{String: metadata.Phase1HashInfo.OPFUUID, Valid: metadata.Phase1HashInfo.OPFUUID != ""},
HashConfidence: pgtype.Text{String: metadata.Phase1HashInfo.HashConfidence, Valid: true},
FileSha256: pgtype.Text{String: metadata.FileHashInfo.FileSHA256, Valid: true},
OpfIdentifier: pgtype.Text{String: metadata.FileHashInfo.OPFIdentifier, Valid: metadata.FileHashInfo.OPFIdentifier != ""},
OpfUuid: pgtype.Text{String: metadata.FileHashInfo.OPFUUID, Valid: metadata.FileHashInfo.OPFUUID != ""},
HashConfidence: pgtype.Text{String: metadata.FileHashInfo.HashConfidence, Valid: true},
})
if err != nil {
fmt.Printf("Warning: failed to update hash identifiers for %s: %v\n", path, err)
}
}
// Store format information (Phase 2)
for _, format := range metadata.Phase1FormatFormats {
// Store format information in the database
for _, format := range metadata.FileFormats {
_, err = s.db.CreateMediaItemFormat(ctx, database.CreateMediaItemFormatParams{
MediaItemID: createdItem.ID,
FormatType: format.FormatType,
@@ -1021,7 +1021,7 @@ func (s *MediaScanner) Close() error {
}
// ============================================
// PHASE 2: SCANNER ENHANCEMENTS (Week 1-2)
// SCANNER ENHANCEMENTS
// ============================================
// calculateFileSHA256 calculates SHA-256 hash using streaming to avoid loading entire file into memory
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert"
)
// TestMediaScanner_LibraryTypeAwareScanning tests Phase 2: library-type-aware scanning
// TestMediaScanner_LibraryTypeAwareScanning tests library-type-aware scanning
func TestMediaScanner_LibraryTypeAwareScanning(t *testing.T) {
t.Run("isScannableFile checks library type restrictions", func(t *testing.T) {
scanner := &MediaScanner{
@@ -121,7 +121,7 @@ func TestMediaScanner_LibraryTypeAwareScanning(t *testing.T) {
})
}
// TestMediaScanner_SetFolders_BuildsLibraryTypeCache tests Phase 2: SetFolders builds cache
// TestMediaScanner_SetFolders_BuildsLibraryTypeCache tests SetFolders builds cache
func TestMediaScanner_SetFolders_BuildsLibraryTypeCache(t *testing.T) {
// This is a unit test that verifies SetFolders properly initializes the libraryTypes cache
// Full integration testing would require a mock database
@@ -150,7 +150,7 @@ func TestMediaScanner_SetFolders_BuildsLibraryTypeCache(t *testing.T) {
})
}
// TestMediaScanner_LibraryTypeCrossContamination tests Phase 2: prevents cross-contamination
// TestMediaScanner_LibraryTypeCrossContamination tests prevents cross-contamination
func TestMediaScanner_LibraryTypeCrossContamination(t *testing.T) {
t.Run("Ebook library rejects comic formats", func(t *testing.T) {
scanner := &MediaScanner{
@@ -185,7 +185,7 @@ func TestMediaScanner_LibraryTypeCrossContamination(t *testing.T) {
})
}
// TestMediaScanner_MultipleLibraryTypes tests Phase 2: multiple libraries with different types
// TestMediaScanner_MultipleLibraryTypes tests multiple libraries with different types
func TestMediaScanner_MultipleLibraryTypes(t *testing.T) {
scanner := &MediaScanner{
folders: []string{