@@ -12,15 +12,15 @@ const ManageCLIError = require('./manage_nsfs_cli_errors').ManageCLIError;
1212const path = require ( 'path' ) ;
1313const { throw_cli_error, get_service_status, NOOBAA_SERVICE_NAME } = require ( './manage_nsfs_cli_utils' ) ;
1414
15- // TODO:
16- // implement
15+ // TODO:
16+ // implement
1717// 1. notifications
1818// 2. POSIX scanning and filtering per rule
1919// 3. GPFS ILM policy and apply for scanning and filtering optimization
2020
2121/**
2222 * run_lifecycle runs the lifecycle workflow
23- * @param {import('../sdk/config_fs').ConfigFS } config_fs
23+ * @param {import('../sdk/config_fs').ConfigFS } config_fs
2424 * @returns {Promise<Void> }
2525 */
2626async function run_lifecycle ( config_fs , disable_service_validation ) {
@@ -47,7 +47,7 @@ async function run_lifecycle(config_fs, disable_service_validation) {
4747
4848/**
4949 * throw_if_noobaa_not_active checks if system.json exists and the noobaa service is active
50- * @param {import('../sdk/config_fs').ConfigFS } config_fs
50+ * @param {import('../sdk/config_fs').ConfigFS } config_fs
5151 * @param {Object } system_json
5252 */
5353async function throw_if_noobaa_not_active ( config_fs , system_json ) {
@@ -64,14 +64,32 @@ async function throw_if_noobaa_not_active(config_fs, system_json) {
6464}
6565
6666/**
67- * get file time since last modified in days
68- * @param { nb.NativeFSStats } stat
67+ * @param { Number } mtime
68+ * @returns { Number } days since object was last modified
6969 */
70- function _get_file_age_days ( stat ) {
71- //TODO how much do we care about rounding errors? (it is by days after all)
72- return ( Date . now ( ) - Number ( stat . mtimeNsBigint ) / 1e6 ) / 24 / 60 / 60 / 1000 ;
70+ function _get_file_age_days ( mtime ) {
71+ return Math . floor ( ( Date . now ( ) - mtime ) / 24 / 60 / 60 / 1000 ) ;
7372}
7473
74+ /**
75+ * get the expiration time in days of an object
76+ * if rule is set with date, then rule is applied for all objects after that date
77+ * return -1 to indicate that the date hasn't arrived, so rule should not be applied
78+ * return 0 in case date has arrived so expiration is true for all elements
79+ * return days in case days was defined and not date
80+ * @param {Object } expiration_rule
81+ * @returns {Number }
82+ */
83+ function _get_expiration_time ( expiration_rule ) {
84+ if ( expiration_rule . date ) {
85+ const expiration_date = new Date ( expiration_rule . date ) . getTime ( ) ;
86+ if ( Date . now ( ) < expiration_date ) return - 1 ;
87+ return 0 ;
88+ }
89+ return expiration_rule . days ;
90+ }
91+
92+
7593/**
7694 * checks if tag query_tag is in the list tag_set
7795 * @param {Object } query_tag
@@ -101,17 +119,28 @@ function _file_contain_tags(object_info, filter_tags) {
101119}
102120
103121/**
104- * @param {* } create_params_parsed
122+ * @param {Object } create_params_parsed
105123 * @param {nb.NativeFSStats } stat
106124 */
107125function _get_lifecycle_object_info_for_mpu ( create_params_parsed , stat ) {
108126 return {
109127 key : create_params_parsed . key ,
110- age : _get_file_age_days ( stat ) ,
128+ age : _get_file_age_days ( stat . mtime . getTime ( ) ) ,
111129 tags : create_params_parsed . tagging ,
112130 } ;
113131}
114132
133+ /**
134+ * @param {Object } entry list object entry
135+ */
136+ function _get_lifecycle_object_info_from_list_object_entry ( entry ) {
137+ return {
138+ key : entry . key ,
139+ age : _get_file_age_days ( entry . create_time ) ,
140+ size : entry . size ,
141+ tags : entry . tagging ,
142+ } ;
143+ }
115144
116145/**
117146 * @typedef {{
@@ -170,7 +199,8 @@ async function get_delete_candidates(bucket_json, lifecycle_rule, object_sdk, fs
170199 // let reply_objects = []; // TODO: needed for the notification log file
171200 const candidates = { delete_candidates : [ ] } ;
172201 if ( lifecycle_rule . expiration ) {
173- await get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json ) ;
202+ const expiration_candidates = await get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json , object_sdk ) ;
203+ candidates . delete_candidates = candidates . delete_candidates . concat ( expiration_candidates ) ;
174204 if ( lifecycle_rule . expiration . days || lifecycle_rule . expiration . expired_object_delete_marker ) {
175205 await get_candidates_by_expiration_delete_marker_rule ( lifecycle_rule , bucket_json ) ;
176206 }
@@ -187,9 +217,9 @@ async function get_delete_candidates(bucket_json, lifecycle_rule, object_sdk, fs
187217
188218/**
189219 * validate_rule_enabled checks if the rule is enabled and should be processed
190- * @param {* } rule
191- * @param {Object } bucket
192- * @param {* } now
220+ * @param {* } rule
221+ * @param {Object } bucket
222+ * @param {* } now
193223 * @returns {boolean }
194224 */
195225function validate_rule_enabled ( rule , bucket , now ) {
@@ -208,40 +238,55 @@ function validate_rule_enabled(rule, bucket, now) {
208238
209239/**
210240 * get_candidates_by_expiration_rule processes the expiration rule
211- * @param {* } lifecycle_rule
212- * @param {Object } bucket_json
241+ * @param {* } lifecycle_rule
242+ * @param {Object } bucket_json
213243 */
214- async function get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json ) {
244+ async function get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json , object_sdk ) {
215245 const is_gpfs = nb_native ( ) . fs . gpfs ;
216246 if ( is_gpfs ) {
217- await get_candidates_by_expiration_rule_gpfs ( lifecycle_rule , bucket_json ) ;
247+ return await get_candidates_by_expiration_rule_gpfs ( lifecycle_rule , bucket_json ) ;
218248 } else {
219- await get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json ) ;
249+ return await get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json , object_sdk ) ;
220250 }
221251}
222252
223253/**
224- *
225- * @param {* } lifecycle_rule
226- * @param {Object } bucket_json
254+ *
255+ * @param {* } lifecycle_rule
256+ * @param {Object } bucket_json
227257 */
228258async function get_candidates_by_expiration_rule_gpfs ( lifecycle_rule , bucket_json ) {
229259 // TODO - implement
230260}
231261
232262/**
233- *
234- * @param {* } lifecycle_rule
235- * @param {Object } bucket_json
263+ *
264+ * @param {* } lifecycle_rule
265+ * @param {Object } bucket_json
236266 */
237- async function get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json ) {
238- // TODO - implement
267+ async function get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json , object_sdk ) {
268+ const expiration = _get_expiration_time ( lifecycle_rule . expiration ) ;
269+ if ( expiration < 0 ) return [ ] ;
270+ const filter_func = _build_lifecycle_filter ( { filter : lifecycle_rule . filter , expiration} ) ;
271+
272+ const filtered_objects = [ ] ;
273+ // TODO list_objects does not accept a filter and works in batch sizes of 1000. should handle batching
274+ // also should maybe create a helper function or add argument for a filter in list object
275+ const objects_list = await object_sdk . list_objects ( { bucket : bucket_json . name , prefix : lifecycle_rule . filter ?. prefix } ) ;
276+ objects_list . objects . forEach ( obj => {
277+ const object_info = _get_lifecycle_object_info_from_list_object_entry ( obj ) ;
278+ if ( filter_func ( object_info ) ) {
279+ filtered_objects . push ( { key : object_info . key } ) ;
280+ }
281+ } ) ;
282+ return filtered_objects ;
283+
239284}
240285
241286/**
242287 * get_candidates_by_expiration_delete_marker_rule processes the expiration delete marker rule
243- * @param {* } lifecycle_rule
244- * @param {Object } bucket_json
288+ * @param {* } lifecycle_rule
289+ * @param {Object } bucket_json
245290 */
246291async function get_candidates_by_expiration_delete_marker_rule ( lifecycle_rule , bucket_json ) {
247292 // TODO - implement
0 commit comments