feat(ops): проверка бэкапа и уборка файлов без записи
- glchat verify-backup: расшифровка age, integrity_check, foreign_key_check, схема и состав данных, сверка с манифестом; живые данные не трогает - чистка удаляет файлы на диске, у которых не осталось записи в базе (так оставались вложения удалённых серверов), и пустые подкаталоги; работает через os.Root, чтобы символическая ссылка не вывела за каталог файлов - удаление сервера теперь чистит и содержимое файлов, а не только записи - install.sh пишет значения .env с пробелами в кавычках: файл подключается через `set -a && . .env`, иначе имя главного сервера выполнялось как команда - тесты: Go на уборку файлов без записи (свежие не трогаются, пустые каталоги удаляются)
This commit is contained in:
@@ -164,3 +164,44 @@ func scanFile(scanner interface{ Scan(...any) error }) (*File, error) {
|
||||
file.CreatedAt = parseTimestamp(createdAt)
|
||||
return &file, nil
|
||||
}
|
||||
|
||||
// FileStoragePaths возвращает пути всех файлов, известных базе: по ним
|
||||
// обслуживание понимает, какие файлы на диске остались без записи.
|
||||
func (s *Store) FileStoragePaths(ctx context.Context) (map[string]bool, error) {
|
||||
rows, err := s.reader.QueryContext(ctx, `SELECT storage_path FROM files WHERE storage_path <> ''`)
|
||||
if err != nil {
|
||||
return nil, mapError(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
paths := map[string]bool{}
|
||||
for rows.Next() {
|
||||
var path string
|
||||
if err := rows.Scan(&path); err != nil {
|
||||
return nil, mapError(err)
|
||||
}
|
||||
paths[path] = true
|
||||
}
|
||||
return paths, rows.Err()
|
||||
}
|
||||
|
||||
// GuildStoragePaths возвращает пути файлов сервера: их нужно удалить с диска
|
||||
// перед удалением сервера, иначе содержимое останется мусором (AGENT.md 6.4).
|
||||
func (s *Store) GuildStoragePaths(ctx context.Context, guildID uint64) ([]string, error) {
|
||||
rows, err := s.reader.QueryContext(ctx,
|
||||
`SELECT storage_path FROM files WHERE guild_id = ? AND storage_path <> ''`, int64(guildID))
|
||||
if err != nil {
|
||||
return nil, mapError(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
paths := make([]string, 0, 8)
|
||||
for rows.Next() {
|
||||
var path string
|
||||
if err := rows.Scan(&path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
paths = append(paths, path)
|
||||
}
|
||||
return paths, rows.Err()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user