Skip to content

Commit 7c61b4d

Browse files
ARSN-218: support lifecycle noncurrent version transition
1 parent 15f0753 commit 7c61b4d

File tree

5 files changed

+457
-3
lines changed

5 files changed

+457
-3
lines changed

lib/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ export const supportedLifecycleRules = [
150150
'noncurrentVersionExpiration',
151151
'abortIncompleteMultipartUpload',
152152
'transitions',
153-
'noncurrentVersionTransition',
153+
'noncurrentVersionTransitions',
154154
];
155155
// Maximum number of buckets to cache (bucket metadata)
156156
export const maxCachedBuckets = process.env.METADATA_MAX_CACHED_BUCKETS ?

lib/models/LifecycleRule.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ class LifecycleRule {
3131
if (this.transitions) {
3232
rule.Transitions = this.transitions;
3333
}
34+
if (this.ncvTransitions) {
35+
rule.NoncurrentVersionTransitions = this.ncvTransitions;
36+
}
3437

3538

3639
const filter = {};
@@ -133,6 +136,11 @@ class LifecycleRule {
133136
this.transitions = transitions;
134137
return this;
135138
}
139+
140+
addNCVTransitions(nvcTransitions) {
141+
this.ncvTransitions = nvcTransitions;
142+
return this;
143+
}
136144
}
137145

138146
module.exports = LifecycleRule;

lib/s3middleware/lifecycleHelpers/LifecycleDateTime.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export default class LifecycleDateTime {
4444
* @return - The normalized transition timestamp
4545
*/
4646
getTransitionTimestamp(
47-
transition: { Date?: string; Days?: number },
47+
transition: { Date?: string; Days?: number, NoncurrentDays?: number },
4848
lastModified: string,
4949
) {
5050
if (transition.Date !== undefined) {
@@ -55,5 +55,10 @@ export default class LifecycleDateTime {
5555
const timeTravel = this._transitionOneDayEarlier ? -oneDay : 0;
5656
return lastModifiedTime + (transition.Days * oneDay) + timeTravel;
5757
}
58+
if (transition.NoncurrentDays !== undefined) {
59+
const lastModifiedTime = this.getTimestamp(lastModified);
60+
const timeTravel = this._transitionOneDayEarlier ? -oneDay : 0;
61+
return lastModifiedTime + (transition.NoncurrentDays * oneDay) + timeTravel;
62+
}
5863
}
5964
}

lib/s3middleware/lifecycleHelpers/LifecycleUtils.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,46 @@ export default class LifecycleUtils {
9898
});
9999
}
100100

101+
/**
102+
* Find the most relevant trantition rule for the given transitions array
103+
* and any previously stored transition from another rule.
104+
* @param params.noncurrentTransitions - Array of lifecycle rule noncurrent
105+
* transitions
106+
* @param params.lastModified - The object's last modified
107+
* @param params.currentDate - current date
108+
* @param params.store - object containing applicable rules
109+
* date
110+
* @return The most applicable transition rule
111+
*/
112+
getApplicableNoncurrentVersionTransition(params: {
113+
store: any;
114+
currentDate: Date;
115+
noncurrentTransitions: any[];
116+
lastModified: string;
117+
}) {
118+
const { noncurrentTransitions, store, lastModified, currentDate } = params;
119+
const ncvt = noncurrentTransitions.reduce((result, ncvt) => {
120+
const isApplicable = // Is the transition time in the past?
121+
this._datetime.getTimestamp(currentDate) >=
122+
this._datetime.getTransitionTimestamp(ncvt, lastModified)!;
123+
if (!isApplicable) {
124+
return result;
125+
}
126+
return this.compareTransitions({
127+
transition1: ncvt,
128+
transition2: result,
129+
lastModified,
130+
});
131+
}, undefined);
132+
133+
134+
return this.compareTransitions({
135+
transition1: ncvt,
136+
transition2: store.NoncurrentVersionTransition,
137+
lastModified,
138+
});
139+
}
140+
101141
// TODO
102142
/**
103143
* Filter out all rules based on `Status` and `Filter` (Prefix and Tags)
@@ -239,14 +279,31 @@ export default class LifecycleUtils {
239279
currentDate,
240280
});
241281
}
242-
// TODO: Add support for NoncurrentVersionTransitions.
282+
283+
const ncvt = 'NoncurrentVersionTransitions';
284+
const hasNoncurrentTransitions = Array.isArray(rule[ncvt]) && rule[ncvt].length > 0;
285+
if (hasNoncurrentTransitions && this._supportedRules.includes('noncurrentVersionTransitions')) {
286+
store.NoncurrentVersionTransition = this.getApplicableNoncurrentVersionTransition({
287+
noncurrentTransitions: rule.NoncurrentVersionTransitions,
288+
lastModified: metadata.LastModified,
289+
store,
290+
currentDate,
291+
});
292+
}
293+
243294
return store;
244295
}, {});
245296
// Do not transition to a location where the object is already stored.
246297
if (applicableRules.Transition
247298
&& applicableRules.Transition.StorageClass === metadata.StorageClass) {
248299
applicableRules.Transition = undefined;
249300
}
301+
302+
if (applicableRules.NoncurrentVersionTransition
303+
&& applicableRules.NoncurrentVersionTransition.StorageClass === metadata.StorageClass) {
304+
applicableRules.NoncurrentVersionTransition = undefined;
305+
}
306+
250307
return applicableRules;
251308
/* eslint-enable no-param-reassign */
252309
}

0 commit comments

Comments
 (0)