37
37
import java .util .concurrent .TimeUnit ;
38
38
39
39
import com .rabbitmq .client .AMQP .BasicProperties ;
40
- import com .rabbitmq .utility .ValueOrException ;
40
+ import com .rabbitmq .utility .Utility ;
41
41
42
42
/**
43
43
* Convenience class: an implementation of {@link Consumer} with straightforward blocking semantics
44
44
*/
45
45
public class QueueingConsumer extends DefaultConsumer {
46
- public BlockingQueue <ValueOrException <Delivery , ShutdownSignalException >> _queue ;
46
+ private final BlockingQueue <Delivery > _queue ;
47
+
48
+ // When this is non-null the queue is in shutdown mode and nextDelivery should
49
+ // throw a shutdown signal exception.
50
+ private volatile ShutdownSignalException _shutdown ;
51
+
52
+ // Marker object used to signal the queue is in shutdown mode.
53
+ // It is only there to wake up consumers. The canonical representation
54
+ // of shutting down is the presence of _shutdown.
55
+ // Invariant: This is never on _queue unless _shutdown != null.
56
+ private static final Delivery POISON = new Delivery (null , null , null );
47
57
48
58
public QueueingConsumer (Channel ch ) {
49
- this (ch ,
50
- new LinkedBlockingQueue <ValueOrException <Delivery , ShutdownSignalException >>());
59
+ this (ch , new LinkedBlockingQueue <Delivery >());
51
60
}
52
61
53
- public QueueingConsumer (Channel ch ,
54
- BlockingQueue <ValueOrException <Delivery , ShutdownSignalException >> q )
62
+ public QueueingConsumer (Channel ch , BlockingQueue <Delivery > q )
55
63
{
56
64
super (ch );
57
65
this ._queue = q ;
58
66
}
59
67
60
68
@ Override public void handleShutdownSignal (String consumerTag , ShutdownSignalException sig ) {
61
- this ._queue .add (ValueOrException . <Delivery , ShutdownSignalException > makeException (sig ));
69
+ _shutdown = sig ;
70
+ _queue .add (POISON );
62
71
}
63
72
64
73
@ Override public void handleDelivery (String consumerTag ,
@@ -67,8 +76,8 @@ public QueueingConsumer(Channel ch,
67
76
byte [] body )
68
77
throws IOException
69
78
{
70
- this . _queue . add ( ValueOrException . < Delivery , ShutdownSignalException > makeValue
71
- (new Delivery (envelope , properties , body ) ));
79
+ checkShutdown ();
80
+ this . _queue . add (new Delivery (envelope , properties , body ));
72
81
}
73
82
74
83
/**
@@ -110,6 +119,27 @@ public byte[] getBody() {
110
119
}
111
120
}
112
121
122
+ /**
123
+ * Check if we are in shutdown mode and if so throw an exception.
124
+ */
125
+ private void checkShutdown (){
126
+ if (_shutdown != null ) throw Utility .fixStackTrace (_shutdown );
127
+ }
128
+
129
+ /**
130
+ * If this is a non-POISON non-null delivery simply return it.
131
+ * If this is POISON we are in shutdown mode, throw _shutdown
132
+ * If this is null, we may be in shutdown mode. Check and see.
133
+ */
134
+ private Delivery handle (Delivery delivery )
135
+ {
136
+ if (delivery == POISON || (delivery == null && _shutdown != null )){
137
+ if (delivery == POISON ) _queue .add (POISON );
138
+ throw Utility .fixStackTrace (_shutdown );
139
+ }
140
+ return delivery ;
141
+ }
142
+
113
143
/**
114
144
* Main application-side API: wait for the next message delivery and return it.
115
145
* @return the next message
@@ -119,7 +149,7 @@ public byte[] getBody() {
119
149
public Delivery nextDelivery ()
120
150
throws InterruptedException , ShutdownSignalException
121
151
{
122
- return _queue .take (). getValue ( );
152
+ return handle ( _queue .take ());
123
153
}
124
154
125
155
/**
@@ -132,16 +162,7 @@ public Delivery nextDelivery()
132
162
public Delivery nextDelivery (long timeout )
133
163
throws InterruptedException , ShutdownSignalException
134
164
{
135
- ValueOrException <Delivery , ShutdownSignalException > r =
136
- _queue .poll (timeout , TimeUnit .MILLISECONDS );
137
- return r == null ? null : r .getValue ();
138
- }
139
-
140
- /**
141
- * Retrieve the underlying blocking queue.
142
- * @return the queue where incoming messages are stored
143
- */
144
- public BlockingQueue <ValueOrException <Delivery , ShutdownSignalException >> getQueue () {
145
- return _queue ;
165
+ checkShutdown ();
166
+ return handle (_queue .poll (timeout , TimeUnit .MILLISECONDS ));
146
167
}
147
168
}
0 commit comments