forked from gaffo/jorb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
serializer.go
132 lines (113 loc) · 3.94 KB
/
serializer.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
128
129
130
131
132
package jorb
import (
"bytes"
"encoding/json"
"io"
"log/slog"
"os"
"path/filepath"
"time"
)
// Serializer is an interface for job run seralization
type Serializer[OC any, JC any] interface {
Serialize(r Run[OC, JC]) error
Deserialize() (*Run[OC, JC], error)
}
// JsonSerializer is a struct that implements Serializer and stores and loads run from a file specified
// in the File field, there is a anonymous variable type check
type JsonSerializer[OC any, JC any] struct {
File string
}
// NewJsonSerializer create a new instance of the JsonSerializer struct.
// It takes a single argument `file` of type string, which represents the file path where the serialized
// run data will be stored or loaded from.
func NewJsonSerializer[OC any, JC any](file string) *JsonSerializer[OC, JC] {
return &JsonSerializer[OC, JC]{
File: file,
}
}
var _ Serializer[any, any] = (*JsonSerializer[any, any])(nil)
// Serialize takes a Run[OC, JC] instance and serializes it to JSON format,
// writing the serialized data to the file specified when creating the JsonSerializer instance.
// It creates the parent directory for the file if it doesn't exist, and creates the file if it doesn't exist.
//
// If any error occurs during the process, such as creating the directory, creating the file,
// or encoding the Run instance, the function returns the error.
//
// Parameters:
//
// run Run[OC, JC]: The Run instance to be serialized.
//
// Returns:
//
// error: An error value if the serialization or file writing operation fails, otherwise nil.
func (js JsonSerializer[OC, JC]) Serialize(run Run[OC, JC]) error {
start := time.Now()
// Create the parent directory if it doesn't exist
dir := filepath.Dir(js.File)
err := os.MkdirAll(dir, 0600)
if err != nil {
return err
}
buf := &bytes.Buffer{}
encoder := json.NewEncoder(buf)
encoder.SetIndent("", " ")
err = encoder.Encode(run)
if err != nil {
return err
}
file, err := os.Create(js.File)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(file, buf)
if err != nil {
return err
}
slog.Info("Serialized", "file", js.File, "delta", time.Since(start))
return nil
}
// Deserialize reads the serialized Run[OC, JC] data from the file specified when creating the JsonSerializer instance,
// deserializes the JSON data into a Run[OC, JC] instance, and returns the deserialized Run instance.
//
// If any error occurs during the process, such as opening the file or decoding the JSON data,
// the function returns a zero-value Run[OC, JC] instance and the error.
//
// Returns:
//
// Run[OC, JC]: The deserialized Run instance.
// error: An error value if the deserialization or file reading operation fails, otherwise nil.
func (js JsonSerializer[OC, JC]) Deserialize() (*Run[OC, JC], error) {
start := time.Now()
file, err := os.Open(js.File)
if err != nil {
return nil, err
}
defer file.Close()
decoder := json.NewDecoder(file)
var run Run[OC, JC]
err = decoder.Decode(&run)
if err != nil {
return nil, err
}
slog.Info("Deserialized", "file", js.File, "delta", time.Since(start))
run.Init()
return &run, nil
}
// NilSerializer implements the Serializer interface with no-op implementations
// of the Serialize and Deserialize methods. It is useful when you don't need to persist or load
// Run instances, and is used as the default by NewProcessor if you don't specify one
type NilSerializer[OC any, JC any] struct {
}
// Serialize is a no-op implementation that does nothing and always returns nil.
// It satisfies the Serializer interface's Serialize method requirement.
func (n *NilSerializer[OC, JC]) Serialize(run Run[OC, JC]) error {
return nil
}
// Deserialize is a no-op implementation that panics with a "not implemented" message.
// It satisfies the Serializer interface's Deserialize method requirement, but it should
// never be called in practice when using the NilSerializer.
func (n *NilSerializer[OC, JC]) Deserialize() (*Run[OC, JC], error) {
panic("not implemented, shouldn't be called")
}