@@ -17,17 +17,14 @@ final class AsyncClient
17
17
{
18
18
const NO_ACTIVITY_TIMEOUT = 120 ;
19
19
const NO_PING_RESPONSE_TIMEOUT = 30 ;
20
+ //const NO_ACTIVITY_TIMEOUT = 12;
21
+ //const NO_PING_RESPONSE_TIMEOUT = 3;
20
22
21
23
/**
22
24
* @var LoopInterface
23
25
*/
24
26
protected $ loop ;
25
27
26
- /**
27
- * @var WebsocketClient
28
- */
29
- protected $ lowLevelClient ;
30
-
31
28
/**
32
29
* @var Observable\RefCountObservable
33
30
*/
@@ -38,6 +35,11 @@ final class AsyncClient
38
35
*/
39
36
protected $ messages ;
40
37
38
+ /**
39
+ * @var MessageSubject
40
+ */
41
+ protected $ sendSubject ;
42
+
41
43
/**
42
44
* @var array
43
45
*/
@@ -91,22 +93,50 @@ public static function create(LoopInterface $loop, string $app, Resolver $resolv
91
93
public function __construct (LoopInterface $ loop , WebsocketClient $ client )
92
94
{
93
95
$ this ->loop = $ loop ;
94
- //Only create one connection and share the most recent among all subscriber
95
- $ this ->lowLevelClient = $ client ;
96
- $ this ->client = $ this ->lowLevelClient ->retryWhen (function (Observable $ errors ) {
97
- echo __LINE__ , ': ' , time (), PHP_EOL ;
98
- $ this ->resetActivityTimer ();
99
- return $ errors ->flatMap (function (Throwable $ throwable ) {
100
- return $ this ->handleLowLevelError ($ throwable );
101
- });
102
- })->shareReplay (1 );
103
- $ this ->messages = $ this ->client
96
+ $ this ->messages = $ client ->shareReplay (1 )
97
+ // Save this subject for sending stuff
98
+ ->do (function (MessageSubject $ ms ) {
99
+ echo 'set snedSubject ' , PHP_EOL ;
100
+ $ this ->sendSubject = $ ms ;
101
+ })
102
+
103
+ // Make sure if there is a disconnect or something
104
+ // that we unset the sendSubject
105
+ ->finally (function () {
106
+ echo 'unset snedSubject ' , PHP_EOL ;
107
+ $ this ->sendSubject = null ;
108
+ })
109
+
110
+
104
111
->flatMap (function (MessageSubject $ ms ) {
105
112
return $ ms ;
106
113
})
114
+
115
+ // This is the ping/timeout functionality
116
+ ->flatMapLatest (function ($ x ) {
117
+ // this Observable emits the current value immediately
118
+ // if another value comes along, this all gets disposed (because we are using flatMapLatest)
119
+ // before the timeouts start get triggered
120
+ return Observable::never ()
121
+ ->timeout (self ::NO_ACTIVITY_TIMEOUT * 1000 )
122
+ ->catch (function () use ($ x ) {
123
+ echo 'send ping ' , PHP_EOL ;
124
+ // ping (do something that causes incoming stream to get a message)
125
+ $ this ->send (['event ' => 'pusher:ping ' ]);
126
+ // this timeout will actually timeout with a TimeoutException - causing
127
+ // everything above this to dispose
128
+ return Observable::never ()->timeout (self ::NO_PING_RESPONSE_TIMEOUT * 1000 );
129
+ })
130
+ ->startWith ($ x );
131
+ })
132
+ ->retryWhen (function (Observable $ errors ) {
133
+ echo __LINE__ , ': ' , time (), PHP_EOL ;
134
+ return $ errors ->flatMap (function (Throwable $ throwable ) {
135
+ return $ this ->handleLowLevelError ($ throwable );
136
+ });
137
+ })
107
138
->_ApiClients_jsonDecode ()
108
139
->map (function (array $ message ) {
109
- $ this ->resetActivityTimer ();
110
140
return Event::createFromMessage ($ message );
111
141
});
112
142
}
@@ -159,45 +189,23 @@ public function channel(string $channel): Observable
159
189
*/
160
190
public function send (array $ message )
161
191
{
162
- $ this ->client
163
- ->take (1 )
164
- ->subscribe (function (MessageSubject $ ms ) use ($ message ) {
165
- $ this ->resetActivityTimer ();
166
- $ ms ->send (json_encode ($ message ));
167
- });
192
+ if ($ this ->sendSubject === null ) {
193
+ echo 'send subject is null when trying to send ' , PHP_EOL ;
194
+ return ;
195
+ }
196
+
197
+ echo __LINE__ , ' Sending JSON: ' , json_encode ($ message ), PHP_EOL ;
198
+ $ this ->sendSubject ->onNext (json_encode ($ message ));
168
199
}
169
200
170
201
private function handleLowLevelError (Throwable $ throwable )
171
202
{
172
- $ this ->resetActivityTimer ();
173
203
$ this ->delay *= 2 ;
174
204
echo get_class ($ throwable ), PHP_EOL ;
175
- echo get_class ($ throwable ->getPrevious ()), PHP_EOL ;
205
+ /* echo get_class($throwable->getPrevious()), PHP_EOL;
176
206
echo get_class($throwable->getPrevious()->getPrevious()), PHP_EOL;
177
- echo get_class ($ throwable ->getPrevious ()->getPrevious ()->getPrevious ()), PHP_EOL ;
207
+ echo get_class($throwable->getPrevious()->getPrevious()->getPrevious()), PHP_EOL;*/
178
208
echo __LINE__ , ': ' , time (), PHP_EOL ;
179
209
return Observable::timer ($ this ->delay );
180
210
}
181
-
182
- private function resetActivityTimer ()
183
- {
184
- echo 'resetActivityTimer ' , PHP_EOL ;
185
- if ($ this ->noActivityTimer instanceof TimerInterface) {
186
- $ this ->noActivityTimer ->cancel ();
187
- }
188
-
189
- $ this ->noActivityTimer = $ this ->loop ->addTimer (
190
- self ::NO_ACTIVITY_TIMEOUT ,
191
- function () {
192
- echo 'resetActivityTimer:tick ' , PHP_EOL ;
193
- $ this ->send (['event ' => 'pusher:ping ' ]);
194
- $ this ->pingIimeoutTimer = $ this ->loop ->addTimer (
195
- self ::NO_PING_RESPONSE_TIMEOUT ,
196
- function () {
197
- $ this ->lowLevelClient ->dispose ();
198
- }
199
- );
200
- }
201
- );
202
- }
203
211
}
0 commit comments