Harden chunk plan cache storage and reuse
This commit is contained in:
@@ -17,7 +17,8 @@ import (
|
||||
const SchemaVersion = pipeline.ChunkPlanSchemaVersion
|
||||
|
||||
type filesystemStore struct {
|
||||
root string
|
||||
root string
|
||||
write func(string, []byte) error
|
||||
}
|
||||
|
||||
func NewFilesystemStore(root string) (pipeline.ChunkPlanStore, error) {
|
||||
@@ -28,7 +29,7 @@ func NewFilesystemStore(root string) (pipeline.ChunkPlanStore, error) {
|
||||
if strings.ContainsRune(root, '\x00') {
|
||||
return nil, fmt.Errorf("chunk plan root must not contain NUL")
|
||||
}
|
||||
return &filesystemStore{root: filepath.Clean(root)}, nil
|
||||
return &filesystemStore{root: filepath.Clean(root), write: writeAtomic}, nil
|
||||
}
|
||||
|
||||
func (s *filesystemStore) Load(sourceDigest string) (pipeline.ChunkPlanRecord, pipeline.ChunkPlanDecision, error) {
|
||||
@@ -77,7 +78,11 @@ func (s *filesystemStore) Save(record pipeline.ChunkPlanRecord) error {
|
||||
return fmt.Errorf("encode chunk plan record: %w", err)
|
||||
}
|
||||
data = append(data, '\n')
|
||||
if err := writeAtomic(target, data); err != nil {
|
||||
writer := s.write
|
||||
if writer == nil {
|
||||
writer = writeAtomic
|
||||
}
|
||||
if err := writer(target, data); err != nil {
|
||||
return fmt.Errorf("write chunk plan: %w", err)
|
||||
}
|
||||
return nil
|
||||
@@ -164,7 +169,16 @@ func invalidDecision(reason string) (pipeline.ChunkPlanRecord, pipeline.ChunkPla
|
||||
return pipeline.ChunkPlanRecord{}, pipeline.ChunkPlanDecision{Status: pipeline.ChunkPlanInvalid, Reason: reason}, nil
|
||||
}
|
||||
|
||||
type atomicWriteHooks struct {
|
||||
BeforeCreateTemp func() error
|
||||
BeforeRename func() error
|
||||
}
|
||||
|
||||
func writeAtomic(target string, data []byte) error {
|
||||
return writeAtomicWithHooks(target, data, atomicWriteHooks{})
|
||||
}
|
||||
|
||||
func writeAtomicWithHooks(target string, data []byte, hooks atomicWriteHooks) error {
|
||||
dir := filepath.Dir(target)
|
||||
if err := os.MkdirAll(dir, 0o700); err != nil {
|
||||
return err
|
||||
@@ -173,6 +187,11 @@ func writeAtomic(target string, data []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if hooks.BeforeCreateTemp != nil {
|
||||
if err := hooks.BeforeCreateTemp(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
temp, err := os.CreateTemp(dir, ".plan.json.tmp-*")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -199,6 +218,11 @@ func writeAtomic(target string, data []byte) error {
|
||||
if err := temp.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if hooks.BeforeRename != nil {
|
||||
if err := hooks.BeforeRename(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := os.Rename(tempPath, target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user