1
- // Copyright © 2023 Kaleido, Inc.
1
+ // Copyright © 2024 Kaleido, Inc.
2
2
//
3
3
// SPDX-License-Identifier: Apache-2.0
4
4
//
@@ -20,6 +20,7 @@ import (
20
20
"context"
21
21
"os"
22
22
"path"
23
+ "time"
23
24
24
25
"github.com/fsnotify/fsnotify"
25
26
"github.com/hyperledger/firefly-common/pkg/fftypes"
@@ -35,9 +36,19 @@ import (
35
36
// - Only fires if the data in the file is different to the last notification
36
37
// - Does not reload the config - that's the caller's responsibility
37
38
func Watch (ctx context.Context , fullFilePath string , onChange , onClose func ()) error {
39
+ return sync (ctx , fullFilePath , onChange , onClose , nil , nil )
40
+ }
41
+
42
+ // Reconcile behaves the same as Watch, except it allows for running the onSync func on a provided
43
+ // interval. The default re-sync internal is 1m.
44
+ func Reconcile (ctx context.Context , fullFilePath string , onChange , onClose , onSync func (), resyncInterval * time.Duration ) error {
45
+ return sync (ctx , fullFilePath , onChange , onClose , onSync , resyncInterval )
46
+ }
47
+
48
+ func sync (ctx context.Context , fullFilePath string , onChange , onClose , onSync func (), resyncInterval * time.Duration ) error {
38
49
filePath := path .Dir (fullFilePath )
39
50
fileName := path .Base (fullFilePath )
40
- log .L (ctx ).Debugf ("Starting file listener for '%s' in directory '%s'" , fileName , filePath )
51
+ log .L (ctx ).Debugf ("Starting file reconciler for '%s' in directory '%s'" , fileName , filePath )
41
52
42
53
watcher , err := fsnotify .NewWatcher ()
43
54
if err == nil {
@@ -46,7 +57,7 @@ func Watch(ctx context.Context, fullFilePath string, onChange, onClose func()) e
46
57
if onClose != nil {
47
58
onClose ()
48
59
}
49
- }, watcher .Events , watcher .Errors )
60
+ }, onSync , resyncInterval , watcher .Events , watcher .Errors )
50
61
err = watcher .Add (filePath )
51
62
}
52
63
if err != nil {
@@ -56,9 +67,18 @@ func Watch(ctx context.Context, fullFilePath string, onChange, onClose func()) e
56
67
return nil
57
68
}
58
69
59
- func fsListenerLoop (ctx context.Context , fullFilePath string , onChange , onClose func (), events chan fsnotify.Event , errors chan error ) {
70
+ func fsListenerLoop (ctx context.Context , fullFilePath string , onChange , onClose , onSync func (), resyncInterval * time. Duration , events chan fsnotify.Event , errors chan error ) {
60
71
defer onClose ()
61
72
73
+ timeout := resyncInterval
74
+ if timeout == nil {
75
+ timeout = func () * time.Duration {
76
+ defaultTimeout := time .Minute
77
+ return & defaultTimeout
78
+ }()
79
+ }
80
+ log .L (ctx ).Debugf ("re-sync interval set to '%s'" , * timeout )
81
+
62
82
var lastHash * fftypes.Bytes32
63
83
for {
64
84
select {
@@ -83,6 +103,15 @@ func fsListenerLoop(ctx context.Context, fullFilePath string, onChange, onClose
83
103
lastHash = dataHash
84
104
}
85
105
}
106
+ case <- time .After (* timeout ):
107
+ if onSync != nil {
108
+ data , err := os .ReadFile (fullFilePath )
109
+ if err == nil {
110
+ dataHash := fftypes .HashString (string (data ))
111
+ log .L (ctx ).Infof ("Config file re-sync. Event=Resync Name=%s Size=%d Hash=%s" , fullFilePath , len (data ), dataHash )
112
+ onSync ()
113
+ }
114
+ }
86
115
case err , ok := <- errors :
87
116
if ok {
88
117
log .L (ctx ).Errorf ("FSEvent error: %s" , err )
0 commit comments