merged from gramsrv upstream
This commit is contained in:
parent
79c64ee916
commit
21a0856587
651 changed files with 54774 additions and 4590 deletions
111
internal/store/postgres/blob_migration.go
Normal file
111
internal/store/postgres/blob_migration.go
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
// BlobMigrationObject is one immutable content-addressed object referenced by
|
||||
// one or more logical file locations on the same permanent backend.
|
||||
type BlobMigrationObject struct {
|
||||
ObjectKey string
|
||||
Size int64
|
||||
SHA256 []byte
|
||||
LocationRows int64
|
||||
}
|
||||
|
||||
// ListBlobMigrationObjects keyset-pages distinct objects. Inconsistent size or
|
||||
// digest metadata for one content key is returned as an error, never guessed.
|
||||
func (s *MediaStore) ListBlobMigrationObjects(
|
||||
ctx context.Context,
|
||||
backend domain.MediaBackend,
|
||||
afterObjectKey string,
|
||||
limit int,
|
||||
) ([]BlobMigrationObject, error) {
|
||||
if limit <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
rows, err := s.db.Query(ctx, `
|
||||
SELECT
|
||||
object_key,
|
||||
min(size)::bigint,
|
||||
count(DISTINCT size)::bigint,
|
||||
min(encode(sha256, 'hex')),
|
||||
count(DISTINCT encode(sha256, 'hex'))::bigint,
|
||||
count(*)::bigint
|
||||
FROM file_blobs
|
||||
WHERE backend = $1 AND object_key > $2
|
||||
GROUP BY object_key
|
||||
ORDER BY object_key
|
||||
LIMIT $3`, string(backend), afterObjectKey, limit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list %s blob migration objects: %w", backend, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
objects := make([]BlobMigrationObject, 0, limit)
|
||||
for rows.Next() {
|
||||
var (
|
||||
object BlobMigrationObject
|
||||
sizeVariants int64
|
||||
digestHex string
|
||||
digestVariants int64
|
||||
)
|
||||
if err := rows.Scan(
|
||||
&object.ObjectKey,
|
||||
&object.Size,
|
||||
&sizeVariants,
|
||||
&digestHex,
|
||||
&digestVariants,
|
||||
&object.LocationRows,
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("scan blob migration object: %w", err)
|
||||
}
|
||||
if sizeVariants != 1 || digestVariants != 1 {
|
||||
return nil, fmt.Errorf("blob %q has inconsistent persisted size or SHA-256 metadata", object.ObjectKey)
|
||||
}
|
||||
digest, err := hex.DecodeString(digestHex)
|
||||
if err != nil || len(digest) != 32 {
|
||||
return nil, fmt.Errorf("blob %q has invalid persisted SHA-256 metadata", object.ObjectKey)
|
||||
}
|
||||
if object.ObjectKey != digestHex {
|
||||
return nil, fmt.Errorf("blob %q object key does not match persisted SHA-256 %q", object.ObjectKey, digestHex)
|
||||
}
|
||||
object.SHA256 = digest
|
||||
objects = append(objects, object)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("iterate blob migration objects: %w", err)
|
||||
}
|
||||
return objects, nil
|
||||
}
|
||||
|
||||
// MoveFileBlobBackendForObject atomically relabels every logical location for a
|
||||
// verified immutable object. It refuses partial/racing changes.
|
||||
func (s *MediaStore) MoveFileBlobBackendForObject(
|
||||
ctx context.Context,
|
||||
from domain.MediaBackend,
|
||||
to domain.MediaBackend,
|
||||
objectKey string,
|
||||
expectedRows int64,
|
||||
) error {
|
||||
if expectedRows <= 0 {
|
||||
return fmt.Errorf("blob %q expected row count must be positive", objectKey)
|
||||
}
|
||||
result, err := s.db.Exec(ctx, `
|
||||
UPDATE file_blobs
|
||||
SET backend = $1
|
||||
WHERE backend = $2 AND object_key = $3`, string(to), string(from), objectKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("move blob %q metadata from %s to %s: %w", objectKey, from, to, err)
|
||||
}
|
||||
if result.RowsAffected() != expectedRows {
|
||||
return fmt.Errorf(
|
||||
"move blob %q metadata changed %d rows, want %d",
|
||||
objectKey, result.RowsAffected(), expectedRows,
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue