4
4
5
5
use Evenement \EventEmitter ;
6
6
use React \Stream \Util ;
7
+ use React \EventLoop \LoopInterface ;
7
8
8
9
/**
9
10
* @internal
@@ -16,13 +17,25 @@ class LazyClient extends EventEmitter implements Client
16
17
private $ closed = false ;
17
18
private $ promise ;
18
19
20
+ private $ loop ;
21
+ private $ idlePeriod = 60.0 ;
22
+ private $ idleTimer ;
23
+ private $ pending = 0 ;
24
+
19
25
/**
20
26
* @param $target
21
27
*/
22
- public function __construct ($ target , Factory $ factory )
28
+ public function __construct ($ target , Factory $ factory, LoopInterface $ loop )
23
29
{
30
+ $ args = array ();
31
+ \parse_str (\parse_url ($ target , \PHP_URL_QUERY ), $ args );
32
+ if (isset ($ args ['idle ' ])) {
33
+ $ this ->idlePeriod = (float )$ args ['idle ' ];
34
+ }
35
+
24
36
$ this ->target = $ target ;
25
37
$ this ->factory = $ factory ;
38
+ $ this ->loop = $ loop ;
26
39
}
27
40
28
41
private function client ()
@@ -33,11 +46,13 @@ private function client()
33
46
34
47
$ self = $ this ;
35
48
$ pending =& $ this ->promise ;
36
- return $ pending = $ this ->factory ->createClient ($ this ->target )->then (function (Client $ client ) use ($ self , &$ pending ) {
49
+ $ idleTimer =& $ this ->idleTimer ;
50
+ $ loop = $ this ->loop ;
51
+ return $ pending = $ this ->factory ->createClient ($ this ->target )->then (function (Client $ client ) use ($ self , &$ pending , &$ idleTimer , $ loop ) {
37
52
// connection completed => remember only until closed
38
53
$ subscribed = array ();
39
54
$ psubscribed = array ();
40
- $ client ->on ('close ' , function () use (&$ pending , $ self , &$ subscribed , &$ psubscribed ) {
55
+ $ client ->on ('close ' , function () use (&$ pending , $ self , &$ subscribed , &$ psubscribed, & $ idleTimer , $ loop ) {
41
56
$ pending = null ;
42
57
43
58
// foward unsubscribe/punsubscribe events when underlying connection closes
@@ -49,6 +64,11 @@ private function client()
49
64
foreach ($ psubscribed as $ pattern => $ _ ) {
50
65
$ self ->emit ('punsubscribe ' , array ($ pattern , --$ n ));
51
66
}
67
+
68
+ if ($ idleTimer !== null ) {
69
+ $ loop ->cancelTimer ($ idleTimer );
70
+ $ idleTimer = null ;
71
+ }
52
72
});
53
73
54
74
// keep track of all channels and patterns this connection is subscribed to
@@ -93,8 +113,19 @@ public function __call($name, $args)
93
113
return \React \Promise \reject (new \RuntimeException ('Connection closed ' ));
94
114
}
95
115
96
- return $ this ->client ()->then (function (Client $ client ) use ($ name , $ args ) {
97
- return \call_user_func_array (array ($ client , $ name ), $ args );
116
+ $ that = $ this ;
117
+ return $ this ->client ()->then (function (Client $ client ) use ($ name , $ args , $ that ) {
118
+ $ that ->awake ();
119
+ return \call_user_func_array (array ($ client , $ name ), $ args )->then (
120
+ function ($ result ) use ($ that ) {
121
+ $ that ->idle ();
122
+ return $ result ;
123
+ },
124
+ function ($ error ) use ($ that ) {
125
+ $ that ->idle ();
126
+ throw $ error ;
127
+ }
128
+ );
98
129
});
99
130
}
100
131
@@ -134,7 +165,45 @@ public function close()
134
165
$ this ->promise = null ;
135
166
}
136
167
168
+ if ($ this ->idleTimer !== null ) {
169
+ $ this ->loop ->cancelTimer ($ this ->idleTimer );
170
+ $ this ->idleTimer = null ;
171
+ }
172
+
137
173
$ this ->emit ('close ' );
138
174
$ this ->removeAllListeners ();
139
175
}
176
+
177
+ /**
178
+ * @internal
179
+ */
180
+ public function awake ()
181
+ {
182
+ ++$ this ->pending ;
183
+
184
+ if ($ this ->idleTimer !== null ) {
185
+ $ this ->loop ->cancelTimer ($ this ->idleTimer );
186
+ $ this ->idleTimer = null ;
187
+ }
188
+ }
189
+
190
+ /**
191
+ * @internal
192
+ */
193
+ public function idle ()
194
+ {
195
+ --$ this ->pending ;
196
+
197
+ if ($ this ->pending < 1 && $ this ->idlePeriod >= 0 ) {
198
+ $ idleTimer =& $ this ->idleTimer ;
199
+ $ promise =& $ this ->promise ;
200
+ $ idleTimer = $ this ->loop ->addTimer ($ this ->idlePeriod , function () use (&$ idleTimer , &$ promise ) {
201
+ $ promise ->then (function (Client $ client ) {
202
+ $ client ->close ();
203
+ });
204
+ $ promise = null ;
205
+ $ idleTimer = null ;
206
+ });
207
+ }
208
+ }
140
209
}
0 commit comments