force_reindex_test.go 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package nginx_log
  2. import (
  3. "sync"
  4. "testing"
  5. "time"
  6. )
  7. // TestForceReindexFileGroupSingleNotification tests that ForceReindexFileGroup only sends one completion notification per log group
  8. func TestForceReindexFileGroupSingleNotification(t *testing.T) {
  9. // This test simulates what happens in real scenario from your logs
  10. mainLogPath := "/var/log/nginx/access.log"
  11. // Test that IndexLogFileFull called with main log path works correctly
  12. // This mimics what ForceReindexFileGroup should do: queue one task per log group, not per file
  13. // Create a mock scenario where IndexLogFileFull is called directly with mainLogPath
  14. // This simulates the fix where ForceReindexFileGroup queues a single task
  15. logFiles := []struct {
  16. path string
  17. compressed bool
  18. lines int64
  19. }{
  20. {"/var/log/nginx/access.log", false, 1210},
  21. {"/var/log/nginx/access.log.1", false, 1505},
  22. {"/var/log/nginx/access.log.2.gz", true, 2975},
  23. {"/var/log/nginx/access.log.3.gz", true, 1541},
  24. {"/var/log/nginx/access.log.4.gz", true, 5612},
  25. {"/var/log/nginx/access.log.5.gz", true, 2389},
  26. }
  27. // This test validates that processing a complete log group results in only one completion notification
  28. // Test scenario: Single call to process entire log group
  29. // This is what should happen with the fix
  30. tracker := GetProgressTracker(mainLogPath)
  31. // Add all files to the progress tracker (simulating IndexLogFileFull discovery)
  32. for _, file := range logFiles {
  33. tracker.AddFile(file.path, file.compressed)
  34. tracker.SetFileEstimate(file.path, file.lines)
  35. }
  36. // Simulate concurrent processing of all files (like indexSingleFileForGroup would do)
  37. var wg sync.WaitGroup
  38. for i, file := range logFiles {
  39. wg.Add(1)
  40. go func(f struct {
  41. path string
  42. compressed bool
  43. lines int64
  44. }, index int) {
  45. defer wg.Done()
  46. // Simulate processing delay
  47. time.Sleep(time.Duration(index*50) * time.Millisecond)
  48. tracker.StartFile(f.path)
  49. // Simulate processing
  50. for progress := int64(100); progress <= f.lines; progress += 100 {
  51. tracker.UpdateFileProgress(f.path, progress)
  52. time.Sleep(time.Millisecond)
  53. }
  54. tracker.CompleteFile(f.path, f.lines)
  55. t.Logf("Completed processing file: %s (%d lines)", f.path, f.lines)
  56. }(file, i)
  57. }
  58. wg.Wait()
  59. // Allow time for all notifications to be processed
  60. time.Sleep(50 * time.Millisecond)
  61. // Verify final state
  62. percentage, stats := tracker.GetProgress()
  63. if percentage != 100 {
  64. t.Errorf("Expected 100%% progress, got %.2f%%", percentage)
  65. }
  66. if stats.CompletedFiles != 6 {
  67. t.Errorf("Expected 6 completed files, got %d", stats.CompletedFiles)
  68. }
  69. if !stats.IsCompleted {
  70. t.Errorf("Expected IsCompleted to be true")
  71. }
  72. expectedTotalLines := int64(1210 + 1505 + 2975 + 1541 + 5612 + 2389)
  73. if stats.ProcessedLines != expectedTotalLines {
  74. t.Errorf("Expected %d processed lines, got %d", expectedTotalLines, stats.ProcessedLines)
  75. }
  76. RemoveProgressTracker(mainLogPath)
  77. t.Logf("✅ SUCCESS: Single completion notification verified for log group with %d files", len(logFiles))
  78. }