summaryrefslogtreecommitdiff
path: root/internal/watcher
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-07 16:32:10 +0200
committerPaul Buetow <paul@buetow.org>2026-02-07 16:32:10 +0200
commit3fd46f3977fb650974e5e936cba362c787c00637 (patch)
treeb49111ddd0b7af4a007bca6a304dba10efcd88ff /internal/watcher
reimport this PoC
Diffstat (limited to 'internal/watcher')
-rw-r--r--internal/watcher/file_watcher.go86
1 files changed, 86 insertions, 0 deletions
diff --git a/internal/watcher/file_watcher.go b/internal/watcher/file_watcher.go
new file mode 100644
index 0000000..63ccb08
--- /dev/null
+++ b/internal/watcher/file_watcher.go
@@ -0,0 +1,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
+}