@@ -31,6 +31,9 @@ import { BulkInsertOnProgressEventArgs } from "./Session/SessionEvents";
3131import * as semaphore from "semaphore" ;
3232import { acquireSemaphore } from "../Utility/SemaphoreUtil" ;
3333import { Buffer } from "node:buffer" ;
34+ import { createGzip , Gzip } from "node:zlib" ;
35+ import { pipeline } from "readable-stream" ;
36+ import { promisify } from "node:util" ;
3437
3538class BulkInsertStream {
3639
@@ -105,7 +108,7 @@ export class BulkInsertOperation {
105108 private _bulkInsertExecuteTask : Promise < any > ;
106109 private _bulkInsertExecuteTaskErrored = false ;
107110
108- private _stream : RequestBodyStream ;
111+ private _stream : stream . Readable & { flush : ( callback ?: ( ) => void ) => void ; } ;
109112
110113 private _first : boolean = true ;
111114 private _inProgressCommand : CommandType ;
@@ -129,8 +132,8 @@ export class BulkInsertOperation {
129132 private readonly _streamLock : semaphore . Semaphore ;
130133 private _heartbeatCheckInterval = 40_000 ;
131134
132- //TODO: private GZipStream _compressedStream;
133- private _requestBodyStream : RequestBodyStream ; //TODO: raw reableable or wrapped with compressed
135+ private _compressedStream : Gzip ;
136+ private _requestBodyStream : RequestBodyStream ;
134137 private _requestBodyStreamFinished : boolean = false ;
135138 private _currentWriter : BulkInsertStream ;
136139 private _backgroundWriter : BulkInsertStream ;
@@ -460,6 +463,12 @@ export class BulkInsertOperation {
460463 this . _isInitialWrite = false ;
461464
462465 await this . _requestBodyStream . flush ( ) ;
466+
467+ if ( this . _compressedStream ) {
468+ const flush = promisify ( this . _compressedStream . flush ) ;
469+ await flush . call ( this . _compressedStream ) ;
470+ }
471+
463472 this . _lastWriteToStream = new Date ( ) ;
464473 }
465474 } finally {
@@ -535,29 +544,23 @@ export class BulkInsertOperation {
535544 }
536545
537546 private async _ensureStream ( ) {
538- //TODO: sync with c#
539- //TODO if (CompressionLevel != CompressionLevel.NoCompression)
540- // _streamExposerContent.Headers.ContentEncoding.Add("gzip");
541-
542547 try {
543548 this . _requestBodyStream = new RequestBodyStream ( ) ;
544- this . _stream = this . _requestBodyStream ; //TODO:
549+ this . _stream = this . _requestBodyStream ;
550+
551+ if ( this . useCompression ) {
552+ this . _compressedStream = createGzip ( ) ;
553+ pipeline ( this . _requestBodyStream , this . _compressedStream ) ;
554+ }
555+
545556 const bulkCommand =
546- new BulkInsertCommand ( this . _operationId , this . _requestBodyStream , this . _nodeTag , this . _options . skipOverwriteIfUnchanged ) ;
557+ new BulkInsertCommand ( this . _operationId , this . _compressedStream ?? this . _requestBodyStream , this . _nodeTag , this . _options . skipOverwriteIfUnchanged ) ;
547558 bulkCommand . useCompression = this . _useCompression ;
548559
549560 this . _bulkInsertExecuteTask = this . _requestExecutor . execute ( bulkCommand ) ;
550561
551562 this . _currentWriter . push ( "[" ) ;
552563
553- /* TODO
554- if (CompressionLevel != CompressionLevel.NoCompression)
555- {
556- _compressedStream = new GZipStream(_stream, CompressionLevel, leaveOpen: true);
557- _requestBodyStream = _compressedStream;
558- }
559- */
560-
561564 this . _bulkInsertExecuteTask
562565 . catch ( ( ) => this . _bulkInsertExecuteTaskErrored = true ) ;
563566
@@ -598,8 +601,7 @@ export class BulkInsertOperation {
598601 try {
599602 this . _currentWriter . push ( "]" ) ;
600603 await this . _asyncWrite ;
601- this . _requestBodyStream . write ( this . _currentWriter . toBuffer ( ) ) ;
602- //TODO: _compressedStream?.Dispose();
604+ this . _requestBodyStream . push ( this . _currentWriter . toBuffer ( ) ) ;
603605 await this . _stream . flush ( ) ;
604606 } finally {
605607 context . dispose ( ) ;
@@ -1017,7 +1019,7 @@ export class BulkInsertOperation {
10171019
10181020 await this . _operation . flushIfNeeded ( ) ;
10191021
1020- this . _operation . _currentWriter . push ( bytes ) ; //TODO: do we want to stream here?
1022+ this . _operation . _currentWriter . push ( bytes ) ;
10211023
10221024 await this . _operation . flushIfNeeded ( ) ;
10231025 } catch ( e ) {
@@ -1078,8 +1080,12 @@ export class BulkInsertCommand extends RavenCommand<void> {
10781080 + "/bulk_insert?id=" + this . _id
10791081 + "&skipOverwriteIfUnchanged=" + ( this . _skipOverwriteIfUnchanged ? "true" : "false" ) ;
10801082
1081- const headers = this . _headers ( ) . typeAppJson ( ) . build ( ) ;
1082- // TODO: useCompression ? new GzipCompressingEntity(_stream) : _stream);
1083+ const headersBuilder = this . _headers ( ) . typeAppJson ( ) ;
1084+ if ( this . useCompression ) {
1085+ headersBuilder . with ( "Content-Encoding" , "gzip" ) ;
1086+ }
1087+
1088+ const headers = headersBuilder . build ( ) ;
10831089 return {
10841090 method : "POST" ,
10851091 uri,
0 commit comments