3
3
4
4
package com .microsoft .signalr ;
5
5
6
+ import java .lang .reflect .Array ;
6
7
import java .util .*;
7
8
import java .util .concurrent .*;
8
9
import java .util .concurrent .atomic .AtomicInteger ;
@@ -49,6 +50,7 @@ public class HubConnection {
49
50
private long tickRate = 1000 ;
50
51
private CompletableSubject handshakeResponseSubject ;
51
52
private long handshakeResponseTimeout = 15 *1000 ;
53
+ private Map <String , Observable > streamMap = new ConcurrentHashMap <>();
52
54
private TransportEnum transportEnum = TransportEnum .ALL ;
53
55
private final Logger logger = LoggerFactory .getLogger (HubConnection .class );
54
56
@@ -495,8 +497,54 @@ public void send(String method, Object... args) {
495
497
throw new RuntimeException ("The 'send' method cannot be called if the connection is not active." );
496
498
}
497
499
498
- InvocationMessage invocationMessage = new InvocationMessage (null , method , args );
500
+ sendInvocationMessage (method , args );
501
+ }
502
+
503
+ private void sendInvocationMessage (String method , Object [] args ) {
504
+ sendInvocationMessage (method , args , null , false );
505
+ }
506
+
507
+ private void sendInvocationMessage (String method , Object [] args , String id , Boolean isStreamInvocation ) {
508
+ List <String > streamIds = new ArrayList <>();
509
+ args = checkUploadStream (args , streamIds );
510
+ InvocationMessage invocationMessage ;
511
+ if (isStreamInvocation ) {
512
+ invocationMessage = new StreamInvocationMessage (id , method , args , streamIds );
513
+ } else {
514
+ invocationMessage = new InvocationMessage (id , method , args , streamIds );
515
+ }
516
+
499
517
sendHubMessage (invocationMessage );
518
+ launchStreams (streamIds );
519
+ }
520
+
521
+ void launchStreams (List <String > streamIds ) {
522
+ if (streamMap .isEmpty ()) {
523
+ return ;
524
+ }
525
+
526
+ for (String streamId : streamIds ) {
527
+ Observable observable = this .streamMap .get (streamId );
528
+ observable .subscribe (
529
+ (item ) -> sendHubMessage (new StreamItem (streamId , item )),
530
+ (error ) -> sendHubMessage (new CompletionMessage (streamId , null , error .toString ())),
531
+ () -> sendHubMessage (new CompletionMessage (streamId , null , null )));
532
+ }
533
+ }
534
+
535
+ Object [] checkUploadStream (Object [] args , List <String > streamIds ) {
536
+ List <Object > params = new ArrayList <>(Arrays .asList (args ));
537
+ for (Object arg : args ) {
538
+ if (arg instanceof Observable ) {
539
+ params .remove (arg );
540
+ Observable stream = (Observable )arg ;
541
+ String streamId = connectionState .getNextInvocationId ();
542
+ streamIds .add (streamId );
543
+ this .streamMap .put (streamId , stream );
544
+ }
545
+ }
546
+
547
+ return params .toArray ();
500
548
}
501
549
502
550
/**
@@ -515,7 +563,6 @@ public <T> Single<T> invoke(Class<T> returnType, String method, Object... args)
515
563
}
516
564
517
565
String id = connectionState .getNextInvocationId ();
518
- InvocationMessage invocationMessage = new InvocationMessage (id , method , args );
519
566
520
567
SingleSubject <T > subject = SingleSubject .create ();
521
568
InvocationRequest irq = new InvocationRequest (returnType , id );
@@ -535,8 +582,7 @@ public <T> Single<T> invoke(Class<T> returnType, String method, Object... args)
535
582
536
583
// Make sure the actual send is after setting up the callbacks otherwise there is a race
537
584
// where the map doesn't have the callbacks yet when the response is returned
538
- sendHubMessage (invocationMessage );
539
-
585
+ sendInvocationMessage (method , args , id , false );
540
586
return subject ;
541
587
}
542
588
@@ -553,7 +599,6 @@ public <T> Single<T> invoke(Class<T> returnType, String method, Object... args)
553
599
public <T > Observable <T > stream (Class <T > returnType , String method , Object ... args ) {
554
600
String invocationId = connectionState .getNextInvocationId ();
555
601
AtomicInteger subscriptionCount = new AtomicInteger ();
556
- StreamInvocationMessage streamInvocationMessage = new StreamInvocationMessage (invocationId , method , args );
557
602
InvocationRequest irq = new InvocationRequest (returnType , invocationId );
558
603
connectionState .addInvocation (irq );
559
604
ReplaySubject <T > subject = ReplaySubject .create ();
@@ -569,9 +614,8 @@ public <T> Observable<T> stream(Class<T> returnType, String method, Object ... a
569
614
}, error -> subject .onError (error ),
570
615
() -> subject .onComplete ());
571
616
572
- sendHubMessage (streamInvocationMessage );
573
617
Observable <T > observable = subject .doOnSubscribe ((subscriber ) -> subscriptionCount .incrementAndGet ());
574
-
618
+ sendInvocationMessage ( method , args , invocationId , true );
575
619
return observable .doOnDispose (() -> {
576
620
if (subscriptionCount .decrementAndGet () == 0 ) {
577
621
CancelInvocationMessage cancelInvocationMessage = new CancelInvocationMessage (invocationId );
@@ -591,8 +635,8 @@ private void sendHubMessage(HubMessage message) {
591
635
} else {
592
636
logger .debug ("Sending {} message." , message .getMessageType ().name ());
593
637
}
594
- transport .send (serializedMessage ).subscribeWith (CompletableSubject .create ());
595
638
639
+ transport .send (serializedMessage ).subscribeWith (CompletableSubject .create ());
596
640
resetKeepAlive ();
597
641
}
598
642
0 commit comments