Skip to content

Commit 88d46bf

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

File tree

5 files changed

+455
-3
lines changed

5 files changed

+455
-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: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,44 @@ 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 - The function parameters
105+
* @param params.transitions - Array of lifecycle rule transitions
106+
* @param params.lastModified - The object's last modified
107+
* date
108+
* @return The most applicable transition rule
109+
*/
110+
getApplicableNoncurrentVersionTransition(params: {
111+
store: any;
112+
currentDate: Date;
113+
noncurrentTransitions: any[];
114+
lastModified: string;
115+
}) {
116+
const { noncurrentTransitions, store, lastModified, currentDate } = params;
117+
const ncvt = noncurrentTransitions.reduce((result, ncvt) => {
118+
const isApplicable = // Is the transition time in the past?
119+
this._datetime.getTimestamp(currentDate) >=
120+
this._datetime.getTransitionTimestamp(ncvt, lastModified)!;
121+
if (!isApplicable) {
122+
return result;
123+
}
124+
return this.compareTransitions({
125+
transition1: ncvt,
126+
transition2: result,
127+
lastModified,
128+
});
129+
}, undefined);
130+
131+
132+
return this.compareTransitions({
133+
transition1: ncvt,
134+
transition2: store.NoncurrentVersionTransition,
135+
lastModified,
136+
});
137+
}
138+
101139
// TODO
102140
/**
103141
* Filter out all rules based on `Status` and `Filter` (Prefix and Tags)
@@ -239,14 +277,31 @@ export default class LifecycleUtils {
239277
currentDate,
240278
});
241279
}
242-
// TODO: Add support for NoncurrentVersionTransitions.
280+
281+
const ncvt = 'NoncurrentVersionTransitions';
282+
const hasNoncurrentTransitions = Array.isArray(rule[ncvt]) && rule[ncvt].length > 0;
283+
if (hasNoncurrentTransitions && this._supportedRules.includes('noncurrentVersionTransitions')) {
284+
store.NoncurrentVersionTransition = this.getApplicableNoncurrentVersionTransition({
285+
noncurrentTransitions: rule.NoncurrentVersionTransitions,
286+
lastModified: metadata.LastModified,
287+
store,
288+
currentDate,
289+
});
290+
}
291+
243292
return store;
244293
}, {});
245294
// Do not transition to a location where the object is already stored.
246295
if (applicableRules.Transition
247296
&& applicableRules.Transition.StorageClass === metadata.StorageClass) {
248297
applicableRules.Transition = undefined;
249298
}
299+
300+
if (applicableRules.NoncurrentVersionTransition
301+
&& applicableRules.NoncurrentVersionTransition.StorageClass === metadata.StorageClass) {
302+
applicableRules.NoncurrentVersionTransition = undefined;
303+
}
304+
250305
return applicableRules;
251306
/* eslint-enable no-param-reassign */
252307
}

0 commit comments

Comments
 (0)