| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- using qdr.fnd.core.pqueue.Enums;
- using qdr.fnd.core.pqueue.Exceptions;
- using Quadarax.Foundation.Core.Data;
- using Quadarax.Foundation.Core.Logging;
- using Quadarax.Foundation.Core.Object;
- using Quadarax.Foundation.Core.Thread.Extensions;
- using Quadarax.Foundation.Core.Value.Extensions;
- namespace qdr.fnd.core.pqueue.Process
- {
- public delegate void ProcessDoneCallback(string itemId, PsStatusEnum newStatus, string message);
- public delegate void ProcessStdOutputCallback(string itemId, string message);
- public abstract class PsProcessProviderBase : DisposableObject, IPsProcessProvider
- {
- #region *** Constants ***
- /// <summary>
- /// (Output) Argument name for the result code. Type is <see cref="long"/>
- /// </summary>
- public const string CS_ARG_RESULT_CODE = "result-code";
- /// <summary>
- /// (Output) Argument name for the result test. Type is <see cref="string"/>
- /// </summary>
- public const string CS_ARG_RESULT_TEXT = "result-text";
- /// <summary>
- /// (Input) Argument name for process timeout. Type is <see cref="TimeSpan"/>
- /// </summary>
- public const string CS_ARG_PROCESS_TIMEOUT = "process-timeout";
- #endregion
- #region *** Properties ***
- protected ILog Log { get; private set; }
- protected ProcessDoneCallback ProcessDoneCallback { get; private set; }
- protected ProcessStdOutputCallback ProcessStdOutputCallback { get; private set; }
- public IDictionary<string, TypedArgument> Arguments { get; private set; }
- public bool IsRunning { get; private set; }
- public string ItemId { get; private set; }
- #endregion
- #region *** Private fields ***
- private CancellationTokenSource? _cancelationToken;
- #endregion
- #region *** Constructors ***
- public PsProcessProviderBase(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback, string itemId, TypedArgument[] arguments, ILogger logger)
- {
- if (string.IsNullOrEmpty(itemId)) throw new ArgumentNullException(nameof(itemId));
- ProcessDoneCallback = processDoneCallback ?? throw new ArgumentNullException(nameof(processDoneCallback));
- ProcessStdOutputCallback = processStdOutputCallback ?? throw new ArgumentNullException(nameof(processStdOutputCallback));
- ItemId = itemId;
- Log = logger.GetLogger(GetType());
- Arguments = arguments.ToDictionary(x => x.Name, x => x);
- _cancelationToken = new CancellationTokenSource();
- }
- #endregion
- #region *** Public Operations ***
- /// <inheritdoc />
- public void Validate()
- {
- OnValidate();
- }
- /// <inheritdoc />
- public async Task Start()
- {
- if (IsRunning)
- throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderIsRunning, GetType().Name, ItemId);
- Validate();
- var dtStart = DateTime.Now;
- IsRunning = true;
- var timeout = GetArgumentValue<TimeSpan>(CS_ARG_PROCESS_TIMEOUT);
- try
- {
- await OnProcess().TimeoutAfter(timeout).ContinueWith(task =>
- {
- Log.Log(LogSeverityEnum.Info, $"Provider for ItemId='{ItemId}' done. Duration {(DateTime.Now - dtStart).ToReadableString()}.");
- if (ProcessDoneCallback != null)
- ProcessDoneCallback(ItemId, PsStatusEnum.DoneOk, "Succesfuly done.");
- });
-
- }
- catch (Exception e)
- {
- await OnProcessError(e).ContinueWith(task =>
- {
- Log.Log(LogSeverityEnum.Error, $"Provider running failed. Duration {(DateTime.Now - dtStart).ToReadableString()}.", e);
- if (ProcessDoneCallback != null)
- ProcessDoneCallback(ItemId, PsStatusEnum.DoneFailed, e.Message);
- });
- }
- finally
- {
- IsRunning = false;
- }
- }
- /// <inheritdoc />
- public async void Stop()
- {
- if (!IsRunning)
- throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotRunning, GetType().Name, ItemId);
- //TODO: stops here
- }
- #endregion
- #region *** Protected Operations ***
- protected TValue? GetArgumentValue<TValue>(string name)
- {
- if (Arguments.TryGetValue(name, out var arg))
- return arg.GetTypedValue<TValue>();
- return default;
- }
- protected bool ContainsArgument(string name)
- {
- return Arguments.ContainsKey(name);
- }
- protected virtual void OnValidate()
- {
- if (!ContainsArgument(CS_ARG_RESULT_CODE) || !Arguments[CS_ARG_RESULT_CODE].IsOutput)
- throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotDefinedArgument, GetType().Name, ItemId, CS_ARG_RESULT_CODE);
- if (!ContainsArgument(CS_ARG_RESULT_TEXT) || !Arguments[CS_ARG_RESULT_TEXT].IsOutput)
- throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotDefinedArgument, GetType().Name, ItemId, CS_ARG_RESULT_TEXT);
- if (!ContainsArgument(CS_ARG_PROCESS_TIMEOUT) || Arguments[CS_ARG_PROCESS_TIMEOUT].IsOutput)
- throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotDefinedArgument, GetType().Name, ItemId, CS_ARG_PROCESS_TIMEOUT);
- }
- protected virtual async Task OnProcessError(Exception exception)
- {
- if (ProcessStdOutputCallback != null)
- ProcessStdOutputCallback(ItemId, exception.Message);
- if (ContainsArgument(CS_ARG_RESULT_TEXT))
- Arguments[CS_ARG_RESULT_TEXT].Value = exception.Message;
- }
- protected virtual async Task OnProcess()
- {
- //nothing to do
- }
- /// <inheritdoc />
- protected override void OnDisposing()
- {
- ProcessDoneCallback = null!;
- ProcessStdOutputCallback = null!;
- }
- #endregion
- }
- }
|