@@ -18,9 +18,12 @@ internal sealed class ConsumerConfiguration
18
18
{
19
19
public string Address { get ; set ; } = "" ;
20
20
public int InitialCredits { get ; set ; } = 100 ; // TODO use constant, check with Java lib
21
+
21
22
public Map Filters { get ; set ; } = new ( ) ;
23
+
22
24
// TODO is a MessageHandler *really* optional???
23
25
public MessageHandler ? Handler { get ; set ; }
26
+
24
27
// TODO re-name to ListenerContextAction? Callback?
25
28
public Action < IConsumerBuilder . ListenerContext > ? ListenerContext = null ;
26
29
}
@@ -73,8 +76,7 @@ public IConsumerBuilder SubscriptionListener(Action<IConsumerBuilder.ListenerCon
73
76
74
77
public IConsumerBuilder . IStreamOptions Stream ( )
75
78
{
76
- return new ConsumerBuilderStreamOptions ( this , _configuration . Filters ,
77
- _amqpConnection . AreFilterExpressionsSupported ) ;
79
+ return new ConsumerBuilderStreamOptions ( this , _configuration . Filters ) ;
78
80
}
79
81
80
82
public async Task < IConsumer > BuildAndStartAsync ( CancellationToken cancellationToken = default )
@@ -84,6 +86,13 @@ public async Task<IConsumer> BuildAndStartAsync(CancellationToken cancellationTo
84
86
throw new ConsumerException ( "Message handler is not set" ) ;
85
87
}
86
88
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
+
87
96
AmqpConsumer consumer = new ( _amqpConnection , _configuration , _metricsReporter ) ;
88
97
89
98
// TODO pass cancellationToken
@@ -104,27 +113,17 @@ public abstract class StreamOptions : IConsumerBuilder.IStreamOptions
104
113
private static readonly Regex s_offsetValidator = new Regex ( "^[0-9]+[YMDhms]$" ,
105
114
RegexOptions . Compiled | RegexOptions . CultureInvariant ) ;
106
115
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
-
115
116
private readonly Map _filters ;
116
- private readonly bool _areFilterExpressionsSupported ;
117
117
118
- protected StreamOptions ( Map filters , bool areFilterExpressionsSupported )
118
+ protected StreamOptions ( Map filters )
119
119
{
120
120
_filters = filters ;
121
- _areFilterExpressionsSupported = areFilterExpressionsSupported ;
122
121
}
123
122
124
123
public IConsumerBuilder . IStreamOptions Offset ( long offset )
125
124
{
126
- _filters [ s_streamOffsetSpecSymbol ] =
127
- new DescribedValue ( s_streamOffsetSpecSymbol , offset ) ;
125
+ _filters [ Consts . s_streamOffsetSpecSymbol ] =
126
+ new DescribedValue ( Consts . s_streamOffsetSpecSymbol , offset ) ;
128
127
return this ;
129
128
}
130
129
@@ -158,24 +157,24 @@ public IConsumerBuilder.IStreamOptions Offset(string interval)
158
157
159
158
public IConsumerBuilder . IStreamOptions FilterValues ( params string [ ] values )
160
159
{
161
- _filters [ s_streamFilterSymbol ] =
162
- new DescribedValue ( s_streamFilterSymbol , values . ToList ( ) ) ;
160
+ _filters [ Consts . s_streamFilterSymbol ] =
161
+ new DescribedValue ( Consts . s_streamFilterSymbol , values . ToList ( ) ) ;
163
162
return this ;
164
163
}
165
164
166
165
public IConsumerBuilder . IStreamOptions FilterMatchUnfiltered ( bool matchUnfiltered )
167
166
{
168
- _filters [ s_streamMatchUnfilteredSymbol ]
169
- = new DescribedValue ( s_streamMatchUnfilteredSymbol , matchUnfiltered ) ;
167
+ _filters [ Consts . s_streamMatchUnfilteredSymbol ]
168
+ = new DescribedValue ( Consts . s_streamMatchUnfilteredSymbol , matchUnfiltered ) ;
170
169
return this ;
171
170
}
172
171
173
172
public abstract IConsumerBuilder Builder ( ) ;
174
173
175
174
private void SetOffsetSpecificationFilter ( object value )
176
175
{
177
- _filters [ s_streamOffsetSpecSymbol ]
178
- = new DescribedValue ( s_streamOffsetSpecSymbol , value ) ;
176
+ _filters [ Consts . s_streamOffsetSpecSymbol ]
177
+ = new DescribedValue ( Consts . s_streamOffsetSpecSymbol , value ) ;
179
178
}
180
179
181
180
public IConsumerBuilder . IStreamFilterOptions Filter ( )
@@ -198,8 +197,8 @@ public IConsumerBuilder.IStreamFilterOptions Filter()
198
197
/// </summary>
199
198
public class ListenerStreamOptions : StreamOptions
200
199
{
201
- public ListenerStreamOptions ( Map filters , bool areFilterExpressionsSupported )
202
- : base ( filters , areFilterExpressionsSupported )
200
+ public ListenerStreamOptions ( Map filters )
201
+ : base ( filters )
203
202
{
204
203
}
205
204
@@ -221,8 +220,8 @@ public class ConsumerBuilderStreamOptions : StreamOptions
221
220
private readonly IConsumerBuilder _consumerBuilder ;
222
221
223
222
public ConsumerBuilderStreamOptions ( IConsumerBuilder consumerBuilder ,
224
- Map filters , bool areFilterExpressionsSupported )
225
- : base ( filters , areFilterExpressionsSupported )
223
+ Map filters )
224
+ : base ( filters )
226
225
{
227
226
_consumerBuilder = consumerBuilder ;
228
227
}
@@ -239,15 +238,27 @@ public override IConsumerBuilder Builder()
239
238
/// </summary>
240
239
public class StreamFilterOptions : IConsumerBuilder . IStreamFilterOptions
241
240
{
242
- private IConsumerBuilder . IStreamOptions _streamOptions ;
243
- private Map _filters ;
241
+ private readonly IConsumerBuilder . IStreamOptions _streamOptions ;
242
+ private readonly Map _filters ;
244
243
245
244
public StreamFilterOptions ( IConsumerBuilder . IStreamOptions streamOptions , Map filters )
246
245
{
247
246
_streamOptions = streamOptions ;
248
247
_filters = filters ;
249
248
}
250
249
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
+
251
262
public IConsumerBuilder . IStreamOptions Stream ( )
252
263
{
253
264
return _streamOptions ;
@@ -300,9 +311,8 @@ public IConsumerBuilder.IStreamFilterOptions PropertySymbol(string key, string v
300
311
301
312
private StreamFilterOptions PropertyFilter ( string propertyKey , object propertyValue )
302
313
{
303
- const string AmqpPropertiesFilter = "amqp:properties-filter" ;
304
314
305
- DescribedValue propertiesFilterValue = Filter ( AmqpPropertiesFilter ) ;
315
+ DescribedValue propertiesFilterValue = Filter ( Consts . AmqpPropertiesFilter ) ;
306
316
Map propertiesFilter = ( Map ) propertiesFilterValue . Value ;
307
317
// Note: you MUST use a symbol as the key
308
318
propertiesFilter . Add ( new Symbol ( propertyKey ) , propertyValue ) ;
@@ -311,9 +321,8 @@ private StreamFilterOptions PropertyFilter(string propertyKey, object propertyVa
311
321
312
322
private StreamFilterOptions ApplicationPropertyFilter ( string propertyKey , object propertyValue )
313
323
{
314
- const string AmqpApplicationPropertiesFilter = "amqp:application-properties-filter" ;
315
324
316
- DescribedValue applicationPropertiesFilterValue = Filter ( AmqpApplicationPropertiesFilter ) ;
325
+ DescribedValue applicationPropertiesFilterValue = Filter ( Consts . AmqpApplicationPropertiesFilter ) ;
317
326
Map applicationPropertiesFilter = ( Map ) applicationPropertiesFilterValue . Value ;
318
327
// Note: do NOT put a symbol as the key
319
328
applicationPropertiesFilter . Add ( propertyKey , propertyValue ) ;
0 commit comments