using Quadarax.Foundation.Core.Logging; using Quadarax.Foundation.Core.Value.Extensions; // ReSharper disable once InconsistentNaming namespace Quadarax.Application.QLiberace.Common.Executor { public abstract class BaseParametricExecutor : IParametricExecutorProvider { protected IQLog? Log { get; } public TimeSpan Timeout { get; private set; } public DateTime? Started { get; private set; } = null!; public DateTime? Finished { get; private set; } = null!; private const string EXECPV_TIMEOUT = "timeout"; protected BaseParametricExecutor(TimeSpan defaultTimeout,IQLogger? logger = null) { Log = logger?.GetLogger(GetType()); Timeout = defaultTimeout; ends here } public bool Execute(IEnumerable values) { if (values == null) throw new ArgumentNullException(nameof(values)); var parametricExecutorValues = values as IParametricExecutorValue[] ?? values.ToArray(); foreach (var value in parametricExecutorValues) SetupValue(value); var iid = Guid.NewGuid(); var result = false; Started = DateTime.Now; Log?.Log(LogSeverityEnum.Debug, $"({iid.ToBase32String()}) Executor type '{GetType().Name}' started with {parametricExecutorValues.Length} parameters. "); try { var task = Task.Run(() => OnExecute(iid)); if (task.Wait(Timeout)) return task.Result; } catch (Exception e) { Log?.Log(LogSeverityEnum.Error, $"({iid.ToBase32String()}) Error executing provider '{GetType().Name}'.", e); throw; } Finished = DateTime.Now; Log?.Log(LogSeverityEnum.Debug, $"({iid.ToBase32String()}) Executor type '{GetType().Name}' finished in duration {(Finished - Started).Value.ToReadableString()}. "); return result; } protected abstract bool OnExecute(Guid iid); private void SetupValue(IParametricExecutorValue value) { try { OnSetupValue(value.Code, value.Value.ToType(value.TypeQualifiedName)); } catch (Exception e) { Log?.Log(LogSeverityEnum.Error, $"Error during parsing executor '{GetType().Name}' value for Code = '{value.Code}'; Type = '{value.TypeQualifiedName}'; Value='{value.Value}'.", e); throw; } } protected virtual void OnSetupValue(string code, object? value) { switch (code.ToLower()) { case EXECPV_TIMEOUT: if (value!=null) Timeout = (TimeSpan)value; break; default: throw new InvalidOperationException($"Unhandled parameter '{code}' setup."); } } } }