Documentation ¶
Overview ¶
Package file provides some easy to use methods for caching file information.
The contents of a file may be cached, with automatic invalidation provided with the github.com/fsnotify/fsnotify library. The actual file bytes may be used with NewFileCache or NewEagerFileCache.
Alternatively, reading the file's contents and decoding it can be combined into a single function with NewReaderCache. The Value returned will store the decoded form for easy retrieval.
If you need to perform some action in response to the file being changed, then use OnInvalidate on the Value returned from any of these functions.
Index ¶
- func NewEagerFileCache(ctx context.Context, filename string, log NotifyLog) (*cache.Value[[]byte], error)
- func NewFileCache(ctx context.Context, filename string, log NotifyLog) (*cache.Value[[]byte], error)
- func NewReaderCache[T any](ctx context.Context, filename string, readFunc func(io.Reader) (T, error), ...) (*cache.Value[T], error)
- type NotifyLog
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewEagerFileCache ¶
func NewEagerFileCache(ctx context.Context, filename string, log NotifyLog) (*cache.Value[[]byte], error)
NewEagerFileCache is the same as NewFileCache, except that it will proactively read the file's contents into memory.
func NewFileCache ¶
func NewFileCache(ctx context.Context, filename string, log NotifyLog) (*cache.Value[[]byte], error)
NewFileCache creates a new cache.Value that reads the given file in its loader.
func NewReaderCache ¶
func NewReaderCache[T any](ctx context.Context, filename string, readFunc func(io.Reader) (T, error), log NotifyLog) (*cache.Value[T], error)
NewReaderCache returns a cache of a type extracted from the watched file. Whatever type is produced from readFunc will be the type of the cache.Value, which makes this useful for unmarshalling a file's contents into a user defined type.
Example ¶
dir, cleanup := _mkTmp() defer cleanup() dataFile := filepath.Join(dir, "test.json") type myData struct { A string `json:"a"` B string `json:"b"` } err := os.WriteFile(dataFile, []byte(`{"a":"a","b":"b"}`), 0644) if err != nil { panic(err) } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) val, err := NewReaderCache[myData](ctx, dataFile, func(reader io.Reader) (myData, error) { var data myData err := json.NewDecoder(reader).Decode(&data) return data, err }, StdLog()) val.OnInvalidate(func() { fmt.Println("data invalidated") cancel() }) data, err := val.Get() if err != nil { panic(err) } fmt.Printf("A:%s,B:%s\n", data.A, data.B) val.Invalidate() <-ctx.Done() if !errors.Is(ctx.Err(), context.Canceled) { panic("Context should have been cancelled") }
Output: A:a,B:b data invalidated
Types ¶
type NotifyLog ¶
NotifyLog provides a way for filesystem changes to be logged. This allows for easily plugging in your logger of choice.
func StdLog ¶
func StdLog() NotifyLog
StdLog creates an instance of NotifyLog that uses the standard log package. Unrelated events will not be logged.
Example ¶
package main import ( "errors" "github.com/fsnotify/fsnotify" "testing" ) var _ NotifyLog = (*testNotifyLog)(nil) type testNotifyLog struct { t *testing.T failOnError bool } func testingLog(t *testing.T) NotifyLog { return &testNotifyLog{t: t, failOnError: true} } func (t *testNotifyLog) Event(event fsnotify.Event) { t.t.Logf("Received event [%s] %s", event.Op.String(), event.Name) } func (t *testNotifyLog) UnrelatedEvent(event fsnotify.Event) { t.t.Logf("Received unrelated event [%s] %s", event.Op.String(), event.Name) } func (t *testNotifyLog) Error(err error) { var log func(msg string, args ...any) if t.failOnError { log = t.t.Errorf } else { log = t.t.Logf } log("Error: %v", err) } func main() { log := StdLog() // Called by the fsnotify goroutine when a filesystem event is dispatched. log.Event(fsnotify.Event{ Name: "some-file.txt", Op: fsnotify.Write, }) // Called by the fsnotify goroutine. log.Error(errors.New("something bad happened")) }
Output: