Skip to content

Commit 3c0de5f

Browse files
lpolipeterlimgcnlangzi
authored
Feature/list recent files (#755)
* Remove whopays attribute * Remove dot logger * Fix hashes of test * Remove redundant payer id field * Remove authticket association with readmarker * Fix conflicts * Remove proto file * Update go modules * Generate/Update grpc code * Go mod tidy * Remove payer in test insertion * Make reader pay for read instead of owner * Go mod tidy * Add separate handler for directory creation * Separate directory creation handling * Replace time.Time with common.Timestamp in refs Remove deleted_at column Update tests Optimize *change.go files * Optimize upload file changer * Remove unrequired files * Remove dot import and fmt prints * Fix imports * Update timestamp * Remove calculate hash feature * Fix gosimple issue * Return nil for root path * Reduce slice size * Fix rename issues * Fix timestamp issue and missing db save * Update timestamp for delete operation * Fix tests * Use condition * Check error * Fix root row retrieval issue * Remove deleted columns usages * Add log * Use deleted_at functionality to delete files Use children loaded condition * Fix missing level and ordering issue * Fix missing level issue * Add path hash * Undo path hash removal * Uncomment workers * Uncomment workers and add loop label * Fix unit tests * Merge stashed changes * Remove unrequired argument * Complete function * Use goroutines to execute two queries * Add endpoint * Add from date parameter to filter refs * Merge staging into feature/list-recent-files * Remove same file with two names * Remove fmt print * Remove fmt print * Rename URI * Remove total pages count in response * Use appropriate constants Co-authored-by: peterlimg <54137706+peterlimg@users.noreply.github.com> Co-authored-by: peterlimg <peterlimg@protonmail.com> Co-authored-by: Lz <imlangzi@qq.com>
1 parent 89c9544 commit 3c0de5f

File tree

8 files changed

+136
-10
lines changed

8 files changed

+136
-10
lines changed

code/go/0chain.net/blobbercore/allocation/copyfilechange.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (rf *CopyFileChange) DeleteTempFile() error {
2828
func (rf *CopyFileChange) ApplyChange(ctx context.Context, change *AllocationChange,
2929
allocationRoot string, ts common.Timestamp) (*reference.Ref, error) {
3030

31-
totalRefs, err := reference.CountRefs(ctx, rf.AllocationID)
31+
totalRefs, err := reference.CountRefs(rf.AllocationID)
3232
if err != nil {
3333
return nil, err
3434
}

code/go/0chain.net/blobbercore/allocation/file_changer_upload.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type UploadFileChanger struct {
2424
func (nf *UploadFileChanger) ApplyChange(ctx context.Context, change *AllocationChange,
2525
allocationRoot string, ts common.Timestamp) (*reference.Ref, error) {
2626

27-
totalRefs, err := reference.CountRefs(ctx, nf.AllocationID)
27+
totalRefs, err := reference.CountRefs(nf.AllocationID)
2828
if err != nil {
2929
return nil, err
3030
}

code/go/0chain.net/blobbercore/allocation/newdirchange.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type NewDir struct {
2323
func (nf *NewDir) ApplyChange(ctx context.Context, change *AllocationChange,
2424
allocationRoot string, ts common.Timestamp) (*reference.Ref, error) {
2525

26-
totalRefs, err := reference.CountRefs(ctx, nf.AllocationID)
26+
totalRefs, err := reference.CountRefs(nf.AllocationID)
2727
if err != nil {
2828
return nil, err
2929
}

code/go/0chain.net/blobbercore/blobberhttp/response.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ type RefResult struct {
4242
LatestWM *writemarker.WriteMarker `json:"latest_write_marker"`
4343
}
4444

45+
type RecentRefResult struct {
46+
Offset int `json:"offset"`
47+
Refs []*reference.PaginatedRef `json:"refs"`
48+
}
4549
type ObjectPathResult struct {
4650
*reference.ObjectPath
4751
LatestWM *writemarker.WriteMarker `json:"latest_write_marker"`

code/go/0chain.net/blobbercore/handler/handler.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ func SetupHandlers(r *mux.Router) {
6161
r.HandleFunc("/v1/file/referencepath/{allocation}", common.ToJSONResponse(WithReadOnlyConnection(ReferencePathHandler)))
6262
r.HandleFunc("/v1/file/objecttree/{allocation}", common.ToStatusCode(WithStatusReadOnlyConnection(ObjectTreeHandler))).Methods(http.MethodGet, http.MethodOptions)
6363
r.HandleFunc("/v1/file/refs/{allocation}", common.ToJSONResponse(WithReadOnlyConnection(RefsHandler))).Methods(http.MethodGet, http.MethodOptions)
64+
r.HandleFunc("/v1/file/refs/recent/{allocation}", common.ToJSONResponse(WithReadOnlyConnection(RecentRefsRequestHandler))).Methods(http.MethodGet, http.MethodOptions)
6465
//admin related
6566
r.HandleFunc("/_debug", common.ToJSONResponse(DumpGoRoutines))
6667
r.HandleFunc("/_config", common.ToJSONResponse(GetConfig))
@@ -240,6 +241,15 @@ func RefsHandler(ctx context.Context, r *http.Request) (interface{}, error) {
240241
return response, nil
241242
}
242243

244+
func RecentRefsRequestHandler(ctx context.Context, r *http.Request) (interface{}, error) {
245+
ctx = setupHandlerContext(ctx, r)
246+
response, err := storageHandler.GetRecentlyAddedRefs(ctx, r)
247+
if err != nil {
248+
return nil, err
249+
}
250+
return response, nil
251+
}
252+
243253
func RenameHandler(ctx context.Context, r *http.Request) (interface{}, error) {
244254

245255
ctx = setupHandlerContext(ctx, r)

code/go/0chain.net/blobbercore/handler/storage_handler.go

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ const (
3030
OffsetDateLayout = "2006-01-02T15:04:05.99999Z07:00"
3131
DownloadContentFull = "full"
3232
DownloadContentThumb = "thumbnail"
33-
PageLimit = 100 //100 rows will make up to 100 KB
33+
MaxPageLimit = 100 //100 rows will make up to 100 KB
34+
DefaultPageLimit = 20
3435
)
3536

3637
type StorageHandler struct{}
@@ -782,6 +783,88 @@ func (fsh *StorageHandler) GetObjectTree(ctx context.Context, r *http.Request) (
782783
return &refPathResult, nil
783784
}
784785

786+
func (fsh *StorageHandler) GetRecentlyAddedRefs(ctx context.Context, r *http.Request) (*blobberhttp.RecentRefResult, error) {
787+
allocationTx := ctx.Value(constants.ContextKeyAllocation).(string)
788+
allocationObj, err := fsh.verifyAllocation(ctx, allocationTx, false)
789+
790+
if err != nil {
791+
return nil, common.NewError("invalid_parameters", "Invalid allocation id passed."+err.Error())
792+
}
793+
794+
clientID := ctx.Value(constants.ContextKeyClient).(string)
795+
if clientID == "" {
796+
return nil, common.NewError("invalid_operation", "Client id is required")
797+
}
798+
799+
publicKey, _ := ctx.Value(constants.ContextKeyClientKey).(string)
800+
if publicKey == "" {
801+
if clientID == allocationObj.OwnerID {
802+
publicKey = allocationObj.OwnerPublicKey
803+
} else {
804+
return nil, common.NewError("empty_public_key", "public key is required")
805+
}
806+
}
807+
808+
clientSign := ctx.Value(constants.ContextKeyClientSignatureHeaderKey).(string)
809+
810+
valid, err := verifySignatureFromRequest(allocationTx, clientSign, publicKey)
811+
if !valid || err != nil {
812+
return nil, common.NewError("invalid_signature", "Invalid signature")
813+
}
814+
815+
allocationID := allocationObj.ID
816+
817+
var offset, pageLimit int
818+
offsetStr := r.FormValue("offset")
819+
820+
if offsetStr != "" {
821+
offset, err = strconv.Atoi(offsetStr)
822+
if err != nil {
823+
return nil, common.NewError("invalid_parameters", "Invalid offset value "+err.Error())
824+
}
825+
}
826+
827+
pageLimitStr := r.FormValue("page_limit")
828+
if pageLimitStr != "" {
829+
pageLimit, err = strconv.Atoi(pageLimitStr)
830+
if err != nil {
831+
return nil, common.NewError("invalid_parameters", "Invalid page limit value. Got Error "+err.Error())
832+
}
833+
if pageLimit < 0 {
834+
return nil, common.NewError("invalid_parameters", "Zero/Negative page limit value is not allowed")
835+
}
836+
837+
if pageLimit > MaxPageLimit {
838+
pageLimit = MaxPageLimit
839+
}
840+
841+
} else {
842+
pageLimit = DefaultPageLimit
843+
}
844+
845+
var fromDate int
846+
fromDateStr := r.FormValue("from_date")
847+
if fromDateStr != "" {
848+
fromDate, err = strconv.Atoi(fromDateStr)
849+
if err != nil {
850+
return nil, common.NewError("invalid_parameters", "Invalid from date value. Got error "+err.Error())
851+
}
852+
if fromDate < 0 {
853+
return nil, common.NewError("invalid_parameters", "Negative from date value is not allowed")
854+
}
855+
}
856+
857+
refs, offset, err := reference.GetRecentlyCreatedRefs(ctx, allocationID, pageLimit, offset, fromDate)
858+
if err != nil {
859+
return nil, err
860+
}
861+
862+
return &blobberhttp.RecentRefResult{
863+
Refs: refs,
864+
Offset: offset,
865+
}, nil
866+
}
867+
785868
//Retrieves file refs. One can use three types to refer to regular, updated and deleted. Regular type gives all undeleted rows.
786869
//Updated gives rows that is updated compared to the date given. And deleted gives deleted refs compared to the date given.
787870
//Updated date time format should be as declared in above constant; OffsetDateLayout
@@ -886,16 +969,16 @@ func (fsh *StorageHandler) GetRefs(ctx context.Context, r *http.Request) (*blobb
886969
pageLimitStr := r.FormValue("pageLimit")
887970
var pageLimit int
888971
if pageLimitStr == "" {
889-
pageLimit = PageLimit
972+
pageLimit = DefaultPageLimit
890973
} else {
891974
o, err := strconv.Atoi(pageLimitStr)
892975
if err != nil {
893976
return nil, common.NewError("invalid_parameters", "Invalid page limit value type")
894977
}
895978
if o <= 0 {
896979
return nil, common.NewError("invalid_parameters", "Zero/Negative page limit value is not allowed")
897-
} else if o > PageLimit {
898-
pageLimit = PageLimit
980+
} else if o > MaxPageLimit {
981+
pageLimit = MaxPageLimit
899982
} else {
900983
pageLimit = o
901984
}

code/go/0chain.net/blobbercore/reference/ref.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ type Ref struct {
5757
OnCloud bool `gorm:"column:on_cloud;default:false" filelist:"on_cloud"`
5858

5959
CommitMetaTxns []CommitMetaTxn `gorm:"foreignkey:ref_id" filelist:"commit_meta_txns"`
60-
CreatedAt common.Timestamp `gorm:"column:created_at" dirlist:"created_at" filelist:"created_at"`
61-
UpdatedAt common.Timestamp `gorm:"column:updated_at;index:idx_updated_at;" dirlist:"updated_at" filelist:"updated_at"`
60+
CreatedAt common.Timestamp `gorm:"column:created_at;index:idx_created_at,sort:desc" dirlist:"created_at" filelist:"created_at"`
61+
UpdatedAt common.Timestamp `gorm:"column:updated_at;index:idx_updated_at,sort:desc;" dirlist:"updated_at" filelist:"updated_at"`
6262

6363
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at"` // soft deletion
6464

code/go/0chain.net/blobbercore/reference/referencepath.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,36 @@ func GetUpdatedRefs(ctx context.Context, allocationID, path, offsetPath, _type,
294294
return
295295
}
296296

297-
func CountRefs(ctx context.Context, allocationID string) (int64, error) {
297+
// GetRecentlyCreatedRefs will return recently created refs with pagination. As opposed to getting
298+
// refs ordered by path in ascending order, this will return paths in decending order for same timestamp.
299+
// So if a file is created with path "/a/b/c/d/e/f.txt" and if "/a" didn't exist previously then
300+
// creation date for "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/a/b/c/d/e" and "/a/b/c/d/e/f.txt" will be the same.
301+
// The refs returned will be in "/a/b/c/d/e/f.txt", "/a/b/c/d/e", ... order.
302+
//
303+
// pageLimit --> maximum number of refs to return
304+
// fromDate --> timestamp to begin searching refs from i.e. refs created date greater than fromDate
305+
// newOffset --> offset to use for subsequent request
306+
func GetRecentlyCreatedRefs(
307+
// Note: Above mentioned function will only be feasible after splitting reference_objects table.
308+
// Since current limit is 50,000 files per allocation, Using common offset method should not be a big
309+
// deal
310+
ctx context.Context,
311+
allocID string,
312+
pageLimit, offset, fromDate int,
313+
) (refs []*PaginatedRef, newOffset int, err error) {
314+
315+
db := datastore.GetStore().GetTransaction(ctx)
316+
err = db.Model(&Ref{}).Where("allocation_id=? AND created_at > ?",
317+
allocID, fromDate).
318+
Order("created_at desc, path asc").
319+
Offset(offset).
320+
Limit(pageLimit).Find(&refs).Error
321+
322+
newOffset = offset + len(refs)
323+
return
324+
}
325+
326+
func CountRefs(allocationID string) (int64, error) {
298327
var totalRows int64
299328

300329
db := datastore.GetStore().GetDB()

0 commit comments

Comments
 (0)