summaryrefslogtreecommitdiff
path: root/internal/watcher/file_watcher.go
blob: 63ccb0824df0ee642e9359824e7b4bcf75c0f76a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package watcher

import (
	"context"
	"fmt"
	"os"
	"time"
)

// FileWatcher monitors a file for changes based on modification time.
type FileWatcher struct {
	filePath       string
	pollInterval   time.Duration
	lastModTime    time.Time
}

// NewFileWatcher creates a new file watcher.
func NewFileWatcher(filePath string, pollInterval time.Duration) *FileWatcher {
	return &FileWatcher{
		filePath:     filePath,
		pollInterval: pollInterval,
	}
}

// Watch starts watching the file and returns a channel that signals changes.
// If the file doesn't exist yet, it will wait until it appears.
func (fw *FileWatcher) Watch(ctx context.Context) (<-chan struct{}, error) {
	changeChan := make(chan struct{}, 1)

	go func() {
		defer close(changeChan)
		ticker := time.NewTicker(fw.pollInterval)
		defer ticker.Stop()

		fileExists := false
		
		// Wait for file to exist
		for !fileExists {
			select {
			case <-ctx.Done():
				return
			case <-ticker.C:
				info, err := os.Stat(fw.filePath)
				if err != nil {
					// File doesn't exist yet, keep waiting
					fmt.Printf("Waiting for file to exist: %s\n", fw.filePath)
					continue
				}
				
				// File now exists!
				fileExists = true
				fw.lastModTime = info.ModTime()
				// Send initial change to process file
				changeChan <- struct{}{}
				fmt.Printf("File detected, starting watch: %s\n", fw.filePath)
			}
		}

		// Now watch for changes
		for {
			select {
			case <-ctx.Done():
				return
			case <-ticker.C:
				info, err := os.Stat(fw.filePath)
				if err != nil {
					// File might have been deleted or is temporarily unavailable
					continue
				}

				modTime := info.ModTime()
				if modTime.After(fw.lastModTime) {
					fw.lastModTime = modTime
					changeChan <- struct{}{}
				}
			}
		}
	}()

	return changeChan, nil
}

// GetLastModTime returns the last known modification time of the file.
func (fw *FileWatcher) GetLastModTime() time.Time {
	return fw.lastModTime
}