@@ -415,16 +415,22 @@ class NCLifecycle {
415
415
async get_candidates ( bucket_json , lifecycle_rule , object_sdk ) {
416
416
const candidates = { abort_mpu_candidates : [ ] , delete_candidates : [ ] } ;
417
417
const rule_state = this . lifecycle_run_status . buckets_statuses [ bucket_json . name ] . rules_statuses [ lifecycle_rule . id ] ?. state || { } ;
418
+ const versions_list = undefined ;
418
419
if ( lifecycle_rule . expiration ) {
419
420
candidates . delete_candidates = await this . get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json ,
420
- object_sdk , rule_state ) ;
421
+ object_sdk ) ;
421
422
if ( lifecycle_rule . expiration . days || lifecycle_rule . expiration . expired_object_delete_marker ) {
422
423
const dm_candidates = await this . get_candidates_by_expiration_delete_marker_rule ( lifecycle_rule , bucket_json ) ;
423
424
candidates . delete_candidates = candidates . delete_candidates . concat ( dm_candidates ) ;
424
425
}
425
426
}
426
427
if ( lifecycle_rule . noncurrent_version_expiration ) {
427
- const non_current_candidates = await this . get_candidates_by_noncurrent_version_expiration_rule ( lifecycle_rule , bucket_json ) ;
428
+ const non_current_candidates = await this . get_candidates_by_noncurrent_version_expiration_rule (
429
+ lifecycle_rule ,
430
+ bucket_json ,
431
+ object_sdk ,
432
+ { versions_list}
433
+ ) ;
428
434
candidates . delete_candidates = candidates . delete_candidates . concat ( non_current_candidates ) ;
429
435
}
430
436
if ( lifecycle_rule . abort_incomplete_multipart_upload ) {
@@ -472,12 +478,12 @@ class NCLifecycle {
472
478
* @param {Object } bucket_json
473
479
* @returns {Promise<Object[]> }
474
480
*/
475
- async get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json , object_sdk , rule_state ) {
481
+ async get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json , object_sdk ) {
476
482
const is_gpfs = nb_native ( ) . fs . gpfs ;
477
483
if ( is_gpfs && config . NC_LIFECYCLE_GPFS_ILM_ENABLED ) {
478
484
return this . get_candidates_by_expiration_rule_gpfs ( lifecycle_rule , bucket_json ) ;
479
485
} else {
480
- return this . get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json , object_sdk , rule_state ) ;
486
+ return this . get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json , object_sdk ) ;
481
487
}
482
488
}
483
489
@@ -490,26 +496,41 @@ class NCLifecycle {
490
496
return [ ] ;
491
497
}
492
498
499
+ async load_objects_list ( object_sdk , lifecycle_rule , bucket_json , rule_state ) {
500
+ const objects_list = await object_sdk . list_objects ( {
501
+ bucket : bucket_json . name ,
502
+ prefix : lifecycle_rule . filter ?. prefix ,
503
+ key_marker : rule_state . key_marker ,
504
+ limit : config . NC_LIFECYCLE_LIST_BATCH_SIZE
505
+ } ) ;
506
+ if ( objects_list . is_truncated ) {
507
+ rule_state . key_marker = objects_list . next_marker ;
508
+ rule_state . is_finished = false ;
509
+ } else {
510
+ rule_state . is_finished = true ;
511
+ }
512
+ const bucket_state = this . lifecycle_run_status . buckets_statuses [ bucket_json . name ] . state ;
513
+ bucket_state . num_processed_objects += objects_list . objects . length ;
514
+ return objects_list ;
515
+ }
516
+
493
517
/**
494
518
*
495
519
* @param {* } lifecycle_rule
496
520
* @param {Object } bucket_json
497
521
* @returns {Promise<Object[]> }
498
522
*/
499
- async get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json , object_sdk , rule_state ) {
523
+ async get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json , object_sdk ) {
524
+ const rule_state = this . lifecycle_run_status . buckets_statuses [ bucket_json . name ] . rules_statuses [ lifecycle_rule . id ] . state . expire ;
525
+ if ( rule_state . is_finished ) return [ ] ;
500
526
const expiration = this . _get_expiration_time ( lifecycle_rule . expiration ) ;
501
527
if ( expiration < 0 ) return [ ] ;
502
528
const filter_func = this . _build_lifecycle_filter ( { filter : lifecycle_rule . filter , expiration} ) ;
503
529
504
530
const filtered_objects = [ ] ;
505
531
// TODO list_objects does not accept a filter and works in batch sizes of 1000. should handle batching
506
532
// also should maybe create a helper function or add argument for a filter in list object
507
- const objects_list = await object_sdk . list_objects ( {
508
- bucket : bucket_json . name ,
509
- prefix : lifecycle_rule . filter ?. prefix ,
510
- key_marker : rule_state . key_marker ,
511
- limit : config . NC_LIFECYCLE_LIST_BATCH_SIZE
512
- } ) ;
533
+ const objects_list = await this . load_objects_list ( object_sdk , lifecycle_rule , bucket_json , rule_state ) ;
513
534
objects_list . objects . forEach ( obj => {
514
535
const lifecycle_object = this . _get_lifecycle_object_info_from_list_object_entry ( obj ) ;
515
536
if ( filter_func ( lifecycle_object ) ) {
@@ -518,14 +539,6 @@ class NCLifecycle {
518
539
filtered_objects . push ( candidate ) ;
519
540
}
520
541
} ) ;
521
-
522
- const bucket_state = this . lifecycle_run_status . buckets_statuses [ bucket_json . name ] . state ;
523
- bucket_state . num_processed_objects += objects_list . objects . length ;
524
- if ( objects_list . is_truncated ) {
525
- rule_state . key_marker = objects_list . next_marker ;
526
- } else {
527
- rule_state . is_finished = true ;
528
- }
529
542
return filtered_objects ;
530
543
}
531
544
@@ -543,6 +556,63 @@ class NCLifecycle {
543
556
/////////////////////////////////////////////
544
557
//////// NON CURRENT VERSION HELPERS ////////
545
558
/////////////////////////////////////////////
559
+ /**
560
+ * load versions list bacth and update state for the next cycle
561
+ * @param {Object } object_sdk
562
+ * @param {Object } bucket_json
563
+ * @param {Object } rule_state
564
+ * @returns
565
+ */
566
+ async load_versions_list ( object_sdk , bucket_json , rule_state ) {
567
+ const list_versions = await object_sdk . list_object_versions ( {
568
+ bucket : bucket_json . name ,
569
+ prefix : rule_state . filter ?. prefix ,
570
+ limit : config . NC_LIFECYCLE_LIST_BATCH_SIZE ,
571
+ key_marker : rule_state . key_marker_versioned ,
572
+ version_id_marker : rule_state . version_id_marker
573
+ } ) ;
574
+ if ( list_versions . is_truncated ) {
575
+ rule_state . is_finished = false ;
576
+ rule_state . key_marker_versioned = list_versions . next_marker ;
577
+ rule_state . version_id_marker = list_versions . next_version_id_marker ;
578
+ } else {
579
+ rule_state . is_finished = true ;
580
+ }
581
+ const bucket_state = this . lifecycle_run_status . buckets_statuses [ bucket_json . name ] . state ;
582
+ bucket_state . num_processed_objects += list_versions . objects . length ;
583
+ return list_versions ;
584
+ }
585
+
586
+ /**
587
+ * check if object is delete candidate based on newer noncurrent versions rule
588
+ * @param {Object } object_info
589
+ * @param {Object } newer_noncurrent_state
590
+ * @param {Number } num_newer_versions
591
+ * @returns
592
+ */
593
+ filter_newer_versions ( object_info , newer_noncurrent_state , num_newer_versions ) {
594
+ if ( object_info . is_latest ) {
595
+ newer_noncurrent_state . version_count = 0 ; //latest
596
+ newer_noncurrent_state . current_version = object_info . key ;
597
+ return false ;
598
+ }
599
+ newer_noncurrent_state . version_count += 1 ;
600
+ if ( newer_noncurrent_state . version_count > num_newer_versions ) {
601
+ return true ;
602
+ }
603
+ return false ;
604
+ }
605
+
606
+ /**
607
+ * check if object is delete candidate based on number of noncurrent days rule
608
+ * @param {Object } object_info
609
+ * @param {Number } num_non_current_days
610
+ * @returns
611
+ */
612
+ filter_noncurrent_days ( object_info , num_non_current_days ) {
613
+ //TODO implement
614
+ return true ;
615
+ }
546
616
547
617
/**
548
618
* get_candidates_by_noncurrent_version_expiration_rule processes the noncurrent version expiration rule
@@ -553,11 +623,31 @@ class NCLifecycle {
553
623
* @param {Object } bucket_json
554
624
* @returns {Promise<Object[]> }
555
625
*/
556
- async get_candidates_by_noncurrent_version_expiration_rule ( lifecycle_rule , bucket_json ) {
557
- // TODO - implement
558
- return [ ] ;
559
- }
626
+ async get_candidates_by_noncurrent_version_expiration_rule ( lifecycle_rule , bucket_json , object_sdk , { versions_list} ) {
627
+ const rule_state = this . lifecycle_run_status . buckets_statuses [ bucket_json . name ] . rules_statuses [ lifecycle_rule . id ] . state . noncurrent ;
628
+ if ( rule_state . is_finished ) return [ ] ;
629
+
630
+ if ( ! versions_list ) {
631
+ versions_list = await this . load_versions_list ( object_sdk , bucket_json , rule_state ) ;
632
+ }
633
+
634
+ const filter_func = this . _build_lifecycle_filter ( { filter : lifecycle_rule . filter , expiration : 0 } ) ;
635
+ const num_newer_versions = lifecycle_rule . noncurrent_version_expiration . newer_noncurrent_versions ;
636
+ const num_non_current_days = lifecycle_rule . noncurrent_version_expiration . noncurrent_days ;
637
+ const delete_candidates = [ ] ;
638
+
639
+ for ( const entry of versions_list . objects ) {
640
+ const lifecycle_info = this . _get_lifecycle_object_info_from_list_object_entry ( entry ) ;
641
+ if ( ( num_newer_versions === undefined || this . filter_newer_versions ( entry , rule_state , num_newer_versions ) ) &&
642
+ ( num_non_current_days === undefined || this . filter_noncurrent_days ( entry , num_non_current_days ) ) ) {
643
+ if ( filter_func ( lifecycle_info ) ) {
644
+ delete_candidates . push ( { key : entry . key , version_id : entry . version_id } ) ;
645
+ }
646
+ }
647
+ }
560
648
649
+ return delete_candidates ;
650
+ }
561
651
////////////////////////////////////
562
652
///////// ABORT MPU HELPERS ////////
563
653
////////////////////////////////////
@@ -733,6 +823,11 @@ class NCLifecycle {
733
823
this . init_bucket_status ( bucket_name ) ;
734
824
}
735
825
}
826
+ if ( op_times . end_time ) {
827
+ if ( op_name === TIMED_OPS . PROCESS_RULE ) {
828
+ this . update_rule_status_is_finished ( bucket_name , rule_id ) ;
829
+ }
830
+ }
736
831
this . _update_times_on_status ( { op_name, op_times, bucket_name, rule_id } ) ;
737
832
this . _update_error_on_status ( { error, bucket_name, rule_id } ) ;
738
833
if ( bucket_name && rule_id ) {
@@ -879,12 +974,23 @@ class NCLifecycle {
879
974
*/
880
975
init_rule_status ( bucket_name , rule_id ) {
881
976
this . lifecycle_run_status . buckets_statuses [ bucket_name ] . rules_statuses [ rule_id ] ??= { } ;
882
- this . lifecycle_run_status . buckets_statuses [ bucket_name ] . rules_statuses [ rule_id ] . state ??= { } ;
977
+ this . lifecycle_run_status . buckets_statuses [ bucket_name ] . rules_statuses [ rule_id ] . state ??= { expire : { } , noncurrent : { } } ;
883
978
this . lifecycle_run_status . buckets_statuses [ bucket_name ] . rules_statuses [ rule_id ] . rule_process_times = { } ;
884
979
this . lifecycle_run_status . buckets_statuses [ bucket_name ] . rules_statuses [ rule_id ] . rule_stats = { } ;
885
980
return this . lifecycle_run_status . buckets_statuses [ bucket_name ] . rules_statuses [ rule_id ] ;
886
981
}
887
982
983
+ /**
984
+ * updates the rule state if all actions finished
985
+ * @param {string } bucket_name
986
+ * @param {string } rule_id
987
+ */
988
+ update_rule_status_is_finished ( bucket_name , rule_id ) {
989
+ const rule_state = this . lifecycle_run_status . buckets_statuses [ bucket_name ] . rules_statuses [ rule_id ] . state ;
990
+ rule_state . is_finished = ( rule_state . expire . is_finished === undefined || rule_state . expire . is_finished === true ) &&
991
+ ( rule_state . noncurrent . is_finished === undefined || rule_state . noncurrent . is_finished === true ) ;
992
+ }
993
+
888
994
/**
889
995
*
890
996
* @param {Object[] } buckets
@@ -908,7 +1014,7 @@ class NCLifecycle {
908
1014
}
909
1015
}
910
1016
}
911
- }
1017
+ }
912
1018
}
913
1019
914
1020
//////////////////
0 commit comments