55use ReactphpX \Concurrent \Concurrent ;
66use ReactphpX \Limiter \TokenBucket ;
77use React \Filesystem \Factory ;
8+ use function React \Async \async ;
9+ use function React \Async \await ;
810
911final class Bandwidth
1012{
@@ -35,33 +37,37 @@ public function file(string $path, $p = 0, $length = -1, $readKB = 0)
3537
3638 $ readKB = $ readKB > 0 ? min ($ readKB , $ this ->KB ) : $ this ->KB ;
3739
38- $ this ->filesystem ->detect ($ path )->then (function ($ node ) use ($ path ) {
39- if ($ node instanceof \React \Filesystem \Node \FileInterface) {
40- return $ node ->stat ();
41- } else {
42- throw new \RuntimeException ($ path . ' is not a file ' );
43- }
44- })->then (function ($ stat ) use ($ stream , $ p , $ length , $ readKB ) {
45- if ($ this ->queue ) {
46- return $ this ->concurrent ->concurrent (function () use ($ stream , $ stat , $ p , $ length , $ readKB ) {
40+ async (function ($ path , $ stream , $ p , $ length , $ readKB ) {
41+ try {
42+ $ node = await ($ this ->filesystem ->detect ($ path ));
43+ if (!($ node instanceof \React \Filesystem \Node \FileInterface)) {
44+ throw new \RuntimeException ($ path . ' is not a file ' );
45+ }
46+ $ stat = await ($ node ->stat ());
47+
48+ if ($ this ->queue ) {
49+ await ($ this ->concurrent ->concurrent (
50+ async (function () use ($ stream , $ stat , $ p , $ length , $ readKB ) {
51+ $ file = $ this ->filesystem ->file ($ stat ->path ());
52+ $ size = $ stat ->size ();
53+ if ($ length > 0 ) {
54+ $ size = min ($ size , $ p + $ length );
55+ }
56+ return await ($ this ->fileStream ($ file , $ stream , $ p , $ size , $ readKB ));
57+ })
58+ ));
59+ } else {
4760 $ file = $ this ->filesystem ->file ($ stat ->path ());
4861 $ size = $ stat ->size ();
4962 if ($ length > 0 ) {
5063 $ size = min ($ size , $ p + $ length );
5164 }
52- return $ this ->fileStream ($ file , $ stream , $ p , $ size , $ readKB );
53- });
54- } else {
55- $ file = $ this ->filesystem ->file ($ stat ->path ());
56- $ size = $ stat ->size ();
57- if ($ length > 0 ) {
58- $ size = min ($ size , $ p + $ length );
65+ await ($ this ->fileStream ($ file , $ stream , $ p , $ size , $ readKB ));
5966 }
60- return $ this ->fileStream ($ file , $ stream , $ p , $ size , $ readKB );
67+ } catch (\Throwable $ e ) {
68+ $ stream ->emit ('error ' , [$ e ]);
6169 }
62- }, function ($ e ) use ($ stream ) {
63- $ stream ->emit ('error ' , [$ e ]);
64- });
70+ })($ path , $ stream , $ p , $ length , $ readKB );
6571 return $ stream ;
6672 }
6773
@@ -72,11 +78,12 @@ public function stream($stream)
7278 $ concurrent = $ this ->queue ? $ this ->concurrent : new Concurrent (1 );
7379
7480 $ stream ->on ('data ' , function ($ data ) use ($ _stream , $ concurrent ) {
75- $ concurrent ->concurrent (function () use ($ _stream , $ data ){
76- return $ this ->bucket ->removeTokens (1024 * strlen ($ data ))->then (function () use ($ _stream , $ data ) {
81+ $ concurrent ->concurrent (
82+ async (function () use ($ _stream , $ data ) {
83+ await ($ this ->bucket ->removeTokens (1024 * strlen ($ data )));
7784 $ _stream ->write ($ data );
78- });
79- } );
85+ })
86+ );
8087 });
8188
8289 return $ _stream ;
@@ -85,32 +92,31 @@ public function stream($stream)
8592 protected function fileStream ($ file , $ stream , $ p , $ size , $ readKB )
8693 {
8794
88- if (!$ stream ->isWritable ()) {
89- return \React \Promise \resolve (null );
90- }
91-
92- $ currentSize = $ size - $ p ;
93-
94- if ($ currentSize /1024 < $ readKB ) {
95- return $ this ->bucket ->removeTokens (1024 * 1024 * ceil ($ currentSize /1024 ))->then (function () use ($ file , $ stream , $ p , $ currentSize ) {
96- return $ file ->getContents ($ p , $ currentSize )->then (function ($ contents ) use ($ stream ) {
97- $ stream ->end ($ contents );
98- return null ;
99- });
100- });
101- } else {
102- return $ this ->bucket ->removeTokens (1024 * 1024 * $ readKB )->then (function () use ($ file , $ stream , $ p , $ size , $ readKB ) {
103- return $ file ->getContents ($ p , 1024 * 1024 * $ readKB )->then (function ($ contents ) use ($ stream , $ file , $ p , $ size , $ readKB ) {
104- $ p += strlen ($ contents );
105- if ($ p >= $ size ) {
106- $ stream ->end ($ contents );
107- return null ;
108- } else {
109- $ stream ->write ($ contents );
110- return $ this ->fileStream ($ file , $ stream , $ p , $ size , $ readKB );
111- }
112- });
113- });
114- }
95+ return async (function () use ($ file , $ stream , $ p , $ size , $ readKB ) {
96+ while (true ) {
97+ if (!$ stream ->isWritable ()) {
98+ return true ;
99+ }
100+ $ remaining = $ size - $ p ;
101+ if ($ remaining <= 0 ) {
102+ return true ;
103+ }
104+ if ($ remaining /1024 < $ readKB ) {
105+ await ($ this ->bucket ->removeTokens (1024 * 1024 * ceil ($ remaining /1024 )));
106+ $ contents = await ($ file ->getContents ($ p , $ remaining ));
107+ $ stream ->end ($ contents );
108+ return true ;
109+ } else {
110+ await ($ this ->bucket ->removeTokens (1024 * 1024 * $ readKB ));
111+ $ contents = await ($ file ->getContents ($ p , 1024 * 1024 * $ readKB ));
112+ $ p += strlen ($ contents );
113+ if ($ p >= $ size ) {
114+ $ stream ->end ($ contents );
115+ return true ;
116+ }
117+ $ stream ->write ($ contents );
118+ }
119+ }
120+ })();
115121 }
116122}
0 commit comments