feat:[AH-1083]: fix download count and upstream proxy for NPM (#3678)

* feat:[AH-1083]: review changes
* feat:[AH-1083]: review changes
* feat:[AH-1083]: fix checks
* feat:[AH-1083]: fix download count
* feat:[AH-1083]: fix download count
* feat:[AH-1083]: NPM upstream proxy fix
This commit is contained in:
Sourabh Awashti 2025-04-15 10:21:54 +00:00 committed by Harness
parent 691e692c21
commit 266591513c
10 changed files with 67 additions and 9 deletions

View File

@ -16,14 +16,17 @@ package metadata
import (
"context"
"encoding/json"
"errors"
"fmt"
"path/filepath"
"strconv"
"strings"
"github.com/harness/gitness/app/url"
artifactapi "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/app/metadata"
npm2 "github.com/harness/gitness/registry/app/metadata/npm"
"github.com/harness/gitness/registry/types"
"github.com/rs/zerolog/log"
@ -503,19 +506,31 @@ func GetPythonArtifactDetail(
func GetNPMArtifactDetail(
image *types.Image, artifact *types.Artifact,
metadata map[string]interface{},
downloadCount int64,
) artifactapi.ArtifactDetail {
createdAt := GetTimeInMs(artifact.CreatedAt)
modifiedAt := GetTimeInMs(artifact.UpdatedAt)
artifactDetail := &artifactapi.ArtifactDetail{
CreatedAt: &createdAt,
ModifiedAt: &modifiedAt,
Name: &image.Name,
Version: artifact.Version,
var npmMetadata npm2.NpmMetadata
err := json.Unmarshal(artifact.Metadata, &npmMetadata)
if err != nil {
log.Error().Err(err).Msgf("Error unmarshalling the artifact metadata "+
"for image: [%s], version: [%s]", image.Name, artifact.Version)
return artifactapi.ArtifactDetail{}
}
err := artifactDetail.FromNpmArtifactDetailConfig(artifactapi.NpmArtifactDetailConfig{
totalSize := strconv.FormatInt(npmMetadata.Size, 10)
artifactDetail := &artifactapi.ArtifactDetail{
CreatedAt: &createdAt,
ModifiedAt: &modifiedAt,
Name: &image.Name,
Version: artifact.Version,
DownloadCount: &downloadCount,
Size: &totalSize,
}
err = artifactDetail.FromNpmArtifactDetailConfig(artifactapi.NpmArtifactDetailConfig{
Metadata: &metadata,
})
if err != nil {
log.Error().Err(err).Msgf("Error setting the artifact details for image: [%s]", image.Name)
return artifactapi.ArtifactDetail{}
}
return *artifactDetail

View File

@ -95,6 +95,16 @@ func (c *APIController) GetArtifactDetails(
}, nil
}
downloadCount, err := c.DownloadStatRepository.GetTotalDownloadsForArtifactID(ctx, art.ID)
if err != nil {
return artifact.GetArtifactDetails500JSONResponse{
InternalServerErrorJSONResponse: artifact.InternalServerErrorJSONResponse(
*GetErrorResponse(http.StatusInternalServerError, err.Error()),
),
}, nil
}
var artifactDetails artifact.ArtifactDetail
// FIXME: Arvind: Unify the metadata structure to avoid this type checking
@ -144,7 +154,7 @@ func (c *APIController) GetArtifactDetails(
),
}, nil
}
artifactDetails = GetNPMArtifactDetail(img, art, result)
artifactDetails = GetNPMArtifactDetail(img, art, result, downloadCount)
case artifact.PackageTypeDOCKER:
case artifact.PackageTypeHELM:
default:

View File

@ -34,6 +34,8 @@ func (c *controller) DownloadPackageFile(
f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response {
info.RegIdentifier = registry.Name
info.RegistryID = registry.ID
info.Registry = registry
info.ParentID = registry.ParentID
npmRegistry, ok := a.(npm2.Registry)
if !ok {
return &GetArtifactResponse{

View File

@ -34,6 +34,8 @@ func (c *controller) DownloadPackageFileByName(
f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response {
info.RegIdentifier = registry.Name
info.RegistryID = registry.ID
info.Registry = registry
info.ParentID = registry.ParentID
npmRegistry, ok := a.(npm2.Registry)
if !ok {
return &GetArtifactResponse{

View File

@ -34,6 +34,8 @@ func (c *controller) HeadPackageFileByName(
f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response {
info.RegIdentifier = registry.Name
info.RegistryID = registry.ID
info.Registry = registry
info.ParentID = registry.ParentID
npmRegistry, ok := a.(npm2.Registry)
if !ok {
return &HeadMetadataResponse{

View File

@ -34,6 +34,8 @@ func (c *controller) ListTags(
f := func(registry types.Registry, a pkg.Artifact) response.Response {
info.RegIdentifier = registry.Name
info.RegistryID = registry.ID
info.Registry = registry
info.ParentID = registry.ParentID
npmRegistry, ok := a.(npm2.Registry)
if !ok {
return &ListTagResponse{

View File

@ -42,6 +42,8 @@ func (c *controller) GetPackageMetadata(
f := func(registry types.Registry, a pkg.Artifact) response.Response {
info.RegIdentifier = registry.Name
info.RegistryID = registry.ID
info.Registry = registry
info.ParentID = registry.ParentID
npmRegistry, ok := a.(npm2.Registry)
if !ok {
return &GetMetadataResponse{

View File

@ -505,6 +505,7 @@ type DownloadStatRepository interface {
imageID int64,
) (map[string]int64, error)
CreateByRegistryIDImageAndArtifactName(ctx context.Context, regID int64, image string, artifactName string) error
GetTotalDownloadsForArtifactID(ctx context.Context, artifactID int64) (int64, error)
}
type BandwidthStatRepository interface {

View File

@ -155,6 +155,28 @@ func (d DownloadStatDao) GetTotalDownloadsForImage(ctx context.Context, imageID
return count, nil
}
func (d DownloadStatDao) GetTotalDownloadsForArtifactID(ctx context.Context, artifactID int64) (int64, error) {
q := databaseg.Builder.Select(`count(*)`).
From("download_stats ds").Where("ds.download_stat_artifact_id = ?", artifactID)
sql, args, err := q.ToSql()
if err != nil {
return 0, errors.Wrap(err, "Failed to convert query to sql")
}
// Log the final sql query
finalQuery := util.FormatQuery(sql, args)
log.Ctx(ctx).Debug().Str("sql", finalQuery).Msg("Executing GetTotalDownloadsForArtifact query")
// Execute query
db := dbtx.GetAccessor(ctx, d.db)
var count int64
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
if err != nil {
return 0, databaseg.ProcessSQLErrorf(ctx, err, "Failed executing count query")
}
return count, nil
}
func (d DownloadStatDao) GetTotalDownloadsForManifests(
ctx context.Context,
artifactVersions []string,

View File

@ -135,7 +135,7 @@ func (r UpstreamproxyDao) Get(ctx context.Context, id int64) (upstreamProxy *typ
dst := new(upstreamProxyDB)
if err = db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed to get tag detail")
return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed to get upstream proxy detail")
}
return r.mapToUpstreamProxy(ctx, dst)
@ -159,7 +159,7 @@ func (r UpstreamproxyDao) GetByRegistryIdentifier(
dst := new(upstreamProxyDB)
if err = db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed to get tag detail")
return nil, databaseg.ProcessSQLErrorf(ctx, err, "Failed to get upstream proxy detail")
}
return r.mapToUpstreamProxy(ctx, dst)