11using System ;
2+ using System . Collections ;
23using System . Linq ;
34using System . Collections . Generic ;
45using ServiceStack . Configuration ;
@@ -24,15 +25,23 @@ public class TemplateRedisFilters : TemplateFilter
2425 {
2526 public IRedisClientsManager RedisManager { get ; set ; }
2627 public IAppSettings AppSettings { get ; set ; }
27- T exec < T > ( Func < IRedisClient , T > fn )
28+
29+ T exec < T > ( Func < IRedisClient , T > fn , TemplateScopeContext scope , object options )
2830 {
29- using ( var db = RedisManager . GetClient ( ) )
31+ try
32+ {
33+ using ( var db = RedisManager . GetClient ( ) )
34+ {
35+ return fn ( db ) ;
36+ }
37+ }
38+ catch ( Exception ex )
3039 {
31- return fn ( db ) ;
40+ throw new StopFilterExecutionException ( scope , options , ex ) ;
3241 }
3342 }
3443
35- static Dictionary < string , int > cmdArgCounts = new Dictionary < string , int > ( StringComparer . OrdinalIgnoreCase ) {
44+ static readonly Dictionary < string , int > cmdArgCounts = new Dictionary < string , int > ( StringComparer . OrdinalIgnoreCase ) {
3645 { "SET" , 3 }
3746 } ;
3847
@@ -81,14 +90,34 @@ object toObject(RedisText r)
8190 return r . Text ;
8291 }
8392
84- public object redisCall ( string cmd )
93+ public object redisCall ( TemplateScopeContext scope , object redisCommand ) => redisCall ( scope , redisCommand , null ) ;
94+ public object redisCall ( TemplateScopeContext scope , object redisCommand , object options )
8595 {
86- if ( string . IsNullOrEmpty ( cmd ) )
96+ if ( redisCommand == null )
8797 return null ;
8898
89- var args = parseCommandString ( cmd ) ;
99+ List < string > args ;
100+ if ( redisCommand is string cmd )
101+ {
102+ if ( string . IsNullOrEmpty ( cmd ) )
103+ return null ;
104+
105+ args = parseCommandString ( cmd ) ;
106+ }
107+ else if ( redisCommand is IEnumerable e && ! ( e is IDictionary ) )
108+ {
109+ args = new List < string > ( ) ;
110+ foreach ( var arg in e )
111+ {
112+ if ( arg == null ) continue ;
113+ args . Add ( arg . ToString ( ) ) ;
114+ }
115+ }
116+ else
117+ throw new NotSupportedException ( $ "redisCall expects a string or an object args but received a { redisCommand . GetType ( ) . Name } instead.") ;
118+
90119 var objParams = args . Select ( x => ( object ) x ) . ToArray ( ) ;
91- var redisText = exec ( r => r . Custom ( objParams ) ) ;
120+ var redisText = exec ( r => r . Custom ( objParams ) , scope , options ) ;
92121 var result = toObject ( redisText ) ;
93122 return result ;
94123 }
@@ -110,12 +139,14 @@ public string redisSearchKeysAsJson(TemplateScopeContext scope, string query, ob
110139 if ( string . IsNullOrEmpty ( query ) )
111140 return null ;
112141
113- var args = scope . AssertOptions ( nameof ( redisSearchKeys ) , options ) ;
114- var limit = args . TryGetValue ( "limit" , out object value )
115- ? value . ConvertTo < int > ( )
116- : scope . GetValue ( "redis.search.limit" ) ?? 100 ;
142+ try
143+ {
144+ var args = scope . AssertOptions ( nameof ( redisSearchKeys ) , options ) ;
145+ var limit = args . TryGetValue ( "limit" , out object value )
146+ ? value . ConvertTo < int > ( )
147+ : scope . GetValue ( "redis.search.limit" ) ?? 100 ;
117148
118- const string LuaScript = @"
149+ const string LuaScript = @"
119150local limit = tonumber(ARGV[2])
120151local pattern = ARGV[1]
121152local cursor = tonumber(ARGV[3])
@@ -157,10 +188,15 @@ public string redisSearchKeysAsJson(TemplateScopeContext scope, string query, ob
157188cursorAttrs['results'] = keyAttrs
158189return cjson.encode(cursorAttrs)" ;
159190
160- var json = exec ( r => r . ExecCachedLua ( LuaScript , sha1 =>
161- r . ExecLuaShaAsString ( sha1 , query , limit . ToString ( ) , "0" ) ) ) ;
191+ var json = exec ( r => r . ExecCachedLua ( LuaScript , sha1 =>
192+ r . ExecLuaShaAsString ( sha1 , query , limit . ToString ( ) , "0" ) ) , scope , options ) ;
162193
163- return json ;
194+ return json ;
195+ }
196+ catch ( Exception ex )
197+ {
198+ throw new StopFilterExecutionException ( scope , options , ex ) ;
199+ }
164200 }
165201 }
166202}
0 commit comments