1
+ import { ReadStream , createReadStream } from "fs" ;
2
+ import { Readable } from "stream" ;
3
+ import ILogger from "../ILogger" ;
4
+
5
+
6
+ export default class FileLazyReadStream extends Readable {
7
+ private extentStream : ReadStream | undefined ;
8
+ constructor (
9
+ private readonly extentPath : string ,
10
+ private readonly start : number ,
11
+ private readonly end : number ,
12
+ private readonly logger : ILogger ,
13
+ private readonly persistencyId : string ,
14
+ private readonly extentId : string ,
15
+ private readonly contextId ?: string ) {
16
+ super ( ) ;
17
+ }
18
+
19
+ public _read ( ) : void {
20
+ if ( this . extentStream === undefined ) {
21
+ this . extentStream = createReadStream ( this . extentPath , {
22
+ start : this . start ,
23
+ end : this . end
24
+ } ) . on ( "close" , ( ) => {
25
+ this . logger . verbose (
26
+ `FSExtentStore:readExtent() Read stream closed. LocationId:${ this . persistencyId } extentId:${ this . extentId
27
+ } path:${ this . extentPath } offset:${ this . start } end:${ this . end } `,
28
+ this . contextId
29
+ ) ;
30
+ } ) ;
31
+ this . setSourceEventHandlers ( ) ;
32
+ }
33
+ this . extentStream ?. resume ( ) ;
34
+ }
35
+
36
+ private setSourceEventHandlers ( ) {
37
+ this . extentStream ?. on ( "data" , this . sourceDataHandler ) ;
38
+ this . extentStream ?. on ( "end" , this . sourceErrorOrEndHandler ) ;
39
+ this . extentStream ?. on ( "error" , this . sourceErrorOrEndHandler ) ;
40
+ }
41
+
42
+ private removeSourceEventHandlers ( ) {
43
+ this . extentStream ?. removeListener ( "data" , this . sourceDataHandler ) ;
44
+ this . extentStream ?. removeListener ( "end" , this . sourceErrorOrEndHandler ) ;
45
+ this . extentStream ?. removeListener ( "error" , this . sourceErrorOrEndHandler ) ;
46
+ }
47
+
48
+ private sourceDataHandler = ( data : Buffer ) => {
49
+ if ( ! this . push ( data ) ) {
50
+ this . extentStream ?. pause ( ) ;
51
+ }
52
+ }
53
+
54
+ private sourceErrorOrEndHandler = ( err ?: Error ) => {
55
+ if ( err && err . name === "AbortError" ) {
56
+ this . destroy ( err ) ;
57
+ return ;
58
+ }
59
+
60
+ this . removeSourceEventHandlers ( ) ;
61
+ this . push ( null ) ;
62
+ this . destroy ( err ) ;
63
+ }
64
+
65
+ _destroy ( error : Error | null , callback : ( error ?: Error ) => void ) : void {
66
+ // remove listener from source and release source
67
+ //this.removeSourceEventHandlers();
68
+ ( this . extentStream as Readable ) . destroy ( ) ;
69
+
70
+ callback ( error === null ? undefined : error ) ;
71
+ }
72
+ }
0 commit comments