Files
clawgo/pkg/jsonlog/store.go
2026-04-13 13:41:01 +08:00

97 lines
2.1 KiB
Go

package jsonlog
import (
"bufio"
"encoding/json"
"fmt"
"os"
"path/filepath"
)
// AppendLine appends a single JSON-encoded line and returns the resulting file size.
func AppendLine(path string, value interface{}) (int64, error) {
data, err := json.Marshal(value)
if err != nil {
return 0, err
}
return AppendRawLine(path, data)
}
// AppendRawLine appends a raw JSON line and returns the resulting file size.
func AppendRawLine(path string, line []byte) (int64, error) {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return 0, err
}
f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return 0, err
}
defer f.Close()
if _, err := f.Write(append(line, '\n')); err != nil {
return 0, err
}
st, err := f.Stat()
if err != nil {
return 0, err
}
return st.Size(), nil
}
// Scan walks each non-empty JSONL line in order.
func Scan(path string, fn func(line []byte) error) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
scanner := bufio.NewScanner(f)
scanner.Buffer(make([]byte, 0, 64*1024), 8*1024*1024)
for scanner.Scan() {
line := append([]byte(nil), scanner.Bytes()...)
if len(line) == 0 {
continue
}
if err := fn(line); err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("scan %s: %w", path, err)
}
return nil
}
// FileSize returns 0 when the file does not exist.
func FileSize(path string) (int64, error) {
st, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return 0, nil
}
return 0, err
}
return st.Size(), nil
}
// ReadJSON reads a JSON sidecar file into dst.
func ReadJSON(path string, dst interface{}) error {
data, err := os.ReadFile(path)
if err != nil {
return err
}
return json.Unmarshal(data, dst)
}
// WriteJSON writes a JSON sidecar file atomically enough for local runtime use.
func WriteJSON(path string, value interface{}) error {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return err
}
data, err := json.MarshalIndent(value, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, data, 0644)
}