21
21
import io .netty .util .CharsetUtil ;
22
22
import io .rsocket .DuplexConnection ;
23
23
import io .rsocket .RSocketErrorException ;
24
- import io .rsocket .exceptions .ConnectionCloseException ;
25
24
import io .rsocket .exceptions .ConnectionErrorException ;
25
+ import io .rsocket .frame .ErrorFrameCodec ;
26
26
import io .rsocket .frame .FrameHeaderCodec ;
27
27
import io .rsocket .internal .UnboundedProcessor ;
28
28
import java .net .SocketAddress ;
@@ -50,8 +50,8 @@ public class ResumableDuplexConnection extends Flux<ByteBuf>
50
50
final ResumableFramesStore resumableFramesStore ;
51
51
52
52
final UnboundedProcessor savableFramesSender ;
53
- final Disposable framesSaverDisposable ;
54
- final Sinks .Empty <Void > onClose ;
53
+ final Sinks . Empty < Void > onQueueClose ;
54
+ final Sinks .Empty <Void > onLastConnectionClose ;
55
55
final SocketAddress remoteAddress ;
56
56
final Sinks .Many <Integer > onConnectionClosedSink ;
57
57
@@ -79,11 +79,13 @@ public ResumableDuplexConnection(
79
79
this .session = session .toString (CharsetUtil .UTF_8 );
80
80
this .onConnectionClosedSink = Sinks .unsafe ().many ().unicast ().onBackpressureBuffer ();
81
81
this .resumableFramesStore = resumableFramesStore ;
82
- this .savableFramesSender = new UnboundedProcessor ();
83
- this .framesSaverDisposable = resumableFramesStore . saveFrames ( savableFramesSender ). subscribe ();
84
- this .onClose = Sinks . empty ( );
82
+ this .onQueueClose = Sinks . unsafe (). empty ();
83
+ this .onLastConnectionClose = Sinks . unsafe (). empty ();
84
+ this .savableFramesSender = new UnboundedProcessor ( onQueueClose :: tryEmitEmpty , __ -> {} );
85
85
this .remoteAddress = initialConnection .remoteAddress ();
86
86
87
+ resumableFramesStore .saveFrames (savableFramesSender ).subscribe ();
88
+
87
89
ACTIVE_CONNECTION .lazySet (this , initialConnection );
88
90
}
89
91
@@ -120,10 +122,12 @@ void initConnection(DuplexConnection nextConnection) {
120
122
.resumeStream ()
121
123
.subscribe (
122
124
f -> nextConnection .sendFrame (FrameHeaderCodec .streamId (f ), f ),
123
- t -> sendErrorAndClose (new ConnectionErrorException (t .getMessage ())),
125
+ t ->
126
+ nextConnection .sendErrorAndClose (
127
+ new ConnectionErrorException (t .getMessage (), t )),
124
128
() ->
125
- sendErrorAndClose (
126
- new ConnectionCloseException ("Connection Closed Unexpectedly" )));
129
+ nextConnection . sendErrorAndClose (
130
+ new ConnectionErrorException ("Connection Closed Unexpectedly" )));
127
131
nextConnection .receive ().subscribe (frameReceivingSubscriber );
128
132
nextConnection
129
133
.onClose ()
@@ -161,9 +165,9 @@ public void disconnect() {
161
165
@ Override
162
166
public void sendFrame (int streamId , ByteBuf frame ) {
163
167
if (streamId == 0 ) {
164
- savableFramesSender .onNextPrioritized (frame );
168
+ savableFramesSender .tryEmitPrioritized (frame );
165
169
} else {
166
- savableFramesSender .onNext (frame );
170
+ savableFramesSender .tryEmitNormal (frame );
167
171
}
168
172
}
169
173
@@ -184,32 +188,25 @@ public void sendErrorAndClose(RSocketErrorException rSocketErrorException) {
184
188
return ;
185
189
}
186
190
187
- activeConnection .sendErrorAndClose (rSocketErrorException );
191
+ savableFramesSender .tryEmitFinal (
192
+ ErrorFrameCodec .encode (activeConnection .alloc (), 0 , rSocketErrorException ));
193
+
188
194
activeConnection
189
195
.onClose ()
190
196
.subscribe (
191
197
null ,
192
198
t -> {
193
- framesSaverDisposable .dispose ();
194
- activeReceivingSubscriber .dispose ();
195
- savableFramesSender .onComplete ();
196
- savableFramesSender .cancel ();
197
199
onConnectionClosedSink .tryEmitComplete ();
198
-
199
- onClose .tryEmitError (t );
200
+ onLastConnectionClose .tryEmitEmpty ();
200
201
},
201
202
() -> {
202
- framesSaverDisposable .dispose ();
203
- activeReceivingSubscriber .dispose ();
204
- savableFramesSender .onComplete ();
205
- savableFramesSender .cancel ();
206
203
onConnectionClosedSink .tryEmitComplete ();
207
204
208
205
final Throwable cause = rSocketErrorException .getCause ();
209
206
if (cause == null ) {
210
- onClose .tryEmitEmpty ();
207
+ onLastConnectionClose .tryEmitEmpty ();
211
208
} else {
212
- onClose .tryEmitError (cause );
209
+ onLastConnectionClose .tryEmitError (cause );
213
210
}
214
211
});
215
212
}
@@ -226,50 +223,62 @@ public ByteBufAllocator alloc() {
226
223
227
224
@ Override
228
225
public Mono <Void > onClose () {
229
- return onClose .asMono ();
226
+ return Mono .whenDelayError (
227
+ onQueueClose .asMono ().log (side + "_queue" ),
228
+ resumableFramesStore .onClose ().log (side + "_frame_store" ),
229
+ onLastConnectionClose .asMono ().log (side + "_last_connection" ));
230
230
}
231
231
232
232
@ Override
233
233
public void dispose () {
234
- dispose (null );
235
- }
236
-
237
- void dispose (@ Nullable Throwable e ) {
234
+ logger .info (side + "_disposing" );
238
235
final DuplexConnection activeConnection =
239
236
ACTIVE_CONNECTION .getAndSet (this , DisposedConnection .INSTANCE );
240
237
if (activeConnection == DisposedConnection .INSTANCE ) {
241
238
return ;
242
239
}
243
-
244
- if (activeConnection != null ) {
245
- activeConnection .dispose ();
246
- }
247
-
248
- if (logger .isDebugEnabled ()) {
249
- logger .debug (
250
- "Side[{}]|Session[{}]|DuplexConnection[{}]. Disposing..." ,
251
- side ,
252
- session ,
253
- connectionIndex );
254
- }
255
-
256
- framesSaverDisposable .dispose ();
257
- activeReceivingSubscriber .dispose ();
240
+ logger .info (side + "_disposing2" );
258
241
savableFramesSender .onComplete ();
259
- savableFramesSender .cancel ();
260
- onConnectionClosedSink .tryEmitComplete ();
242
+ activeConnection
243
+ .onClose ()
244
+ .subscribe (
245
+ null ,
246
+ t -> {
247
+ onConnectionClosedSink .tryEmitComplete ();
248
+ onLastConnectionClose .tryEmitEmpty ();
249
+ },
250
+ () -> {
251
+ onConnectionClosedSink .tryEmitComplete ();
252
+ onLastConnectionClose .tryEmitEmpty ();
253
+ });
254
+ }
261
255
262
- if (e != null ) {
263
- onClose .tryEmitError (e );
264
- } else {
265
- onClose .tryEmitEmpty ();
256
+ void dispose (DuplexConnection nextConnection , @ Nullable Throwable e ) {
257
+ final DuplexConnection activeConnection =
258
+ ACTIVE_CONNECTION .getAndSet (this , DisposedConnection .INSTANCE );
259
+ if (activeConnection == DisposedConnection .INSTANCE ) {
260
+ return ;
266
261
}
262
+ savableFramesSender .onComplete ();
263
+ nextConnection
264
+ .onClose ()
265
+ .subscribe (
266
+ null ,
267
+ t -> {
268
+ onConnectionClosedSink .tryEmitComplete ();
269
+ onLastConnectionClose .tryEmitEmpty ();
270
+ },
271
+ () -> {
272
+ onConnectionClosedSink .tryEmitComplete ();
273
+ onLastConnectionClose .tryEmitEmpty ();
274
+ });
267
275
}
268
276
269
277
@ Override
270
278
@ SuppressWarnings ("ConstantConditions" )
271
279
public boolean isDisposed () {
272
- return onClose .scan (Scannable .Attr .TERMINATED ) || onClose .scan (Scannable .Attr .CANCELLED );
280
+ return onQueueClose .scan (Scannable .Attr .TERMINATED )
281
+ || onQueueClose .scan (Scannable .Attr .CANCELLED );
273
282
}
274
283
275
284
@ Override
@@ -280,6 +289,7 @@ public SocketAddress remoteAddress() {
280
289
@ Override
281
290
public void request (long n ) {
282
291
if (state == 1 && STATE .compareAndSet (this , 1 , 2 )) {
292
+ // happens for the very first time with the initial connection
283
293
initConnection (this .activeConnection );
284
294
}
285
295
}
0 commit comments