Files
Zach LeslieandGitHub c5fe2e7e6b [backend-scheduler] initial work file sharding for more targeted marshaling (#5412)
* [backend-scheduler] initial work file sharding for more targeted marshaling

* Add integration coverage for both work implementations

* Update config manifest

* Add integration coverage for sharded work configuration

* Fix integration test config path

* Add test coverage for sharded work migrations and marshaling

* Use new sharded work file in the backend and handle migration

* Clean up backend after migration

* Use shared method for shard file name

* Add method to write files atomically and test

* Update work interface for simpler flush/load interactions

* Update callers for local flush/load interface methods

* Fix lint

* Fix lint

* Fix lint

* Clean up

* Clean up after refactor new interface functions

* Promote the sharded implementation to be the only implementation

* Clean up comments

* Generate config manifest

* Clean up interface and improve test coverage

* Drop transitional comments

* Protect work marshal/unmarshal with a mutex

* Add test coverage for concurrent marshal/unmarshal

* Lint

* Fix race condition in Marshal/Unmarshal when jobs are operating

* Relocate methods

* Update changelog

* Drop interface method only used in tests

* Rename method for clarity, add doc

* Update doc for clarity

* Lock for safety

* Clarify and improve locking flush behavior

* Encapsulate the lock/unlock in a func

* Address some PR feedback

* Further unifi shard file name generation

* Modify work to use int rather than uint8

* Fix lint
2025-07-25 18:04:22 +00:00

45 lines
942 B
Go

package work
import (
"os"
"path/filepath"
)
// atomicWriteFile writes data to a file atomically using a temporary file and rename.
// This prevents possible data corruption in case of a crash or interruption during the write operation.
func atomicWriteFile(data []byte, targetPath, tempPrefix string) error {
dir := filepath.Dir(targetPath)
// Create unique temporary file
tempFile, err := os.CreateTemp(dir, tempPrefix+".tmp.")
if err != nil {
return err
}
tempPath := tempFile.Name()
// Write data to temporary file
_, err = tempFile.Write(data)
if err != nil {
tempFile.Close()
os.Remove(tempPath)
return err
}
// Sync and close temporary file
err = tempFile.Sync()
if err != nil {
tempFile.Close()
os.Remove(tempPath)
return err
}
err = tempFile.Close()
if err != nil {
os.Remove(tempPath)
return err
}
// Atomically move temp file to final location
return os.Rename(tempPath, targetPath)
}