Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-11 08:39:17 -05:00
pkg-proxy/internal/database/local_artifacts.go

70 lines
2.2 KiB
Go
Raw Permalink Normal View History

package database
import (
"database/sql"
"fmt"
"time"
)
// LocalArtifact is a pushed artifact with the integrity of its version.
type LocalArtifact struct {
Artifact
Integrity sql.NullString `db:"integrity"`
}
// GetLocalArtifacts returns the artifacts pushed to the proxy for a package,
// ordered by version and filename.
func (db *DB) GetLocalArtifacts(packagePURL string) ([]LocalArtifact, error) {
var artifacts []LocalArtifact
query := db.Rebind(`
SELECT a.id, a.version_purl, a.filename, a.upstream_url, a.storage_path, a.content_hash,
a.size, a.content_type, a.fetched_at, a.hit_count, a.last_accessed_at,
a.created_at, a.updated_at, a.source, a.manifest, v.integrity
FROM artifacts a
JOIN versions v ON v.purl = a.version_purl
WHERE v.package_purl = ? AND a.source = 'local'
ORDER BY a.version_purl, a.filename
`)
if err := db.Select(&artifacts, query, packagePURL); err != nil {
return nil, err
}
return artifacts, nil
}
// DeleteLocalArtifacts removes the pushed artifacts of a version and queues
// their stored objects for deletion in the same transaction, so a failed
// queue keeps the records instead of orphaning the objects. Artifacts cached
// from an upstream are left alone. It returns how many records it removed.
func (db *DB) DeleteLocalArtifacts(versionPURL string) (int, error) {
tx, err := db.Beginx()
if err != nil {
return 0, err
}
defer func() { _ = tx.Rollback() }()
var paths []string
selectQuery := db.Rebind(`
SELECT storage_path FROM artifacts
WHERE version_purl = ? AND source = 'local' AND storage_path IS NOT NULL
`)
if err := tx.Select(&paths, selectQuery, versionPURL); err != nil {
return 0, fmt.Errorf("reading local artifacts: %w", err)
}
res, err := tx.Exec(db.Rebind(`DELETE FROM artifacts WHERE version_purl = ? AND source = 'local'`), versionPURL)
if err != nil {
return 0, fmt.Errorf("deleting local artifacts: %w", err)
}
deleted, err := res.RowsAffected()
if err != nil {
return 0, err
}
queuedAt := time.Now().UTC()
for _, path := range paths {
if _, err := tx.Exec(db.Rebind(queuePendingDeleteQuery), path, queuedAt); err != nil {
return 0, fmt.Errorf("queueing %s for deletion: %w", path, err)
}
}
return int(deleted), tx.Commit()
}