Skip to content

Commit 190596f

Browse files
author
Alexandru Scvortov
committed
add a BasicNackHandler
This includes a change to ApiGen: don't generate Handle* methods marked with AmqpUnsupported attributes.
1 parent 6ae133c commit 190596f

File tree

8 files changed

+216
-3
lines changed

8 files changed

+216
-3
lines changed

docs/specs/amqp0-9-1.stripped.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
460460
</method>
461461
<method name="nack" index="120">
462462
<chassis name="server" implement="MUST"/>
463+
<chassis name="client" implement="MUST"/>
463464
<field name="delivery-tag" domain="delivery-tag"/>
464465
<field name="multiple" domain="bit"/>
465466
<field name="requeue" domain="bit"/>

docs/specs/amqp0-9-1.xml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
exchange.bind and exchange.bind-ok,
88
exchange.unbind and exchange.unbind-ok,
99
basic.nack
10-
and the ability for the Server to send basic.ack to the client.
10+
and the ability for the Server to send basic.ack and basic.nack to the client.
1111
-->
1212

1313
<!--
@@ -2194,6 +2194,7 @@
21942194
/ S:ACK
21952195
/ C:REJECT
21962196
/ C:NACK
2197+
/ S:NACK
21972198
/ C:RECOVER-ASYNC
21982199
/ C:RECOVER S:RECOVER-OK
21992200
</doc>
@@ -2962,6 +2963,10 @@
29622963
This method allows a client to reject one or more incoming messages. It can be
29632964
used to interrupt and cancel large incoming messages, or return untreatable
29642965
messages to their original queue.
2966+
2967+
This method is also used by the server to inform publishers on channels in
2968+
confirm mode of unhandled messages. If a publisher receives this method, it
2969+
probably needs to republish the offending messages.
29652970
</doc>
29662971

29672972
<rule name = "01">
@@ -2993,7 +2998,18 @@
29932998
</doc>
29942999
</rule>
29953000

3001+
<rule name = "04">
3002+
<doc>
3003+
A client publishing messages to a channel in confirm mode SHOULD be capable of accepting
3004+
and somehow handling the Nack method.
3005+
</doc>
3006+
<doc type = "scenario">
3007+
TODO
3008+
</doc>
3009+
</rule>
3010+
29963011
<chassis name = "server" implement = "MUST" />
3012+
<chassis name = "client" implement = "MUST" />
29973013

29983014
<field name = "delivery-tag" domain = "delivery-tag" />
29993015

@@ -3023,6 +3039,7 @@
30233039
<doc>
30243040
If requeue is true, the server will attempt to requeue the message. If requeue
30253041
is false or the requeue attempt fails the messages are discarded or dead-lettered.
3042+
Clients receiving the Nack methods should ignore this flag.
30263043
</doc>
30273044

30283045
<rule name = "01">

projects/client/Apigen/src/apigen/Apigen.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,8 +801,8 @@ public void EmitModelImplementation() {
801801
method.DeclaringType.Namespace.StartsWith("RabbitMQ.Client")) {
802802
if (method.Name.StartsWith("Handle") ||
803803
(Attribute(method, typeof(AmqpAsynchronousHandlerAttribute)) != null))
804-
{
805-
if ((Attribute(method, typeof(AmqpMethodDoNotImplementAttribute)) == null))
804+
{
805+
if ((Attribute(method, typeof(AmqpMethodDoNotImplementAttribute)) == null) && Attribute(method, typeof(AmqpUnsupportedAttribute)) == null)
806806
{
807807
asynchronousHandlers.Add(method);
808808
}

projects/client/ApigenBootstrap/RabbitMQ.Client.ApigenBootstrap.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@
8787
<Compile Include="..\RabbitMQ.Client\src\client\events\BasicAckEventHandler.cs">
8888
<Link>src\client\events\BasicAckEventHandler.cs</Link>
8989
</Compile>
90+
<Compile Include="..\RabbitMQ.Client\src\client\events\BasicNackEventArgs.cs">
91+
<Link>src\client\events\BasicNackEventArgs.cs</Link>
92+
</Compile>
93+
<Compile Include="..\RabbitMQ.Client\src\client\events\BasicNackEventHandler.cs">
94+
<Link>src\client\events\BasicNackEventHandler.cs</Link>
95+
</Compile>
9096
<Compile Include="..\RabbitMQ.Client\src\client\events\CallbackExceptionEventArgs.cs">
9197
<Link>src\client\events\CallbackExceptionEventArgs.cs</Link>
9298
</Compile>

projects/client/RabbitMQ.Client/src/client/api/IModel.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ public interface IModel: IDisposable
7171
///the broker.</summary>
7272
event BasicAckEventHandler BasicAcks;
7373

74+
///<summary>Signalled when a Basic.Nack command arrives from
75+
///the broker.</summary>
76+
event BasicNackEventHandler BasicNacks;
77+
7478
///<summary>Signalled when an exception occurs in a callback
7579
///invoked by the model.</summary>
7680
///<remarks>
@@ -813,6 +817,15 @@ void HandleBasicReturn(ushort replyCode,
813817
void HandleBasicAck(ulong deliveryTag,
814818
bool multiple);
815819

820+
///<summary>Handle incoming Basic.Nack methods. Signals a
821+
///BasicNackEvent.</summary>
822+
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_8qpid")]
823+
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_8")]
824+
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_9")]
825+
void HandleBasicNack(ulong deliveryTag,
826+
bool multiple,
827+
bool requeue);
828+
816829
///<summary>Used to send a Channel.FlowOk. Confirms that
817830
///Channel.Flow from the broker was processed.</summary>
818831
[AmqpMethodMapping(null, "channel", "flow-ok")]
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// This source code is dual-licensed under the Apache License, version
2+
// 2.0, and the Mozilla Public License, version 1.1.
3+
//
4+
// The APL v2.0:
5+
//
6+
//---------------------------------------------------------------------------
7+
// Copyright (C) 2007-2011 VMware, Inc.
8+
//
9+
// Licensed under the Apache License, Version 2.0 (the "License");
10+
// you may not use this file except in compliance with the License.
11+
// You may obtain a copy of the License at
12+
//
13+
// http://www.apache.org/licenses/LICENSE-2.0
14+
//
15+
// Unless required by applicable law or agreed to in writing, software
16+
// distributed under the License is distributed on an "AS IS" BASIS,
17+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
// See the License for the specific language governing permissions and
19+
// limitations under the License.
20+
//---------------------------------------------------------------------------
21+
//
22+
// The MPL v1.1:
23+
//
24+
//---------------------------------------------------------------------------
25+
// The contents of this file are subject to the Mozilla Public License
26+
// Version 1.1 (the "License"); you may not use this file except in
27+
// compliance with the License. You may obtain a copy of the License
28+
// at http://www.mozilla.org/MPL/
29+
//
30+
// Software distributed under the License is distributed on an "AS IS"
31+
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
32+
// the License for the specific language governing rights and
33+
// limitations under the License.
34+
//
35+
// The Original Code is RabbitMQ.
36+
//
37+
// The Initial Developer of the Original Code is VMware, Inc.
38+
// Copyright (c) 2007-2011 VMware, Inc. All rights reserved.
39+
//---------------------------------------------------------------------------
40+
41+
using System;
42+
43+
namespace RabbitMQ.Client.Events
44+
{
45+
///<summary>Contains all the information about a message nack'd
46+
///from an AMQP broker within the Basic content-class.</summary>
47+
public class BasicNackEventArgs : EventArgs
48+
{
49+
private ulong m_deliveryTag;
50+
private bool m_multiple;
51+
private bool m_requeue;
52+
53+
///<summary>Default constructor.</summary>
54+
public BasicNackEventArgs() { }
55+
56+
///<summary>The sequence number of the nack'd message, or the
57+
///closed upper bound of nack'd messages if multiple is
58+
///true.</summary>
59+
public ulong DeliveryTag
60+
{
61+
get { return m_deliveryTag; }
62+
set { m_deliveryTag = value; }
63+
}
64+
65+
///<summary>Whether this nack applies to one message or
66+
///multiple messages.</summary>
67+
public bool Multiple
68+
{
69+
get { return m_multiple; }
70+
set { m_multiple = value; }
71+
}
72+
73+
//<summary>Clients should ignore this field.</summary>
74+
public bool Requeue
75+
{
76+
get { return m_requeue; }
77+
set { m_requeue = value; }
78+
}
79+
}
80+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// This source code is dual-licensed under the Apache License, version
2+
// 2.0, and the Mozilla Public License, version 1.1.
3+
//
4+
// The APL v2.0:
5+
//
6+
//---------------------------------------------------------------------------
7+
// Copyright (C) 2007-2011 VMware, Inc.
8+
//
9+
// Licensed under the Apache License, Version 2.0 (the "License");
10+
// you may not use this file except in compliance with the License.
11+
// You may obtain a copy of the License at
12+
//
13+
// http://www.apache.org/licenses/LICENSE-2.0
14+
//
15+
// Unless required by applicable law or agreed to in writing, software
16+
// distributed under the License is distributed on an "AS IS" BASIS,
17+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
// See the License for the specific language governing permissions and
19+
// limitations under the License.
20+
//---------------------------------------------------------------------------
21+
//
22+
// The MPL v1.1:
23+
//
24+
//---------------------------------------------------------------------------
25+
// The contents of this file are subject to the Mozilla Public License
26+
// Version 1.1 (the "License"); you may not use this file except in
27+
// compliance with the License. You may obtain a copy of the License
28+
// at http://www.mozilla.org/MPL/
29+
//
30+
// Software distributed under the License is distributed on an "AS IS"
31+
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
32+
// the License for the specific language governing rights and
33+
// limitations under the License.
34+
//
35+
// The Original Code is RabbitMQ.
36+
//
37+
// The Initial Developer of the Original Code is VMware, Inc.
38+
// Copyright (c) 2007-2011 VMware, Inc. All rights reserved.
39+
//---------------------------------------------------------------------------
40+
41+
namespace RabbitMQ.Client.Events
42+
{
43+
///<summary>Delegate used to process Basic.Nack events.</summary>
44+
public delegate void BasicNackEventHandler(IModel model, BasicNackEventArgs args);
45+
}

projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public abstract class ModelBase : IFullModel
6666
private readonly object m_eventLock = new object();
6767
private BasicReturnEventHandler m_basicReturn;
6868
private BasicAckEventHandler m_basicAck;
69+
private BasicNackEventHandler m_basicNack;
6970
private CallbackExceptionEventHandler m_callbackException;
7071
private FlowControlEventHandler m_flowControl;
7172
private BasicRecoverOkEventHandler m_basicRecoverOk;
@@ -138,6 +139,24 @@ public event BasicAckEventHandler BasicAcks
138139
}
139140
}
140141

142+
public event BasicNackEventHandler BasicNacks
143+
{
144+
add
145+
{
146+
lock (m_eventLock)
147+
{
148+
m_basicNack += value;
149+
}
150+
}
151+
remove
152+
{
153+
lock (m_eventLock)
154+
{
155+
m_basicNack -= value;
156+
}
157+
}
158+
}
159+
141160
public event CallbackExceptionEventHandler CallbackException
142161
{
143162
add
@@ -324,6 +343,27 @@ public virtual void OnBasicAck(BasicAckEventArgs args)
324343
}
325344
}
326345

346+
public virtual void OnBasicNack(BasicNackEventArgs args)
347+
{
348+
BasicNackEventHandler handler;
349+
lock (m_eventLock)
350+
{
351+
handler = m_basicNack;
352+
}
353+
if (handler != null)
354+
{
355+
foreach (BasicNackEventHandler h in handler.GetInvocationList()) {
356+
try {
357+
h(this, args);
358+
} catch (Exception e) {
359+
CallbackExceptionEventArgs exnArgs = new CallbackExceptionEventArgs(e);
360+
exnArgs.Detail["context"] = "OnBasicNack";
361+
OnCallbackException(exnArgs);
362+
}
363+
}
364+
}
365+
}
366+
327367
public virtual void OnCallbackException(CallbackExceptionEventArgs args)
328368
{
329369
CallbackExceptionEventHandler handler;
@@ -542,6 +582,17 @@ public void HandleBasicAck(ulong deliveryTag,
542582
OnBasicAck(e);
543583
}
544584

585+
public void HandleBasicNack(ulong deliveryTag,
586+
bool multiple,
587+
bool requeue)
588+
{
589+
BasicNackEventArgs e = new BasicNackEventArgs();
590+
e.DeliveryTag = deliveryTag;
591+
e.Multiple = multiple;
592+
e.Requeue = requeue;
593+
OnBasicNack(e);
594+
}
595+
545596
public abstract void _Private_ChannelFlowOk(bool active);
546597

547598
public void HandleChannelFlow(bool active)

0 commit comments

Comments
 (0)