This repository has been archived by the owner on Mar 24, 2024. It is now read-only.
generated from yandex-praktikum/go-musthave-devops-tpl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
file_backed.go
127 lines (98 loc) · 2.97 KB
/
file_backed.go
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package storage
import (
"context"
"encoding/json"
"fmt"
"os"
"sync"
"github.com/rs/zerolog/log"
)
var _ Storage = (*FileBackedStorage)(nil)
// FileBackedStorage implements in-memory metrics storage with ability to
// dump/restore metrics data to/from disk.
type FileBackedStorage struct {
*MemStorage
sync.Mutex
// Path to backing file.
storePath string
// Dump recorded data on each push of a record.
syncMode bool
}
// NewFileBackedStorage creates new instance of FileBackedStorage.
func NewFileBackedStorage(storePath string, syncMode bool) *FileBackedStorage {
return &FileBackedStorage{
MemStorage: NewMemStorage(),
storePath: storePath,
syncMode: syncMode,
}
}
// Push records metric data.
func (f *FileBackedStorage) Push(ctx context.Context, key string, record Record) error {
if err := f.MemStorage.Push(ctx, key, record); err != nil {
return err
}
if f.syncMode {
return f.Dump(ctx)
}
return nil
}
// PushBatch records list of metrics data.
func (f *FileBackedStorage) PushBatch(ctx context.Context, data map[string]Record) error {
if err := f.MemStorage.PushBatch(ctx, data); err != nil {
return err
}
if f.syncMode {
return f.Dump(ctx)
}
return nil
}
// Close dumps all stored data to disk. The storage can be restored from this dump later.
func (f *FileBackedStorage) Close(ctx context.Context) error {
return f.Dump(ctx)
}
// Restore reads previously stored data from disk and populates the storage.
func (f *FileBackedStorage) Restore() (err error) {
f.Lock()
defer f.Unlock()
log.Info().Msg("Restoring storage data from " + f.storePath)
file, err := os.Open(f.storePath)
if err != nil {
if os.IsNotExist(err) {
log.Warn().Msg("No storage dump found, data restoration is not possible")
return nil
}
return fmt.Errorf("FileBackedStorage - Restore - os.Open: %w", err)
}
defer func() {
if dErr := file.Close(); err == nil && dErr != nil {
err = fmt.Errorf("FileBackedStorage - Restore - file.Close: %w", dErr)
}
}()
decoder := json.NewDecoder(file)
if err := decoder.Decode(f.MemStorage); err != nil {
return fmt.Errorf("FileBackedStorage - Restore - decoder.Decode: %w", err)
}
log.Info().Msg("Storage data was successfully restored")
return nil
}
// Dump writes all stored data to disk. The storage can be restored from this dump later.
func (f *FileBackedStorage) Dump(ctx context.Context) (err error) {
f.Lock()
defer f.Unlock()
log.Ctx(ctx).Info().Msg("Pushing storage data to " + f.storePath)
file, err := os.OpenFile(f.storePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return fmt.Errorf("FileBackedStorage - Dump - os.OpenFile: %w", err)
}
defer func() {
if dErr := file.Close(); err == nil && dErr != nil {
err = fmt.Errorf("FileBackedStorage - Dump - file.Close: %w", dErr)
}
}()
encoder := json.NewEncoder(file)
snapshot := f.Snapshot()
if err := encoder.Encode(snapshot); err != nil {
return fmt.Errorf("FileBackedStorage - Dump - encoder.Encode: %w", err)
}
return nil
}