loader revisited
This commit is contained in:
+44
-32
@@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
gerr "galaxy/error"
|
||||
"galaxy/model/client"
|
||||
"galaxy/model/order"
|
||||
"galaxy/model/report"
|
||||
@@ -77,17 +78,17 @@ func NewFS(storageRoot string) (*fsStorage, error) {
|
||||
fmt.Println("using fs root:", storageRoot)
|
||||
absRoot, err := filepath.Abs(storageRoot)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new fs storage: resolve absolute path for %q: %w", storageRoot, err)
|
||||
return nil, classifyStorageError(fmt.Errorf("new fs storage: resolve absolute path for %q: %w", storageRoot, err))
|
||||
}
|
||||
if ok, err := util.PathExists(absRoot, true); err != nil {
|
||||
return nil, fmt.Errorf("new fs storage: check path %q exists: %w", absRoot, err)
|
||||
return nil, classifyStorageError(fmt.Errorf("new fs storage: check path %q exists: %w", absRoot, err))
|
||||
} else if !ok {
|
||||
return nil, fmt.Errorf("new fs storage: path %q does not exist", absRoot)
|
||||
return nil, classifyStorageError(fmt.Errorf("new fs storage: path %q does not exist", absRoot))
|
||||
}
|
||||
if ok, err := util.Writable(absRoot); err != nil {
|
||||
return nil, fmt.Errorf("new fs storage: check path %q writable: %w", absRoot, err)
|
||||
return nil, classifyStorageError(fmt.Errorf("new fs storage: check path %q writable: %w", absRoot, err))
|
||||
} else if !ok {
|
||||
return nil, fmt.Errorf("new fs storage: path %q is not writable", absRoot)
|
||||
return nil, classifyStorageError(fmt.Errorf("new fs storage: path %q is not writable", absRoot))
|
||||
}
|
||||
|
||||
return &fsStorage{
|
||||
@@ -166,7 +167,7 @@ func (s *fsStorage) SaveOrderAsync(id client.GameID, turn uint, o order.Order, c
|
||||
func (s *fsStorage) FileExists(path string) (bool, string, error) {
|
||||
absPath, err := s.resolvePath(path)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
return false, "", classifyStorageError(err)
|
||||
}
|
||||
|
||||
var exists bool
|
||||
@@ -176,7 +177,7 @@ func (s *fsStorage) FileExists(path string) (bool, string, error) {
|
||||
return opErr
|
||||
})
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
return false, "", classifyStorageError(err)
|
||||
}
|
||||
if !exists {
|
||||
return false, absPath, nil
|
||||
@@ -187,7 +188,7 @@ func (s *fsStorage) FileExists(path string) (bool, string, error) {
|
||||
func (s *fsStorage) ReadFile(path string) ([]byte, error) {
|
||||
absPath, err := s.resolvePath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, classifyStorageError(err)
|
||||
}
|
||||
|
||||
var data []byte
|
||||
@@ -196,27 +197,27 @@ func (s *fsStorage) ReadFile(path string) ([]byte, error) {
|
||||
data, opErr = s.readFileUnlocked(absPath)
|
||||
return opErr
|
||||
})
|
||||
return data, err
|
||||
return data, classifyStorageError(err)
|
||||
}
|
||||
|
||||
func (s *fsStorage) WriteFile(path string, data []byte) error {
|
||||
absPath, err := s.resolvePath(path)
|
||||
if err != nil {
|
||||
return err
|
||||
return classifyStorageError(err)
|
||||
}
|
||||
|
||||
return s.withPathLock(absPath, func() error {
|
||||
return classifyStorageError(s.withPathLock(absPath, func() error {
|
||||
return s.writeFileUnlocked(absPath, data)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *fsStorage) DeleteFile(path string) error {
|
||||
absPath, err := s.resolvePath(path)
|
||||
if err != nil {
|
||||
return err
|
||||
return classifyStorageError(err)
|
||||
}
|
||||
|
||||
return s.withPathLock(absPath, func() error {
|
||||
return classifyStorageError(s.withPathLock(absPath, func() error {
|
||||
exists, err := s.fileExistsUnlocked(absPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -228,7 +229,7 @@ func (s *fsStorage) DeleteFile(path string) error {
|
||||
return fmt.Errorf("delete file %q: %w", absPath, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *fsStorage) ListFiles() ([]string, error) {
|
||||
@@ -252,7 +253,7 @@ func (s *fsStorage) ListFiles() ([]string, error) {
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list files under %q: %w", s.storageRoot, err)
|
||||
return nil, classifyStorageError(fmt.Errorf("list files under %q: %w", s.storageRoot, err))
|
||||
}
|
||||
|
||||
slices.Sort(files)
|
||||
@@ -261,29 +262,30 @@ func (s *fsStorage) ListFiles() ([]string, error) {
|
||||
|
||||
func (s *fsStorage) StateExists() (bool, error) {
|
||||
exists, _, err := s.FileExists(stateFileName)
|
||||
return exists, err
|
||||
return exists, classifyStorageError(err)
|
||||
}
|
||||
|
||||
func (s *fsStorage) LoadState() (client.State, error) {
|
||||
data, err := s.ReadFile(stateFileName)
|
||||
if err != nil {
|
||||
return client.State{}, err
|
||||
return client.State{}, classifyStorageError(err)
|
||||
}
|
||||
return unmarshalState(data)
|
||||
state, err := unmarshalState(data)
|
||||
return state, classifyStorageError(err)
|
||||
}
|
||||
|
||||
func (s *fsStorage) SaveState(state client.State) error {
|
||||
data, err := marshalState(state)
|
||||
if err != nil {
|
||||
return err
|
||||
return classifyStorageError(err)
|
||||
}
|
||||
return s.WriteFile(stateFileName, data)
|
||||
return classifyStorageError(s.WriteFile(stateFileName, data))
|
||||
}
|
||||
|
||||
func (s *fsStorage) loadReportSync(id client.GameID, turn uint) (report.Report, error) {
|
||||
gameData, err := s.loadGameDataSync(id, turn)
|
||||
if err != nil {
|
||||
return report.Report{}, err
|
||||
return report.Report{}, classifyStorageError(err)
|
||||
}
|
||||
return gameData.Report, nil
|
||||
}
|
||||
@@ -291,10 +293,10 @@ func (s *fsStorage) loadReportSync(id client.GameID, turn uint) (report.Report,
|
||||
func (s *fsStorage) saveReportSync(id client.GameID, turn uint, rep report.Report) error {
|
||||
absPath, err := s.resolvePath(gameTurnFilePath(id, turn))
|
||||
if err != nil {
|
||||
return err
|
||||
return classifyStorageError(err)
|
||||
}
|
||||
|
||||
return s.withPathLock(absPath, func() error {
|
||||
return classifyStorageError(s.withPathLock(absPath, func() error {
|
||||
gameData, err := s.loadGameDataUnlocked(absPath)
|
||||
if err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
@@ -306,16 +308,16 @@ func (s *fsStorage) saveReportSync(id client.GameID, turn uint, rep report.Repor
|
||||
gameData.Turn = turn
|
||||
gameData.Report = rep
|
||||
return s.writeGameDataUnlocked(absPath, gameData)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *fsStorage) loadOrderSync(id client.GameID, turn uint) (order.Order, error) {
|
||||
gameData, err := s.loadGameDataSync(id, turn)
|
||||
if err != nil {
|
||||
return order.Order{}, err
|
||||
return order.Order{}, classifyStorageError(err)
|
||||
}
|
||||
if gameData.Order == nil {
|
||||
return order.Order{}, fmt.Errorf("load order for game %q turn %d: %w", id, turn, os.ErrNotExist)
|
||||
return order.Order{}, classifyStorageError(fmt.Errorf("load order for game %q turn %d: %w", id, turn, os.ErrNotExist))
|
||||
}
|
||||
return *gameData.Order, nil
|
||||
}
|
||||
@@ -323,10 +325,10 @@ func (s *fsStorage) loadOrderSync(id client.GameID, turn uint) (order.Order, err
|
||||
func (s *fsStorage) saveOrderSync(id client.GameID, turn uint, o order.Order) error {
|
||||
absPath, err := s.resolvePath(gameTurnFilePath(id, turn))
|
||||
if err != nil {
|
||||
return err
|
||||
return classifyStorageError(err)
|
||||
}
|
||||
|
||||
return s.withPathLock(absPath, func() error {
|
||||
return classifyStorageError(s.withPathLock(absPath, func() error {
|
||||
gameData, err := s.loadGameDataUnlocked(absPath)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
@@ -338,13 +340,13 @@ func (s *fsStorage) saveOrderSync(id client.GameID, turn uint, o order.Order) er
|
||||
gameData.Turn = turn
|
||||
gameData.Order = &o
|
||||
return s.writeGameDataUnlocked(absPath, gameData)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *fsStorage) loadGameDataSync(id client.GameID, turn uint) (client.GameData, error) {
|
||||
absPath, err := s.resolvePath(gameTurnFilePath(id, turn))
|
||||
if err != nil {
|
||||
return client.GameData{}, err
|
||||
return client.GameData{}, classifyStorageError(err)
|
||||
}
|
||||
|
||||
var gameData client.GameData
|
||||
@@ -353,7 +355,7 @@ func (s *fsStorage) loadGameDataSync(id client.GameID, turn uint) (client.GameDa
|
||||
gameData, opErr = s.loadGameDataUnlocked(absPath)
|
||||
return opErr
|
||||
})
|
||||
return gameData, err
|
||||
return gameData, classifyStorageError(err)
|
||||
}
|
||||
|
||||
func (s *fsStorage) loadGameDataUnlocked(absPath string) (client.GameData, error) {
|
||||
@@ -713,3 +715,13 @@ func (s *fsStorage) ensureParentDir(absPath string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func classifyStorageError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if gerr.IsStorage(err) {
|
||||
return err
|
||||
}
|
||||
return gerr.WrapStorage(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user