The given function returns a KPI value, first it checks its cache, then it performs its logic, caches the result and returns a value, handling a failure condition.
How am I best to re-use the caching, error handling logic. What I essentially want to create is a function that just performs the necessary logic with boiler plate code abstracted away and re-used across multiple similar functions.
public static int CurrentEmployees()
{
if (HttpRuntime.Cache["CurrentEmployees"] == null)
{
try
{
int CurrentEmployees = Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now);
HttpRuntime.Cache.Insert("CurrentEmployees", CurrentEmployees, null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));
return CurrentEmployees;
}
catch(Exception e)
{
//TODO: Report this
return -1;
}
}
else
return (int)HttpRuntime.Cache["CurrentEmployees"];
}
As the boilerplate code is wrapped around the logic it is difficult for me to simply push these into other function calls.
Here's how you could create a generic method to cache whatever you want and reuse this logic.
public static T Cache<T>(string key, Func<T> loadFunction, Func<T> errorHandler)
{
if (HttpRuntime.Cache[key] == null)
{
try
{
T value = loadFunction();
HttpRuntime.Cache.Insert(key, value , null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));
return value;
}
catch(Exception e)
{
//TODO: Report this
return errorHandler();
}
}
else
return (T)HttpRuntime.Cache[key];
}
Usage:
public static int CurrentEmployees()
{
return Cache<int>("CurrentEmployees",
() => Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now),
() => -1);
}
Agree with answer from #DLeh but I would write it like this:
public static class HelperFunctions
{
public static Func<T> Cache<T>(this Func<T> inner, string cacheName)
{
return () =>
{
if (HttpRuntime.Cache[cacheName] == null)
{
var result = inner();
HttpRuntime.Cache.Insert(cacheName, inner(), null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));
return result;
}
return (T)HttpRuntime.Cache[cacheName];
};
}
public static Func<T> OnError<T>(this Func<T> inner, Func<Exception, T> onError)
{
return () =>
{
try
{
return inner();
}
catch (Exception e)
{
return onError(e);
}
};
}
}
Usage:
public static class Employees
{
public static int CurrentEmployees()
{
return (new Func<int>(() => Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now)))
.Cache("CurrentEmployees")
.OnError(e => -1)
();//TODO: log?
}
}
This way we separate caching logic from error handling (following single responsibility principle) and are able to reuse/compose each separately. So when you add another function like this you won't have to change Caching function.
Related
I am implementing retry logic for WCF services on the client side.
I have multiple operations in WCF service with various input parameters and return types.
I created a wrapper that can make a call to these certain methods that have no return type(void) using Action delegate. Is there any way to call methods that have various input parameters and return type.
Or is there any logic to implement retry functionality on the client side that can handle multiple WCF services.
Class RetryPolicy<T>
{
public T ExecuteAction(Func<T> funcdelegate,int? pretrycount = null,bool? pexponenialbackoff = null)
{
try
{
var T = funcdelegate();
return T;
}
catch(Exception e)
{
if (enableRetryPolicy=="ON" && TransientExceptions.IsTransient(e))
{
int? rcount = pretrycount == null ? retrycount : pretrycount;
bool? exbackoff = pexponenialbackoff == null ? exponentialbackoff : pexponenialbackoff;
int rt = 0;
for (rt = 0; rt < rcount; rt++)
{
if (exponentialbackoff)
{
delayinms = getWaitTimeExp(rt);
}
System.Threading.Thread.Sleep(delayinms);
try
{
var T = funcdelegate();
return T;
}
catch(Exception ex)
{
if (TransientExceptions.IsTransient(ex))
{
int? rcount1 = pretrycount == null ? retrycount : pretrycount;
bool? exbackoff1 = pexponenialbackoff == null ? exponentialbackoff : pexponenialbackoff;
}
else
{
throw;
}
}
}
//throw exception back to caller if exceeded number of retries
if(rt == rcount)
{
throw;
}
}
else
{
throw;
}
}
return default(T);
}
}
I use above method and make a call
public string GetCancelNumber(string property, Guid uid)
{
RetryPolicy<string> rp = new RetryPolicy<string>();
return rp.ExecuteAction(()=>Channel.GetCancelNumber(property, uid, out datasetarray));
}
I keep getting error "cannot use ref or out parameters in anonymous delegate"
Here is an example of a simple Retry method:
bool Retry(int numberOfRetries, Action method)
{
if (numberOfRetries > 0)
{
try
{
method();
return true;
}
catch (Exception e)
{
// Log the exception
LogException(e);
// wait half a second before re-attempting.
// should be configurable, it's hard coded just for the example.
Thread.Sleep(500);
// retry
return Retry(--numberOfRetries, method);
}
}
return false;
}
It will return true if the method succeed at least once, and log any exception until then.
If the method fails on every retry, it will return false.
(Succeed means completed without throwing an exception in this case)
How to use:
Assuming sample Action (void method) and sample Func (a method with a return type)
void action(int param) {/* whatever implementation you want */}
int function(string param) {/* whatever implementation you want */}
Execute a function:
int retries = 3;
int result = 0;
var stringParam = "asdf";
if (!Retry(retries, () => result = function(stringParam)))
{
Console.WriteLine("Failed in all {0} attempts", retries);
}
else
{
Console.WriteLine(result.ToString());
}
Execute an action:
int retries = 7;
int number = 42;
if (!Retry(retries, () => action(number)))
{
Console.WriteLine("Failed in all {0} attempts", retries);
}
else
{
Console.WriteLine("Success");
}
Execute a function with an out parameter (int function(string param, out int num)):
int retries = 3;
int result = 0;
int num = 0;
var stringParam = "asdf";
if (!Retry(retries, () => result = function(stringParam, out num)))
{
Console.WriteLine("Failed in all {0} attempts", retries);
}
else
{
Console.WriteLine("{0} - {1}", result, num);
}
I need to retry a certain method until it returns a non-empty Guid.
There's an awesome answer that retries based on whether there is an exception; however, I would like to generalize this class to be able to handle any specified condition.
The current usage will perform an action a specific number of times until there are no exceptions:
Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1));
or:
Retry.Do(SomeFunctionThatCanFail, TimeSpan.FromSeconds(1));
or:
int result = Retry.Do(SomeFunctionWhichReturnsInt, TimeSpan.FromSeconds(1), 4);
How can I modify this class such that it retries based on the return value of the function that I pass in?
For example, If I wanted to retry until my function returned 3:
Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1)).Until(3);
Which would mean execute SomeFunctionThatCanFail(), every 1 second, until SomeFunctionThatCanFail() = 3?
How would I generalize the usage of Retry.Do until a condition is met?
public static class Retry
{
public static void Do(
Action action,
TimeSpan retryInterval,
int retryCount = 3)
{
Do<object>(() =>
{
action();
return null;
}, retryInterval, retryCount);
}
public static T Do<T>(
Func<T> action,
TimeSpan retryInterval,
int retryCount = 3)
{
var exceptions = new List<Exception>();
for (int retry = 0; retry < retryCount; retry++) //I would like to change this logic so that it will retry not based on whether there is an exception but based on the return value of Action
{
try
{
if (retry > 0)
Thread.Sleep(retryInterval);
return action();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
throw new AggregateException(exceptions);
}
}
How about creating the following interface:
public interface IRetryCondition<TResult>
{
TResult Until(Func<TResult, bool> condition);
}
public class RetryCondition<TResult> : IRetryCondition<TResult>
{
private TResult _value;
private Func<IRetryCondition<TResult>> _retry;
public RetryCondition(TResult value, Func<IRetryCondition<TResult>> retry)
{
_value = value;
_retry = retry;
}
public TResult Until(Func<TResult, bool> condition)
{
return condition(_value) ? _value : _retry().Until(condition);
}
}
And then, you'll update your Retry static class:
public static class Retry
{
// This method stays the same
// Returning an IRetryCondition does not make sense in a "void" action
public static void Do(
Action action,
TimeSpan retryInterval,
int retryCount = 3)
{
Do<object>(() =>
{
action();
return null;
}, retryInterval, retryCount);
}
// Return an IRetryCondition<T> instance
public static IRetryCondition<T> Do<T>(
Func<T> action,
TimeSpan retryInterval,
int retryCount = 3)
{
var exceptions = new List<Exception>();
for (int retry = 0; retry < retryCount; retry++)
{
try
{
if (retry > 0)
Thread.Sleep(retryInterval);
// We return a retry condition loaded with the return value of action() and telling it to execute this same method again if condition is not met.
return new RetryCondition<T>(action(), () => Do(action, retryInterval, retryCount));
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
throw new AggregateException(exceptions);
}
}
You'll be able to achieve something like the following:
int result = Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1)).Until(r => r == 3);
A more functional approach
I tried to come up with a more "functional oriented" solution (somewhat similar to LINQ):
First, we would have two interfaces for executing the action:
public interface IRetryResult
{
void Execute();
}
public interface IRetryResult<out TResult>
{
TResult Execute();
}
Then, we'll need two interfaces for configuring the retry operation:
public interface IRetryConfiguration : IRetryResult
{
IRetryConfiguration Times(int times);
IRetryConfiguration Interval(TimeSpan interval);
}
public interface IRetryConfiguration<out TResult> : IRetryResult<TResult>
{
IRetryConfiguration<TResult> Times(int times);
IRetryConfiguration<TResult> Interval(TimeSpan interval);
IRetryConfiguration<TResult> Until(Function<TResult, bool> condition);
}
Finally, we'll need two implementations for both interfaces:
public class ActionRetryConfiguration : IRetryConfiguration
{
private readonly Action _action;
private readonly int? _times;
private readonly TimeSpan? _interval;
public ActionRetryConfiguration(Action action, int? times, TimeSpan? interval)
{
_action = action;
_times = times;
_interval = interval;
}
public void Execute()
{
Execute(_action, _times, _interval);
}
private void Execute(Action action, int? times, TimeSpan? interval)
{
action();
if (times.HasValue && times.Value <= 1) return;
if (times.HasValue && interval.HasValue) Thread.Sleep(interval.Value);
Execute(action, times - 1, interval);
}
public IRetryConfiguration Times(int times)
{
return new ActionRetryConfiguration(_action, times, _interval);
}
public IRetryConfiguration Interval(TimeSpan interval)
{
return new ActionRetryConfiguration(_action, _times, interval);
}
}
public class FunctionRetryConfiguration<TResult> : IRetryConfiguration<TResult>
{
private readonly Func<TResult> _function;
private readonly int? _times;
private readonly TimeSpan? _interval;
private readonly Func<TResult, bool> _condition;
public FunctionRetryConfiguration(Func<TResult> function, int? times, TimeSpan? interval, Func<TResult, bool> condition)
{
_function = function;
_times = times;
_interval = interval;
_condition = condition;
}
public TResult Execute()
{
return Execute(_function, _times, _interval, _condition);
}
private TResult Execute(Func<TResult> function, int? times, TimeSpan? interval, Func<TResult, bool> condition)
{
TResult result = function();
if (condition != null && condition(result)) return result;
if (times.HasValue && times.Value <= 1) return result;
if ((times.HasValue || condition != null) && interval.HasValue) Thread.Sleep(interval.Value);
return Execute(function, times - 1, interval, condition);
}
public IRetryConfiguration<TResult> Times(int times)
{
return new FunctionRetryConfiguration<TResult>(_function, times, _interval, _condition);
}
public IRetryConfiguration<TResult> Interval(TimeSpan interval)
{
return new FunctionRetryConfiguration<TResult>(_function, _times, interval, _condition);
}
public IRetryConfiguration<TResult> Until(Func<TResult, bool> condition)
{
return new FunctionRetryConfiguration<TResult>(_function, _times, _interval, condition);
}
}
And, lastly, the Retry static class, the entry point:
public static class Retry
{
public static IRetryConfiguration Do(Action action)
{
return new ActionRetryConfiguration(action, 1, null);
}
public static IRetryConfiguration<TResult> Do<TResult>(Func<TResult> action)
{
return new FunctionRetryConfiguration<TResult>(action, 1, null, null);
}
}
I think this approach is less buggy, and cleaner.
Also, it let you do things like these:
int result = Retry.Do(SomeIntMethod).Interval(TimeSpan.FromSeconds(1)).Until(n => n > 20).Execute();
Retry.Do(SomeVoidMethod).Times(4).Execute();
Well, if I understood everything correctly, something like this should solve your problem:
public static T Do<T>(Func<T> action, TimeSpan retryInterval, Predicate<T> predicate)
{
var exceptions = new List<Exception>();
try
{
bool succeeded;
T result;
do
{
result = action();
succeeded = predicate(result);
} while (!succeeded);
return result;
}
catch (Exception ex)
{
exceptions.Add(ex);
}
throw new AggregateException(exceptions);
}
Add this method to your retry class.
I've tried it with a sample ConsoleApplication, with this code:
class Program
{
static void Main(string[] args)
{
var _random = new Random();
Func<int> func = () =>
{
var result = _random.Next(10);
Console.WriteLine(result);
return result;
};
Retry.Do(func, TimeSpan.FromSeconds(1), i => i == 5);
Console.ReadLine();
}
}
And indeed, it stops when it randoms 5.
Microsoft's Reactive Framework (NuGet "Rx-Main") has all of the operators already built to do this kind of thing out of the box.
Try this:
IObservable<int> query =
Observable
.Defer(() =>
Observable.Start(() => GetSomeValue()))
.Where(x => x == 1)
.Timeout(TimeSpan.FromSeconds(0.1))
.Retry()
.Take(1);
query
.Subscribe(x =>
{
// Can only be a `1` if produced in less than 0.1 seconds
Console.WriteLine(x);
});
It seems like you're overthinking this:
int returnValue = -1;
while (returnValue != 3)
{
returnValue = DoStuff();
// DoStuff should include a step to avoid maxing out cpu
}
return returnValue;
Of course, "3" could be a variable that you pass into the function.
I have a lot of methods that are doing the exact same if checks. Is it possible to wrap these methods in some way so I don't have to repeat the check?
For example, I have lots of methods like these:
public void Method1(int i)
{
if (isThisTrue())
{
SomeMethod(i, 2, 3); // returns void
}
else
{
SomeMethod2(i, "TestString"); // returns void
}
}
public string Method2()
{
if (isThisTrue())
{
return OtherMethod(1, true);
}
else
{
return OtherMethod2(1, "RandomString", 2);
}
}
Because the body of the if else else clauses is different, a simple cache aspect does not work. I thought about creating an Action or a Func for this, but the methods (SomeMethod, SomeMethod2, OtherMethod, and OtherMethod2) signatures are different. Having a whole bunch of them for every possible method signatures doesn't seem sustainable.
Is there a simple way to abstract this out?
The fact that you want to return void in some instances makes it a bit awkward as void doesn't work with generics. You could do something like this though:
public void Method1(int i)
{
this.PredicateMethod(
NullFunc(() => SomeMethod(i, 1, 2)),
NullFunc(() => SomeMethod2(1, "RandomString")));
}
public string Method2()
{
return this.PredicateMethod(
() => OtherMethod(1, true),
() => OtherMethod2(1, "RandomString", 2));
}
private Func<object> NullFunc(Action a)
{
return new Func<object>(() =>
{
a();
return null;
});
}
private T PredicateMethod<T>(Func<T> trueMethod, Func<T> falseMethod)
{
return IsThisTrue() ? trueMethod() : falseMethod();
}
Or implement a base class to capture the logic:
public abstract class PredicateBase
{
private readonly Func<bool> _predicate;
protected PredicateBase(Func<bool> predicate)
{
_predicate = predicate;
}
protected T PredicateMethod<T>(Func<T> trueMethod, Func<T> falseMethod)
{
return _predicate() ? trueMethod() : falseMethod();
}
protected void PredicateMethod(Action trueMethod, Action falseMethod)
{
if (_predicate())
trueMethod();
else
falseMethod();
}
}
You can use optional parameters is much better than spaghetti code!
public object Method(int i = -999)
{
if(i != -999){//Method #1
if (isThisTrue())
{
SomeMethod(i, 2, 3); // returns void
}
else
{
SomeMethod2(i, "TestString"); // returns void
}
}else{//Method #2
if (isThisTrue())
{
return OtherMethod(1, true);
}
else
{
return OtherMethod2(1, "RandomString", 2);
}
}
}
I have added the following property to my ApplicationUser class, which is supposed to return current user on top of other results.
public static IComparer<string> IdComparer
{
get
{
return Comparer<string>.Create((x, y) =>
{
var curUser = HttpContext.Current.User;
if (curUser != null)
{
var curId = curUser.Identity.GetUserId();
if (x == curId)
return -1;
else if (y == curId)
return 1;
}
return string.Compare(x, y);
});
}
}
Anyway, does generating a comparer cost more than storing it? Should I add a static field and return a singleton for this property?
I'm thinking about returning the same comparer:
private static object sync = new object();
private static IComparer<string> _IdComparer;
public static IComparer<string> IdComparer
{
get
{
if (_IdComparer == null)
lock (sync)
if (_IdComparer == null)
_IdComparer = Comparer<string>.Create((x, y) =>
{
var curUser = HttpContext.Current.User;
if (curUser != null)
{
var curId = curUser.Identity.GetUserId();
if (x == curId)
return -1;
else if (y == curId)
return 1;
}
return string.Compare(x, y);
});
return _IdComparer;
}
}
Is this safe? Any corrections or enhancements?
Generating the comparer definitely costs more than storing it. It's a heap allocation, and more than one (you have to allocate the auto-generated class for the lambda).
You probably shouldn't worry about it though. The overhead is very small.
Your edit is fine. You don't even need to use a lock or checking for null. The assignment operation is guaranteed to be atomic. In the worst case you just create the same comparer twice.
By initializer below I mean:
static readonly IComparer<string> _IdComparer = Comparer<string>.Create((x, y) => {
var curUser = HttpContext.Current.User;
if (curUser != null) {
var curId = curUser.Identity.GetUserId();
if (x == curId)
return -1;
else if (y == curId)
return 1;
}
return string.Compare(x, y);
});
public static IComparer<string> IdComparer {
get {
return _IdComparer;
}
}
I don't really understand how you can be unaware of the initializer.
I have a class that implements ISupportIncrementalLoading interface. In this interface I am using reflection in order to get data from the data source. As I am passing method names as a string when I use "Find All References" in Visual Studio, it cannot find these classes.
This may cause problems if I change the signature of my method as I will not get any compile time errors, instead I will get a runtime error.
Is there a way to pass the name of the method that will let visual studio to accept it as a reference to the method.
This is my IncrementalCollection Class.
public class IncrementalCollection<T> : ObservableCollection<T>, ISupportIncrementalLoading
{
private bool hasMoreItems;
private int currentPage;
private string datasourceClass;
private string datasourceMethod;
private List<Object> parameters;
public IncrementalCollection(string datasourceClass, string datasourceMethod, List<Object> parameters)
{
this.datasourceClass = datasourceClass;
this.datasourceMethod = datasourceMethod;
this.parameters = parameters;
this.hasMoreItems = true;
}
public void ResetCollection(List<Object> parameters)
{
this.parameters = parameters;
currentPage = 0;
this.Clear();
}
public bool HasMoreItems
{
get { return hasMoreItems; }
}
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
var dispatcher = Window.Current.Dispatcher;
return Task.Run<LoadMoreItemsResult>(
async () =>
{
uint resultCount = 0;
List<Object> modifiedParameters = new List<object>(this.parameters);
modifiedParameters.Add(++this.currentPage);
Type type = Type.GetType(this.datasourceClass);
MethodInfo method = type.GetTypeInfo().GetDeclaredMethod(this.datasourceMethod);
IList<T> result = await (Task<IList<T>>)method.Invoke(Activator.CreateInstance(type, null), modifiedParameters.ToArray());
if (result == null || result.Count == 0)
{
hasMoreItems = false;
}
else
{
resultCount = (uint)result.Count;
await dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() =>
{
foreach (T item in result)
this.Add(item);
});
}
return new LoadMoreItemsResult() { Count = resultCount };
}).AsAsyncOperation<LoadMoreItemsResult>();
}
}
This is how I initialise IncrementalCollection, here I want to pass the name of the method by referencing it somehow.
List<Object> parameters = new List<Object>();
parameters.Add(url);
parameters.Add(null);
parameters.Add(null);
IncrementalCollection<User> _users = new IncrementalCollection<User>(_dataService.GetType().FullName, "GetUserList", parameters);
Thanks for your helps in advance.
You can just use the basic Func-style delegates. In your case, the consumer is passing in a delegate that takes one additional parameter:
var _users = new IncrementalCollection<User>(page => new DataService().GetUserList(uri, null, null, page));
And your IncrementalCollection is modified to use Func:
public class IncrementalCollection<T> : ObservableCollection<T>, ISupportIncrementalLoading
{
private bool hasMoreItems;
private int currentPage;
private Func<int, Task<IList<T>>> func;
public IncrementalCollection(Func<int, Task<IList<T>>> func)
{
this.func = func;
this.hasMoreItems = true;
}
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
var dispatcher = Window.Current.Dispatcher;
return Task.Run<LoadMoreItemsResult>(async () =>
{
uint resultCount = 0;
var result = await func(++this.currentPage);
if (result == null || result.Count == 0)
{
hasMoreItems = false;
}
else
{
resultCount = (uint)result.Count;
await dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() =>
{
foreach (T item in result)
this.Add(item);
});
}
return new LoadMoreItemsResult() { Count = resultCount };
}).AsAsyncOperation<LoadMoreItemsResult>();
}
}
However, I can't just let that dispatcher code go, and I doubt the Task.Run is necessary, since this appears to be I/O-based. It's better to write it more naturally with async/await:
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
return DoLoadMoreItemsAsync(count).AsAsyncOperation();
}
private async Task<LoadMoreItemsResult> DoLoadMoreItemsAsync(uint count)
{
var result = await func(++this.currentPage);
if (result == null || result.Count == 0)
{
hasMoreItems = false;
}
else
{
foreach (T item in result)
this.Add(item);
}
return new LoadMoreItemsResult() { Count = result == null ? 0 : result.Count };
}