@@ -23,6 +23,8 @@ async function parseArguments() {
23
23
libVersion : { short : 'l' , type : 'string' , default : pkg [ 'mongodb:libmongocrypt' ] } ,
24
24
clean : { short : 'c' , type : 'boolean' , default : false } ,
25
25
build : { short : 'b' , type : 'boolean' , default : false } ,
26
+ crypto : { type : 'boolean' , default : false } , // Use Node.js builtin crypto
27
+ fastDownload : { type : 'boolean' , default : false } , // Potentially incorrect download, only for the brave and impatient
26
28
help : { short : 'h' , type : 'boolean' , default : false }
27
29
} ;
28
30
@@ -39,7 +41,12 @@ async function parseArguments() {
39
41
}
40
42
41
43
return {
42
- libmongocrypt : { url : args . values . gitURL , ref : args . values . libVersion } ,
44
+ libmongocrypt : {
45
+ url : args . values . gitURL ,
46
+ ref : args . values . libVersion ,
47
+ crypto : args . values . crypto
48
+ } ,
49
+ fastDownload : args . values . fastDownload ,
43
50
clean : args . values . clean ,
44
51
build : args . values . build ,
45
52
pkg
@@ -77,7 +84,7 @@ export async function cloneLibMongoCrypt(libmongocryptRoot, { url, ref }) {
77
84
}
78
85
}
79
86
80
- export async function buildLibMongoCrypt ( libmongocryptRoot , nodeDepsRoot ) {
87
+ export async function buildLibMongoCrypt ( libmongocryptRoot , nodeDepsRoot , options ) {
81
88
console . error ( 'building libmongocrypt...' ) ;
82
89
83
90
const nodeBuildRoot = resolveRoot ( nodeDepsRoot , 'tmp' , 'libmongocrypt-build' ) ;
@@ -88,7 +95,6 @@ export async function buildLibMongoCrypt(libmongocryptRoot, nodeDepsRoot) {
88
95
const CMAKE_FLAGS = toFlags ( {
89
96
/**
90
97
* We provide crypto hooks from Node.js binding to openssl (so disable system crypto)
91
- * TODO: NODE-5455
92
98
*
93
99
* One thing that is not obvious from the build instructions for libmongocrypt
94
100
* and the Node.js bindings is that the Node.js driver uses libmongocrypt in
@@ -101,7 +107,7 @@ export async function buildLibMongoCrypt(libmongocryptRoot, nodeDepsRoot) {
101
107
* have a copy of OpenSSL available directly, but for now it seems to make sense
102
108
* to stick with what the Node.js addon does here.
103
109
*/
104
- DDISABLE_NATIVE_CRYPTO : '1' ,
110
+ DDISABLE_NATIVE_CRYPTO : options . crypto ? '0' : '1' ,
105
111
/** A consistent name for the output "library" directory */
106
112
DCMAKE_INSTALL_LIBDIR : 'lib' ,
107
113
/** No warnings allowed */
@@ -128,15 +134,26 @@ export async function buildLibMongoCrypt(libmongocryptRoot, nodeDepsRoot) {
128
134
129
135
await run (
130
136
'cmake' ,
131
- [ ...CMAKE_FLAGS , ...WINDOWS_CMAKE_FLAGS , ...MACOS_CMAKE_FLAGS , libmongocryptRoot ] ,
137
+ [
138
+ '--parallel' ,
139
+ '4' ,
140
+ ...CMAKE_FLAGS ,
141
+ ...WINDOWS_CMAKE_FLAGS ,
142
+ ...MACOS_CMAKE_FLAGS ,
143
+ libmongocryptRoot
144
+ ] ,
132
145
{ cwd : nodeBuildRoot }
133
146
) ;
134
- await run ( 'cmake' , [ '--build' , '.' , '--target' , 'install' , '--config' , 'RelWithDebInfo' ] , {
135
- cwd : nodeBuildRoot
136
- } ) ;
147
+ await run (
148
+ 'cmake' ,
149
+ [ '--parallel' , '4' , '--build' , '.' , '--target' , 'install' , '--config' , 'RelWithDebInfo' ] ,
150
+ {
151
+ cwd : nodeBuildRoot
152
+ }
153
+ ) ;
137
154
}
138
155
139
- export async function downloadLibMongoCrypt ( nodeDepsRoot , { ref } ) {
156
+ export async function downloadLibMongoCrypt ( nodeDepsRoot , { ref, crypto } , fastDownload ) {
140
157
const downloadURL =
141
158
ref === 'latest'
142
159
? 'https://mciuploads.s3.amazonaws.com/libmongocrypt/all/master/latest/libmongocrypt-all.tar.gz'
@@ -164,28 +181,62 @@ export async function downloadLibMongoCrypt(nodeDepsRoot, { ref }) {
164
181
165
182
console . error ( `Platform: ${ detectedPlatform } Prebuild: ${ prebuild } ` ) ;
166
183
167
- const unzipArgs = [ '-xzv' , '-C' , `_libmongocrypt-${ ref } ` , `${ prebuild } /nocrypto` ] ;
184
+ const downloadDestination = crypto ? `${ prebuild } ` : `${ prebuild } /nocrypto` ;
185
+ const unzipArgs = [ '-xzv' , '-C' , `_libmongocrypt-${ ref } ` , downloadDestination ] ;
168
186
console . error ( `+ tar ${ unzipArgs . join ( ' ' ) } ` ) ;
169
187
const unzip = child_process . spawn ( 'tar' , unzipArgs , {
170
- stdio : [ 'pipe' , 'inherit' ] ,
188
+ stdio : [ 'pipe' , 'inherit' , 'pipe' ] ,
171
189
cwd : resolveRoot ( '.' )
172
190
} ) ;
173
191
174
192
const [ response ] = await events . once ( https . get ( downloadURL ) , 'response' ) ;
175
193
176
194
const start = performance . now ( ) ;
177
- await stream . pipeline ( response , unzip . stdin ) ;
195
+
196
+ let signal ;
197
+ if ( fastDownload ) {
198
+ /**
199
+ * Tar will print out each file it finds inside MEMBER (ex. macos/nocrypto)
200
+ * For each file it prints, we give it a deadline of 10seconds to print the next one.
201
+ * If nothing prints after 10 seconds we exit early.
202
+ * This depends on the tar file being in order and un-tar-able in under 10sec.
203
+ *
204
+ * download time went from 230s to 80s
205
+ */
206
+ const controller = new AbortController ( ) ;
207
+ signal = controller . signal ;
208
+ let isFirstStdoutDataEv = true ;
209
+ let timeout ;
210
+ unzip . stderr . on ( 'data' , chunk => {
211
+ process . stderr . write ( chunk , ( ) => {
212
+ if ( isFirstStdoutDataEv ) {
213
+ isFirstStdoutDataEv = false ;
214
+ timeout = setTimeout ( ( ) => controller . abort ( ) , 10_000 ) ;
215
+ }
216
+ timeout ?. refresh ( ) ;
217
+ } ) ;
218
+ } ) ;
219
+ }
220
+
221
+ try {
222
+ await stream . pipeline ( response , unzip . stdin , { signal } ) ;
223
+ } catch {
224
+ await fs . access ( path . join ( `_libmongocrypt-${ ref } ` , downloadDestination ) ) ;
225
+ }
178
226
const end = performance . now ( ) ;
179
227
180
228
console . error ( `downloaded libmongocrypt in ${ ( end - start ) / 1000 } secs...` ) ;
181
229
182
230
await fs . rm ( nodeDepsRoot , { recursive : true , force : true } ) ;
183
- await fs . cp ( resolveRoot ( destination , prebuild , 'nocrypto' ) , nodeDepsRoot , { recursive : true } ) ;
184
- const currentPath = path . join ( nodeDepsRoot , 'lib64' ) ;
231
+ const source = crypto
232
+ ? resolveRoot ( destination , prebuild )
233
+ : resolveRoot ( destination , prebuild , 'nocrypto' ) ;
234
+ await fs . cp ( source , nodeDepsRoot , { recursive : true } ) ;
235
+ const potentialLib64Path = path . join ( nodeDepsRoot , 'lib64' ) ;
185
236
try {
186
- await fs . rename ( currentPath , path . join ( nodeDepsRoot , 'lib' ) ) ;
237
+ await fs . rename ( potentialLib64Path , path . join ( nodeDepsRoot , 'lib' ) ) ;
187
238
} catch ( error ) {
188
- console . error ( `error renaming ${ currentPath } : ${ error . message } ` ) ;
239
+ await fs . access ( path . join ( nodeDepsRoot , 'lib' ) ) ; // Ensure there is a "lib" directory
189
240
}
190
241
}
191
242
@@ -214,11 +265,13 @@ async function main() {
214
265
const isBuilt = libmongocryptBuiltVersion . trim ( ) === libmongocrypt . ref ;
215
266
216
267
if ( clean || ! isBuilt ) {
217
- await buildLibMongoCrypt ( libmongocryptCloneDir , nodeDepsDir ) ;
268
+ await buildLibMongoCrypt ( libmongocryptCloneDir , nodeDepsDir , {
269
+ crypto : libmongocrypt . crypto
270
+ } ) ;
218
271
}
219
272
} else {
220
273
// Download
221
- await downloadLibMongoCrypt ( nodeDepsDir , libmongocrypt ) ;
274
+ await downloadLibMongoCrypt ( nodeDepsDir , libmongocrypt , fastDownload ) ;
222
275
}
223
276
224
277
await fs . rm ( resolveRoot ( 'build' ) , { force : true , recursive : true } ) ;
0 commit comments