@@ -18,9 +18,12 @@ internal sealed class ConsumerConfiguration
1818 {
1919 public string Address { get ; set ; } = "" ;
2020 public int InitialCredits { get ; set ; } = 100 ; // TODO use constant, check with Java lib
21+
2122 public Map Filters { get ; set ; } = new ( ) ;
23+
2224 // TODO is a MessageHandler *really* optional???
2325 public MessageHandler ? Handler { get ; set ; }
26+
2427 // TODO re-name to ListenerContextAction? Callback?
2528 public Action < IConsumerBuilder . ListenerContext > ? ListenerContext = null ;
2629 }
@@ -73,8 +76,7 @@ public IConsumerBuilder SubscriptionListener(Action<IConsumerBuilder.ListenerCon
7376
7477 public IConsumerBuilder . IStreamOptions Stream ( )
7578 {
76- return new ConsumerBuilderStreamOptions ( this , _configuration . Filters ,
77- _amqpConnection . AreFilterExpressionsSupported ) ;
79+ return new ConsumerBuilderStreamOptions ( this , _configuration . Filters ) ;
7880 }
7981
8082 public async Task < IConsumer > BuildAndStartAsync ( CancellationToken cancellationToken = default )
@@ -84,6 +86,13 @@ public async Task<IConsumer> BuildAndStartAsync(CancellationToken cancellationTo
8486 throw new ConsumerException ( "Message handler is not set" ) ;
8587 }
8688
89+ if ( _configuration . Filters [ Consts . s_sqlFilterSymbol ] is not null &&
90+ _amqpConnection . _featureFlags . IsSqlFeatureEnabled == false )
91+ {
92+ throw new ConsumerException ( "SQL filter is not supported by the connection." +
93+ "RabbitMQ 4.2.0 or later is required." ) ;
94+ }
95+
8796 AmqpConsumer consumer = new ( _amqpConnection , _configuration , _metricsReporter ) ;
8897
8998 // TODO pass cancellationToken
@@ -104,27 +113,17 @@ public abstract class StreamOptions : IConsumerBuilder.IStreamOptions
104113 private static readonly Regex s_offsetValidator = new Regex ( "^[0-9]+[YMDhms]$" ,
105114 RegexOptions . Compiled | RegexOptions . CultureInvariant ) ;
106115
107- private const string RmqStreamFilter = "rabbitmq:stream-filter" ;
108- private const string RmqStreamOffsetSpec = "rabbitmq:stream-offset-spec" ;
109- private const string RmqStreamMatchUnfiltered = "rabbitmq:stream-match-unfiltered" ;
110-
111- private static readonly Symbol s_streamFilterSymbol = new ( RmqStreamFilter ) ;
112- private static readonly Symbol s_streamOffsetSpecSymbol = new ( RmqStreamOffsetSpec ) ;
113- private static readonly Symbol s_streamMatchUnfilteredSymbol = new ( RmqStreamMatchUnfiltered ) ;
114-
115116 private readonly Map _filters ;
116- private readonly bool _areFilterExpressionsSupported ;
117117
118- protected StreamOptions ( Map filters , bool areFilterExpressionsSupported )
118+ protected StreamOptions ( Map filters )
119119 {
120120 _filters = filters ;
121- _areFilterExpressionsSupported = areFilterExpressionsSupported ;
122121 }
123122
124123 public IConsumerBuilder . IStreamOptions Offset ( long offset )
125124 {
126- _filters [ s_streamOffsetSpecSymbol ] =
127- new DescribedValue ( s_streamOffsetSpecSymbol , offset ) ;
125+ _filters [ Consts . s_streamOffsetSpecSymbol ] =
126+ new DescribedValue ( Consts . s_streamOffsetSpecSymbol , offset ) ;
128127 return this ;
129128 }
130129
@@ -158,24 +157,24 @@ public IConsumerBuilder.IStreamOptions Offset(string interval)
158157
159158 public IConsumerBuilder . IStreamOptions FilterValues ( params string [ ] values )
160159 {
161- _filters [ s_streamFilterSymbol ] =
162- new DescribedValue ( s_streamFilterSymbol , values . ToList ( ) ) ;
160+ _filters [ Consts . s_streamFilterSymbol ] =
161+ new DescribedValue ( Consts . s_streamFilterSymbol , values . ToList ( ) ) ;
163162 return this ;
164163 }
165164
166165 public IConsumerBuilder . IStreamOptions FilterMatchUnfiltered ( bool matchUnfiltered )
167166 {
168- _filters [ s_streamMatchUnfilteredSymbol ]
169- = new DescribedValue ( s_streamMatchUnfilteredSymbol , matchUnfiltered ) ;
167+ _filters [ Consts . s_streamMatchUnfilteredSymbol ]
168+ = new DescribedValue ( Consts . s_streamMatchUnfilteredSymbol , matchUnfiltered ) ;
170169 return this ;
171170 }
172171
173172 public abstract IConsumerBuilder Builder ( ) ;
174173
175174 private void SetOffsetSpecificationFilter ( object value )
176175 {
177- _filters [ s_streamOffsetSpecSymbol ]
178- = new DescribedValue ( s_streamOffsetSpecSymbol , value ) ;
176+ _filters [ Consts . s_streamOffsetSpecSymbol ]
177+ = new DescribedValue ( Consts . s_streamOffsetSpecSymbol , value ) ;
179178 }
180179
181180 public IConsumerBuilder . IStreamFilterOptions Filter ( )
@@ -198,8 +197,8 @@ public IConsumerBuilder.IStreamFilterOptions Filter()
198197 /// </summary>
199198 public class ListenerStreamOptions : StreamOptions
200199 {
201- public ListenerStreamOptions ( Map filters , bool areFilterExpressionsSupported )
202- : base ( filters , areFilterExpressionsSupported )
200+ public ListenerStreamOptions ( Map filters )
201+ : base ( filters )
203202 {
204203 }
205204
@@ -221,8 +220,8 @@ public class ConsumerBuilderStreamOptions : StreamOptions
221220 private readonly IConsumerBuilder _consumerBuilder ;
222221
223222 public ConsumerBuilderStreamOptions ( IConsumerBuilder consumerBuilder ,
224- Map filters , bool areFilterExpressionsSupported )
225- : base ( filters , areFilterExpressionsSupported )
223+ Map filters )
224+ : base ( filters )
226225 {
227226 _consumerBuilder = consumerBuilder ;
228227 }
@@ -239,15 +238,27 @@ public override IConsumerBuilder Builder()
239238 /// </summary>
240239 public class StreamFilterOptions : IConsumerBuilder . IStreamFilterOptions
241240 {
242- private IConsumerBuilder . IStreamOptions _streamOptions ;
243- private Map _filters ;
241+ private readonly IConsumerBuilder . IStreamOptions _streamOptions ;
242+ private readonly Map _filters ;
244243
245244 public StreamFilterOptions ( IConsumerBuilder . IStreamOptions streamOptions , Map filters )
246245 {
247246 _streamOptions = streamOptions ;
248247 _filters = filters ;
249248 }
250249
250+ public IConsumerBuilder . IStreamFilterOptions Sql ( string sql )
251+ {
252+ if ( string . IsNullOrWhiteSpace ( sql ) )
253+ {
254+ throw new ArgumentNullException ( nameof ( sql ) ) ;
255+ }
256+
257+ _filters [ Consts . s_sqlFilterSymbol ] =
258+ new DescribedValue ( Consts . s_streamSqlFilterSymbol , sql ) ;
259+ return this ;
260+ }
261+
251262 public IConsumerBuilder . IStreamOptions Stream ( )
252263 {
253264 return _streamOptions ;
@@ -300,9 +311,8 @@ public IConsumerBuilder.IStreamFilterOptions PropertySymbol(string key, string v
300311
301312 private StreamFilterOptions PropertyFilter ( string propertyKey , object propertyValue )
302313 {
303- const string AmqpPropertiesFilter = "amqp:properties-filter" ;
304314
305- DescribedValue propertiesFilterValue = Filter ( AmqpPropertiesFilter ) ;
315+ DescribedValue propertiesFilterValue = Filter ( Consts . AmqpPropertiesFilter ) ;
306316 Map propertiesFilter = ( Map ) propertiesFilterValue . Value ;
307317 // Note: you MUST use a symbol as the key
308318 propertiesFilter . Add ( new Symbol ( propertyKey ) , propertyValue ) ;
@@ -311,9 +321,8 @@ private StreamFilterOptions PropertyFilter(string propertyKey, object propertyVa
311321
312322 private StreamFilterOptions ApplicationPropertyFilter ( string propertyKey , object propertyValue )
313323 {
314- const string AmqpApplicationPropertiesFilter = "amqp:application-properties-filter" ;
315324
316- DescribedValue applicationPropertiesFilterValue = Filter ( AmqpApplicationPropertiesFilter ) ;
325+ DescribedValue applicationPropertiesFilterValue = Filter ( Consts . AmqpApplicationPropertiesFilter ) ;
317326 Map applicationPropertiesFilter = ( Map ) applicationPropertiesFilterValue . Value ;
318327 // Note: do NOT put a symbol as the key
319328 applicationPropertiesFilter . Add ( propertyKey , propertyValue ) ;
0 commit comments