Skip to content

Commit 3588a15

Browse files
tangledbytesromayalon
authored andcommitted
move away from running expiry on interval - use fixed hh:mm
Signed-off-by: Utkarsh Srivastava <[email protected]> address PR comments Signed-off-by: Utkarsh Srivastava <[email protected]> set millis to 0 Signed-off-by: Utkarsh Srivastava <[email protected]> (cherry picked from commit 90a2fa6)
1 parent d4917eb commit 3588a15

File tree

3 files changed

+96
-8
lines changed

3 files changed

+96
-8
lines changed

config.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -751,9 +751,19 @@ config.NSFS_GLACIER_MIGRATE_INTERVAL = 15 * 60 * 1000;
751751
// of `manage_nsfs glacier restore`
752752
config.NSFS_GLACIER_RESTORE_INTERVAL = 15 * 60 * 1000;
753753

754-
// NSFS_GLACIER_EXPIRY_INTERVAL indicates the interval between runs
755-
// of `manage_nsfs glacier expiry`
756-
config.NSFS_GLACIER_EXPIRY_INTERVAL = 12 * 60 * 60 * 1000;
754+
// NSFS_GLACIER_EXPIRY_RUN_TIME must be of the format hh:mm which specifies
755+
// when NooBaa should allow running glacier expiry process
756+
// NOTE: This will also be in the same timezone as specified in
757+
// NSFS_GLACIER_EXPIRY_TZ
758+
config.NSFS_GLACIER_EXPIRY_RUN_TIME = '03:00';
759+
760+
// NSFS_GLACIER_EXPIRY_RUN_TIME_TOLERANCE_MINS configures the delay
761+
// tolerance in minutes.
762+
//
763+
// eg. If the expiry run time is set to 03:00 and the tolerance is
764+
// set to be 2 mins then the expiry can trigger till 03:02 (unless
765+
// already triggered between 03:00 - 03:02
766+
config.NSFS_GLACIER_EXPIRY_RUN_DELAY_LIMIT_MINS = 2 * 60;
757767

758768
/** @type {'UTC' | 'LOCAL'} */
759769
config.NSFS_GLACIER_EXPIRY_TZ = 'LOCAL';

src/manage_nsfs/manage_nsfs_glacier.js

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,65 @@ async function process_expiry() {
6969
const fs_context = native_fs_utils.get_process_fs_context();
7070

7171
await lock_and_run(fs_context, SCAN_LOCK, async () => {
72-
if (!(await time_exceeded(fs_context, config.NSFS_GLACIER_EXPIRY_INTERVAL, GlacierBackend.EXPIRY_TIMESTAMP_FILE))) return;
72+
const backend = getGlacierBackend();
73+
if (
74+
await backend.low_free_space() ||
75+
await is_desired_time(
76+
fs_context,
77+
new Date(),
78+
config.NSFS_GLACIER_EXPIRY_RUN_TIME,
79+
config.NSFS_GLACIER_EXPIRY_RUN_DELAY_LIMIT_MINS,
80+
GlacierBackend.EXPIRY_TIMESTAMP_FILE,
81+
)
82+
) {
83+
await backend.expiry(fs_context);
84+
await record_current_time(fs_context, GlacierBackend.EXPIRY_TIMESTAMP_FILE);
85+
}
86+
});
87+
}
7388

89+
/**
90+
* is_desired_time returns true if the given time matches with
91+
* the desired time or if
92+
* @param {nb.NativeFSContext} fs_context
93+
* @param {Date} current
94+
* @param {string} desire time in format 'hh:mm'
95+
* @param {number} delay_limit_mins
96+
* @param {string} timestamp_file
97+
* @returns {Promise<boolean>}
98+
*/
99+
async function is_desired_time(fs_context, current, desire, delay_limit_mins, timestamp_file) {
100+
const [desired_hour, desired_min] = desire.split(':').map(Number);
101+
if (
102+
isNaN(desired_hour) ||
103+
isNaN(desired_min) ||
104+
(desired_hour < 0 || desired_hour >= 24) ||
105+
(desired_min < 0 || desired_min >= 60)
106+
) {
107+
throw new Error('invalid desired_time - must be hh:mm');
108+
}
74109

75-
await getGlacierBackend().expiry(fs_context);
76-
await record_current_time(fs_context, GlacierBackend.EXPIRY_TIMESTAMP_FILE);
77-
});
110+
const min_time = get_tz_date(desired_hour, desired_min, 0, config.NSFS_GLACIER_EXPIRY_TZ);
111+
const max_time = get_tz_date(desired_hour, desired_min + delay_limit_mins, 0, config.NSFS_GLACIER_EXPIRY_TZ);
112+
113+
if (current >= min_time && current <= max_time) {
114+
try {
115+
const { data } = await nb_native().fs.readFile(fs_context, path.join(config.NSFS_GLACIER_LOGS_DIR, timestamp_file));
116+
const lastrun = new Date(data.toString());
117+
118+
// Last run should NOT be in this window
119+
if (lastrun >= min_time && lastrun <= max_time) return false;
120+
} catch (error) {
121+
if (error.code === 'ENOENT') return true;
122+
console.error('failed to read last run timestamp:', error, 'timestamp_file:', timestamp_file);
123+
124+
throw error;
125+
}
126+
127+
return true;
128+
}
129+
130+
return false;
78131
}
79132

80133
/**
@@ -134,6 +187,31 @@ async function run_glacier_operation(fs_context, log_namespace, cb) {
134187
}
135188
}
136189

190+
/**
191+
* @param {number} hours
192+
* @param {number} mins
193+
* @param {number} secs
194+
* @param {'UTC' | 'LOCAL'} tz
195+
* @returns {Date}
196+
*/
197+
function get_tz_date(hours, mins, secs, tz) {
198+
const date = new Date();
199+
200+
if (tz === 'UTC') {
201+
date.setUTCHours(hours);
202+
date.setUTCMinutes(hours);
203+
date.setUTCSeconds(secs);
204+
date.setUTCMilliseconds(0);
205+
} else {
206+
date.setHours(hours);
207+
date.setMinutes(mins);
208+
date.setSeconds(secs);
209+
date.setMilliseconds(0);
210+
}
211+
212+
return date;
213+
}
214+
137215
/**
138216
* lock_and_run acquires a flock and calls the given callback after
139217
* acquiring the lock

src/sdk/nsfs_glacier_backend/tapecloud.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ class TapeCloudGlacierBackend extends GlacierBackend {
278278

279279
async low_free_space() {
280280
const result = await exec(get_bin_path(LOW_FREE_SPACE_SCRIPT), { return_stdout: true });
281-
return result.toLowerCase() === 'true';
281+
return result.toLowerCase().trim() === 'true';
282282
}
283283

284284
// ============= PRIVATE FUNCTIONS =============

0 commit comments

Comments
 (0)