fix(gcssink): prevent empty object finalization on write failure (#8933)
* fix(gcssink): prevent empty object finalization on write failure The GCS writer was created unconditionally with defer wc.Close(), which finalizes the upload even when content decryption or copy fails. This silently overwrites valid objects with empty data. Remove the unconditional defer, explicitly close on success to propagate errors, and delete the object on write failure. * fix(gcssink): use context cancellation instead of obj.Delete on failure obj.Delete() after a failed write would delete the existing object at that key, causing data loss on updates. Use a cancelable context instead — cancelling before Close() aborts the GCS upload without touching any pre-existing object.
This commit is contained in:
@@ -115,23 +115,32 @@ func (g *GcsSink) CreateEntry(key string, entry *filer_pb.Entry, signatures []in
|
||||
totalSize := filer.FileSize(entry)
|
||||
chunkViews := filer.ViewFromChunks(context.Background(), g.filerSource.LookupFileId, entry.GetChunks(), 0, int64(totalSize))
|
||||
|
||||
wc := g.client.Bucket(g.bucket).Object(key).NewWriter(context.Background())
|
||||
defer wc.Close()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
wc := g.client.Bucket(g.bucket).Object(key).NewWriter(ctx)
|
||||
|
||||
writeFunc := func(data []byte) error {
|
||||
_, writeErr := wc.Write(data)
|
||||
return writeErr
|
||||
}
|
||||
|
||||
var writeErr error
|
||||
if len(entry.Content) > 0 {
|
||||
return writeFunc(entry.Content)
|
||||
writeErr = writeFunc(entry.Content)
|
||||
} else {
|
||||
writeErr = repl_util.CopyFromChunkViews(chunkViews, g.filerSource, writeFunc)
|
||||
}
|
||||
|
||||
if err := repl_util.CopyFromChunkViews(chunkViews, g.filerSource, writeFunc); err != nil {
|
||||
return err
|
||||
if writeErr != nil {
|
||||
// Cancel the context to abort the GCS upload without touching
|
||||
// any existing object at this key.
|
||||
cancel()
|
||||
wc.Close()
|
||||
return writeErr
|
||||
}
|
||||
|
||||
return nil
|
||||
return wc.Close()
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user