Skip to content

Commit 406f6ba

Browse files
author
Maciej Wilczyński
authored
feat: Support requirements layer caching (#644)
1 parent c480877 commit 406f6ba

File tree

2 files changed

+63
-5
lines changed

2 files changed

+63
-5
lines changed

lib/layer.js

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const fse = require('fs-extra');
33
const path = require('path');
44
const JSZip = require('jszip');
55
const { writeZip, addTree } = require('./zipTree');
6+
const { sha256Path, getRequirementsLayerPath } = require('./shared');
67

78
BbPromise.promisifyAll(fse);
89

@@ -11,13 +12,49 @@ BbPromise.promisifyAll(fse);
1112
* @return {Promise} the JSZip object constructed.
1213
*/
1314
function zipRequirements() {
14-
const rootZip = new JSZip();
1515
const src = path.join('.serverless', 'requirements');
16-
const runtimepath = 'python';
17-
18-
return addTree(rootZip.folder(runtimepath), src).then(() =>
19-
writeZip(rootZip, path.join('.serverless', 'pythonRequirements.zip'))
16+
const reqChecksum = sha256Path(path.join('.serverless', 'requirements.txt'));
17+
const targetZipPath = path.join('.serverless', 'pythonRequirements.zip');
18+
const zipCachePath = getRequirementsLayerPath(
19+
reqChecksum,
20+
targetZipPath,
21+
this.options,
22+
this.serverless
2023
);
24+
25+
const promises = [];
26+
if (fse.existsSync(zipCachePath)) {
27+
let layerProgress;
28+
if (this.progress && this.log) {
29+
layerProgress = this.progress.get('python-layer-requirements');
30+
layerProgress.update(
31+
'Using cached Python Requirements Lambda Layer file'
32+
);
33+
this.log.info('Found cached Python Requirements Lambda Layer file');
34+
} else {
35+
this.serverless.cli.log(
36+
'Found cached Python Requirements Lambda Layer file'
37+
);
38+
}
39+
} else {
40+
const rootZip = new JSZip();
41+
const runtimepath = 'python';
42+
43+
promises.push(
44+
addTree(rootZip.folder(runtimepath), src).then(() =>
45+
writeZip(rootZip, zipCachePath)
46+
)
47+
);
48+
}
49+
return BbPromise.all(promises).then(() => {
50+
if (zipCachePath !== targetZipPath) {
51+
if (process.platform === 'win32') {
52+
fse.copySync(zipCachePath, targetZipPath);
53+
} else {
54+
fse.symlink(zipCachePath, targetZipPath, 'file');
55+
}
56+
}
57+
});
2158
}
2259

2360
/**

lib/shared.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,26 @@ function getRequirementsWorkingPath(
8686
return path.join(requirementsTxtDirectory, 'requirements');
8787
}
8888

89+
/**
90+
* Path of a cached requirements layer archive file
91+
* @param {string} subfolder
92+
* @param {string} fallback
93+
* @param {Object} options
94+
* @param {Object} serverless
95+
* @return {string}
96+
*/
97+
function getRequirementsLayerPath(hash, fallback, options, serverless) {
98+
// If we want to use the static cache
99+
if (hash && options && options.useStaticCache) {
100+
const architecture = serverless.service.provider.architecture || 'x86_64';
101+
hash = `${hash}_${architecture}_slspyc.zip`;
102+
return path.join(getUserCachePath(options), hash);
103+
}
104+
105+
// If we don't want to use the static cache, then fallback to requirements file in .serverless directory
106+
return fallback;
107+
}
108+
89109
/**
90110
* The static cache path that will be used for this system + options, used if static cache is enabled
91111
* @param {Object} options
@@ -117,6 +137,7 @@ function sha256Path(fullpath) {
117137
module.exports = {
118138
checkForAndDeleteMaxCacheVersions,
119139
getRequirementsWorkingPath,
140+
getRequirementsLayerPath,
120141
getUserCachePath,
121142
sha256Path,
122143
};

0 commit comments

Comments
 (0)