Skip to content

Commit a7a2dd8

Browse files
committed
NC | lifecycle | add newer noncurrent versions rule
Signed-off-by: nadav mizrahi <[email protected]>
1 parent 469392a commit a7a2dd8

File tree

2 files changed

+394
-108
lines changed

2 files changed

+394
-108
lines changed

src/manage_nsfs/nc_lifecycle.js

Lines changed: 112 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -415,16 +415,22 @@ class NCLifecycle {
415415
async get_candidates(bucket_json, lifecycle_rule, object_sdk) {
416416
const candidates = { abort_mpu_candidates: [], delete_candidates: [] };
417417
const rule_state = this.lifecycle_run_status.buckets_statuses[bucket_json.name].rules_statuses[lifecycle_rule.id]?.state || {};
418+
const versions_list = undefined;
418419
if (lifecycle_rule.expiration) {
419420
candidates.delete_candidates = await this.get_candidates_by_expiration_rule(lifecycle_rule, bucket_json,
420-
object_sdk, rule_state);
421+
object_sdk);
421422
if (lifecycle_rule.expiration.days || lifecycle_rule.expiration.expired_object_delete_marker) {
422423
const dm_candidates = await this.get_candidates_by_expiration_delete_marker_rule(lifecycle_rule, bucket_json);
423424
candidates.delete_candidates = candidates.delete_candidates.concat(dm_candidates);
424425
}
425426
}
426427
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+
);
428434
candidates.delete_candidates = candidates.delete_candidates.concat(non_current_candidates);
429435
}
430436
if (lifecycle_rule.abort_incomplete_multipart_upload) {
@@ -472,12 +478,12 @@ class NCLifecycle {
472478
* @param {Object} bucket_json
473479
* @returns {Promise<Object[]>}
474480
*/
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) {
476482
const is_gpfs = nb_native().fs.gpfs;
477483
if (is_gpfs && config.NC_LIFECYCLE_GPFS_ILM_ENABLED) {
478484
return this.get_candidates_by_expiration_rule_gpfs(lifecycle_rule, bucket_json);
479485
} 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);
481487
}
482488
}
483489

@@ -490,26 +496,41 @@ class NCLifecycle {
490496
return [];
491497
}
492498

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+
493517
/**
494518
*
495519
* @param {*} lifecycle_rule
496520
* @param {Object} bucket_json
497521
* @returns {Promise<Object[]>}
498522
*/
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 [];
500526
const expiration = this._get_expiration_time(lifecycle_rule.expiration);
501527
if (expiration < 0) return [];
502528
const filter_func = this._build_lifecycle_filter({filter: lifecycle_rule.filter, expiration});
503529

504530
const filtered_objects = [];
505531
// TODO list_objects does not accept a filter and works in batch sizes of 1000. should handle batching
506532
// 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);
513534
objects_list.objects.forEach(obj => {
514535
const lifecycle_object = this._get_lifecycle_object_info_from_list_object_entry(obj);
515536
if (filter_func(lifecycle_object)) {
@@ -518,14 +539,6 @@ class NCLifecycle {
518539
filtered_objects.push(candidate);
519540
}
520541
});
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-
}
529542
return filtered_objects;
530543
}
531544

@@ -544,6 +557,44 @@ class NCLifecycle {
544557
//////// NON CURRENT VERSION HELPERS ////////
545558
/////////////////////////////////////////////
546559

560+
async load_versions_list(object_sdk, bucket_json, rule_state) {
561+
const list_versions = await object_sdk.list_object_versions({
562+
bucket: bucket_json.name,
563+
prefix: rule_state.filter?.prefix,
564+
limit: config.NC_LIFECYCLE_LIST_BATCH_SIZE,
565+
key_marker: rule_state.key_marker_versioned,
566+
version_id_marker: rule_state.version_id_marker
567+
});
568+
if (list_versions.is_truncated) {
569+
rule_state.is_finished = false;
570+
rule_state.key_marker_versioned = list_versions.next_marker;
571+
rule_state.version_id_marker = list_versions.next_version_id_marker;
572+
} else {
573+
rule_state.is_finished = true;
574+
}
575+
const bucket_state = this.lifecycle_run_status.buckets_statuses[bucket_json.name].state;
576+
bucket_state.num_processed_objects += list_versions.objects.length;
577+
return list_versions;
578+
}
579+
580+
filter_newer_versions(object_info, newer_noncurrent_state, num_newer_versions) {
581+
if (object_info.is_latest) {
582+
newer_noncurrent_state.version_count = 0; //latest
583+
newer_noncurrent_state.current_version = object_info.key;
584+
return false;
585+
}
586+
newer_noncurrent_state.version_count += 1;
587+
if (newer_noncurrent_state.version_count > num_newer_versions) {
588+
return true;
589+
}
590+
return false;
591+
}
592+
593+
filter_noncurrent_days(object_info, num_non_current_days) {
594+
//TODO implement
595+
return false;
596+
}
597+
547598
/**
548599
* get_candidates_by_noncurrent_version_expiration_rule processes the noncurrent version expiration rule
549600
* TODO:
@@ -553,11 +604,31 @@ class NCLifecycle {
553604
* @param {Object} bucket_json
554605
* @returns {Promise<Object[]>}
555606
*/
556-
async get_candidates_by_noncurrent_version_expiration_rule(lifecycle_rule, bucket_json) {
557-
// TODO - implement
558-
return [];
559-
}
607+
async get_candidates_by_noncurrent_version_expiration_rule(lifecycle_rule, bucket_json, object_sdk, {versions_list}) {
608+
const rule_state = this.lifecycle_run_status.buckets_statuses[bucket_json.name].rules_statuses[lifecycle_rule.id].state.noncurrent;
609+
if (rule_state.is_finished) return [];
560610

611+
if (!versions_list) {
612+
versions_list = await this.load_versions_list(object_sdk, bucket_json, rule_state);
613+
}
614+
615+
const filter_func = this._build_lifecycle_filter({filter: lifecycle_rule.filter, expiration: 0});
616+
const num_newer_versions = lifecycle_rule.noncurrent_version_expiration.newer_noncurrent_versions;
617+
const num_non_current_days = lifecycle_rule.noncurrent_version_expiration.noncurrent_days;
618+
const delete_candidates = [];
619+
620+
for (const entry of versions_list.objects) {
621+
const lifecycle_info = this._get_lifecycle_object_info_from_list_object_entry(entry);
622+
if ((num_newer_versions !== undefined && this.filter_newer_versions(entry, rule_state, num_newer_versions)) ||
623+
(num_non_current_days !== undefined && this.filter_noncurrent_days(entry, num_non_current_days))) {
624+
if (filter_func(lifecycle_info)) {
625+
delete_candidates.push({key: entry.key, version_id: entry.version_id});
626+
}
627+
}
628+
}
629+
630+
return delete_candidates;
631+
}
561632
////////////////////////////////////
562633
///////// ABORT MPU HELPERS ////////
563634
////////////////////////////////////
@@ -733,6 +804,11 @@ class NCLifecycle {
733804
this.init_bucket_status(bucket_name);
734805
}
735806
}
807+
if (op_times.end_time) {
808+
if (op_name === TIMED_OPS.PROCESS_RULE) {
809+
this.update_rule_status_is_finished(bucket_name, rule_id);
810+
}
811+
}
736812
this._update_times_on_status({ op_name, op_times, bucket_name, rule_id });
737813
this._update_error_on_status({ error, bucket_name, rule_id });
738814
if (bucket_name && rule_id) {
@@ -879,12 +955,23 @@ class NCLifecycle {
879955
*/
880956
init_rule_status(bucket_name, rule_id) {
881957
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 ??= {};
958+
this.lifecycle_run_status.buckets_statuses[bucket_name].rules_statuses[rule_id].state ??= {expire: {}, noncurrent: {}};
883959
this.lifecycle_run_status.buckets_statuses[bucket_name].rules_statuses[rule_id].rule_process_times = {};
884960
this.lifecycle_run_status.buckets_statuses[bucket_name].rules_statuses[rule_id].rule_stats = {};
885961
return this.lifecycle_run_status.buckets_statuses[bucket_name].rules_statuses[rule_id];
886962
}
887963

964+
/**
965+
* updates the rule state if all actions finished
966+
* @param {string} bucket_name
967+
* @param {string} rule_id
968+
*/
969+
update_rule_status_is_finished(bucket_name, rule_id) {
970+
const rule_state = this.lifecycle_run_status.buckets_statuses[bucket_name].rules_statuses[rule_id].state;
971+
rule_state.is_finished = (rule_state.expire.is_finished === undefined || rule_state.expire.is_finished === true) &&
972+
(rule_state.noncurrent.is_finished === undefined || rule_state.noncurrent.is_finished === true);
973+
}
974+
888975
/**
889976
*
890977
* @param {Object[]} buckets
@@ -908,7 +995,7 @@ class NCLifecycle {
908995
}
909996
}
910997
}
911-
}
998+
}
912999
}
9131000

9141001
//////////////////

0 commit comments

Comments
 (0)