Skip to content

Commit c96e577

Browse files
authored
feat: support fetching specific asset version with URN (#207)
Add functionality to existing endpoint.
1 parent 7fc4a82 commit c96e577

File tree

6 files changed

+173
-66
lines changed

6 files changed

+173
-66
lines changed

core/asset/asset.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ type Repository interface {
1515
GetByID(ctx context.Context, id string) (Asset, error)
1616
GetByURN(ctx context.Context, urn string) (Asset, error)
1717
GetVersionHistory(ctx context.Context, flt Filter, id string) ([]Asset, error)
18-
GetByVersion(ctx context.Context, id string, version string) (Asset, error)
18+
GetByVersionWithID(ctx context.Context, id string, version string) (Asset, error)
19+
GetByVersionWithURN(ctx context.Context, urn string, version string) (Asset, error)
1920
GetTypes(ctx context.Context, flt Filter) (map[Type]int, error)
2021
Upsert(ctx context.Context, ast *Asset) (string, error)
2122
DeleteByID(ctx context.Context, id string) error

core/asset/mocks/asset_repository.go

Lines changed: 55 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/asset/service.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,11 @@ func (s *Service) GetAssetByID(ctx context.Context, id string) (ast Asset, err e
103103
}
104104

105105
func (s *Service) GetAssetByVersion(ctx context.Context, id string, version string) (Asset, error) {
106-
return s.assetRepository.GetByVersion(ctx, id, version)
106+
if isValidUUID(id) {
107+
return s.assetRepository.GetByVersionWithID(ctx, id, version)
108+
}
109+
110+
return s.assetRepository.GetByVersionWithURN(ctx, id, version)
107111
}
108112

109113
func (s *Service) GetAssetVersionHistory(ctx context.Context, flt Filter, id string) ([]Asset, error) {

core/asset/service_test.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ func TestService_GetAssetByID(t *testing.T) {
509509

510510
func TestService_GetAssetByVersion(t *testing.T) {
511511
assetID := "f742aa61-1100-445c-8d72-355a42e2fb59"
512+
urn := "my-test-urn"
512513
type testCase struct {
513514
Description string
514515
ID string
@@ -518,18 +519,36 @@ func TestService_GetAssetByVersion(t *testing.T) {
518519

519520
var testCases = []testCase{
520521
{
521-
Description: `should return error if the GetByVersion function return error`,
522+
Description: `should return error if the GetByVersionWithID function return error`,
522523
ID: assetID,
523524
Setup: func(ctx context.Context, ar *mocks.AssetRepository) {
524-
ar.EXPECT().GetByVersion(ctx, assetID, "v0.0.2").Return(asset.Asset{}, errors.New("error fetching asset"))
525+
ar.EXPECT().GetByVersionWithID(ctx, assetID, "v0.0.2").
526+
Return(asset.Asset{}, errors.New("error fetching asset"))
527+
},
528+
ExpectedErr: errors.New("error fetching asset"),
529+
},
530+
{
531+
Description: `should return error if the GetByVersionWithURN function return error`,
532+
ID: urn,
533+
Setup: func(ctx context.Context, ar *mocks.AssetRepository) {
534+
ar.EXPECT().GetByVersionWithURN(ctx, urn, "v0.0.2").
535+
Return(asset.Asset{}, errors.New("error fetching asset"))
525536
},
526537
ExpectedErr: errors.New("error fetching asset"),
527538
},
528539
{
529-
Description: `should return no error if asset is found`,
540+
Description: `should return no error if asset is found with ID`,
530541
ID: assetID,
531542
Setup: func(ctx context.Context, ar *mocks.AssetRepository) {
532-
ar.EXPECT().GetByVersion(ctx, assetID, "v0.0.2").Return(asset.Asset{}, nil)
543+
ar.EXPECT().GetByVersionWithID(ctx, assetID, "v0.0.2").Return(asset.Asset{}, nil)
544+
},
545+
ExpectedErr: nil,
546+
},
547+
{
548+
Description: `should return no error if asset is found with URN`,
549+
ID: urn,
550+
Setup: func(ctx context.Context, ar *mocks.AssetRepository) {
551+
ar.EXPECT().GetByVersionWithURN(ctx, urn, "v0.0.2").Return(asset.Asset{}, nil)
533552
},
534553
ExpectedErr: nil,
535554
},

internal/store/postgres/asset_repository.go

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -208,51 +208,69 @@ func (r *AssetRepository) GetVersionHistory(ctx context.Context, flt asset.Filte
208208
return avs, nil
209209
}
210210

211-
// GetByVersion retrieves the specific asset version
212-
func (r *AssetRepository) GetByVersion(ctx context.Context, id string, version string) (ast asset.Asset, err error) {
211+
// GetByVersionWithID retrieves the specific asset version
212+
func (r *AssetRepository) GetByVersionWithID(ctx context.Context, id string, version string) (asset.Asset, error) {
213213
if !isValidUUID(id) {
214-
err = asset.InvalidError{AssetID: id}
215-
return
214+
return asset.Asset{}, asset.InvalidError{AssetID: id}
216215
}
217216

218-
latestAsset, err := r.GetByID(ctx, id)
217+
ast, err := r.getByVersion(ctx, id, version, r.GetByID, sq.Eq{
218+
"a.asset_id": id,
219+
"a.version": version,
220+
})
219221
if errors.Is(err, sql.ErrNoRows) {
220-
err = asset.NotFoundError{AssetID: id}
221-
return
222+
return asset.Asset{}, asset.NotFoundError{AssetID: id}
222223
}
223-
224224
if err != nil {
225-
return
225+
return asset.Asset{}, err
226226
}
227227

228-
if latestAsset.Version == version {
229-
ast = latestAsset
230-
return
228+
return ast, nil
229+
}
230+
231+
func (r *AssetRepository) GetByVersionWithURN(ctx context.Context, urn string, version string) (asset.Asset, error) {
232+
ast, err := r.getByVersion(ctx, urn, version, r.GetByURN, sq.Eq{
233+
"a.urn": urn,
234+
"a.version": version,
235+
})
236+
if errors.Is(err, sql.ErrNoRows) {
237+
return asset.Asset{}, asset.NotFoundError{URN: urn}
238+
}
239+
if err != nil {
240+
return asset.Asset{}, err
231241
}
232242

233-
var assetModel AssetModel
234-
builder := r.getAssetVersionSQL().
235-
Where(sq.Eq{"a.asset_id": id, "a.version": version})
236-
query, args, err := r.buildSQL(builder)
243+
return ast, nil
244+
}
245+
246+
type getAssetFunc func(context.Context, string) (asset.Asset, error)
247+
248+
func (r *AssetRepository) getByVersion(
249+
ctx context.Context, id, version string, get getAssetFunc, pred sq.Eq,
250+
) (asset.Asset, error) {
251+
latest, err := get(ctx, id)
237252
if err != nil {
238-
err = fmt.Errorf("error building query: %w", err)
239-
return
253+
return asset.Asset{}, err
240254
}
241255

242-
err = r.client.db.GetContext(ctx, &assetModel, query, args...)
243-
if errors.Is(err, sql.ErrNoRows) {
244-
err = asset.NotFoundError{AssetID: id}
245-
return
256+
if latest.Version == version {
257+
return latest, nil
246258
}
247259

260+
var ast AssetModel
261+
builder := r.getAssetVersionSQL().
262+
Where(pred)
263+
query, args, err := r.buildSQL(builder)
248264
if err != nil {
249-
err = fmt.Errorf("failed fetching asset version: %w", err)
250-
return
265+
return asset.Asset{}, fmt.Errorf("error building query: %w", err)
251266
}
252267

253-
ast, err = assetModel.toVersionedAsset(latestAsset)
268+
err = r.client.db.GetContext(ctx, &ast, query, args...)
269+
if err != nil {
270+
return asset.Asset{}, fmt.Errorf("failed fetching asset version: %w", err)
271+
}
254272

255-
return
273+
return ast.toVersionedAsset(latest)
256274
}
257275

258276
// Upsert creates a new asset if it does not exist yet.

internal/store/postgres/asset_repository_test.go

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -803,16 +803,13 @@ func (r *AssetRepositoryTestSuite) TestVersions() {
803803
r.NoError(err)
804804
// making updatedby user time empty to make ast comparable
805805
for i := 0; i < len(assetVersions); i++ {
806-
assetVersions[i].UpdatedBy.CreatedAt = time.Time{}
807-
assetVersions[i].UpdatedBy.UpdatedAt = time.Time{}
808-
assetVersions[i].CreatedAt = time.Time{}
809-
assetVersions[i].UpdatedAt = time.Time{}
806+
clearTimestamps(&assetVersions[i])
810807
}
811808
r.Equal(expectedAssetVersions, assetVersions)
812809
})
813810

814811
r.Run("should return current version of an assets", func() {
815-
expectedLatestVersion := asset.Asset{
812+
expected := asset.Asset{
816813
ID: astVersioning.ID,
817814
URN: assetURN,
818815
Type: "table",
@@ -830,17 +827,14 @@ func (r *AssetRepositoryTestSuite) TestVersions() {
830827
ast.Owners = nil
831828
r.NoError(err)
832829
// making updatedby user time empty to make ast comparable
833-
ast.UpdatedBy.CreatedAt = time.Time{}
834-
ast.UpdatedBy.UpdatedAt = time.Time{}
835-
ast.CreatedAt = time.Time{}
836-
ast.UpdatedAt = time.Time{}
837-
r.Equal(expectedLatestVersion, ast)
830+
clearTimestamps(&ast)
831+
r.Equal(expected, ast)
838832

839833
r.Len(astOwners, 2)
840834
})
841835

842836
r.Run("should return current version of an assets with by version", func() {
843-
expectedLatestVersion := asset.Asset{
837+
expected := asset.Asset{
844838
ID: astVersioning.ID,
845839
URN: assetURN,
846840
Type: "table",
@@ -852,24 +846,31 @@ func (r *AssetRepositoryTestSuite) TestVersions() {
852846
UpdatedBy: r.users[1],
853847
}
854848

855-
ast, err := r.repository.GetByVersion(r.ctx, astVersioning.ID, "0.5")
849+
ast, err := r.repository.GetByVersionWithID(r.ctx, astVersioning.ID, "0.5")
856850
// hard to get the internally generated user id, we exclude the owners from the assertion
857851
astOwners := ast.Owners
858852
ast.Owners = nil
859853
r.NoError(err)
860854
// making updatedby user time empty to make ast comparable
861-
ast.UpdatedBy.CreatedAt = time.Time{}
862-
ast.UpdatedBy.UpdatedAt = time.Time{}
863-
ast.CreatedAt = time.Time{}
864-
ast.UpdatedAt = time.Time{}
865-
r.Equal(expectedLatestVersion, ast)
855+
clearTimestamps(&ast)
856+
r.Equal(expected, ast)
866857

867858
r.Len(astOwners, 2)
859+
860+
ast, err = r.repository.GetByVersionWithURN(r.ctx, astVersioning.URN, "0.5")
861+
// hard to get the internally generated user id, we exclude the owners from the assertion
862+
astOwners = ast.Owners
863+
ast.Owners = nil
864+
r.NoError(err)
865+
// making updatedby user time empty to make ast comparable
866+
clearTimestamps(&ast)
867+
r.Equal(expected, ast)
868+
r.Len(astOwners, 2)
868869
})
869870

870871
r.Run("should return a specific version of an asset", func() {
871-
selectedVersion := "0.3"
872-
expectedAsset := asset.Asset{
872+
version := "0.3"
873+
expected := asset.Asset{
873874
ID: astVersioning.ID,
874875
URN: assetURN,
875876
Type: "table",
@@ -891,17 +892,28 @@ func (r *AssetRepositoryTestSuite) TestVersions() {
891892
Provider: "meteor",
892893
},
893894
}
894-
astVer, err := r.repository.GetByVersion(r.ctx, astVersioning.ID, selectedVersion)
895+
astVer, err := r.repository.GetByVersionWithID(r.ctx, astVersioning.ID, version)
895896
// hard to get the internally generated user id, we exclude the owners from the assertion
896897
astOwners := astVer.Owners
897898
astVer.Owners = nil
898899
r.Assert().NoError(err)
899900
// making updatedby user time empty to make ast comparable
900-
astVer.UpdatedBy.CreatedAt = time.Time{}
901-
astVer.UpdatedBy.UpdatedAt = time.Time{}
902-
astVer.CreatedAt = time.Time{}
903-
astVer.UpdatedAt = time.Time{}
904-
r.Assert().Equal(expectedAsset, astVer)
901+
clearTimestamps(&astVer)
902+
r.Assert().Equal(expected, astVer)
903+
904+
for i := 0; i < len(astOwners); i++ {
905+
astOwners[i].ID = ""
906+
}
907+
r.Assert().Equal(expectedOwners, astOwners)
908+
909+
astVer, err = r.repository.GetByVersionWithURN(r.ctx, astVersioning.URN, version)
910+
// hard to get the internally generated user id, we exclude the owners from the assertion
911+
astOwners = astVer.Owners
912+
astVer.Owners = nil
913+
r.Assert().NoError(err)
914+
// making updatedby user time empty to make ast comparable
915+
clearTimestamps(&astVer)
916+
r.Assert().Equal(expected, astVer)
905917

906918
for i := 0; i < len(astOwners); i++ {
907919
astOwners[i].ID = ""
@@ -1767,6 +1779,13 @@ func (r *AssetRepositoryTestSuite) assertAsset(expectedAsset *asset.Asset, actua
17671779
return r.Equal(expectedAsset, actualAsset)
17681780
}
17691781

1782+
func clearTimestamps(ast *asset.Asset) {
1783+
ast.UpdatedBy.CreatedAt = time.Time{}
1784+
ast.UpdatedBy.UpdatedAt = time.Time{}
1785+
ast.CreatedAt = time.Time{}
1786+
ast.UpdatedAt = time.Time{}
1787+
}
1788+
17701789
func (r *AssetRepositoryTestSuite) assertProbe(t *testing.T, expected asset.Probe, actual asset.Probe) bool {
17711790
t.Helper()
17721791

0 commit comments

Comments
 (0)