Files
maat/Maat.Data/Controllers/MsSqlController.cs
T
Samuele Locatelli 0cbffd8613 Modifica gestione task
- solo task attivi
- esce da gruppo se fallisce uno step
2025-07-21 12:49:38 +02:00

265 lines
10 KiB
C#

using Maat.Data.DbModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Maat.Core.Enums;
namespace Maat.Data.Controllers
{
public class MsSqlController : IDisposable
{
#region Public Constructors
/// <summary>
/// Avvio Controller ThreadRun x DB
/// </summary>
/// <param name="threadName">nome del thread di esecuzione</param>
/// <param name="cString">stringa di connessione da impiegare</param>
/// <param name="cmdExecTOut">timeout esecuzione comandi (minuti)</param>
public MsSqlController(string threadName, string cString, int cmdExecTOut)
{
tName = threadName;
connString = cString;
cmdTimeout = cmdExecTOut;
Log.Info($"{tName} | Avviata classe MsSqlController");
}
#endregion Public Constructors
#region Public Methods
public DateTime CalcNextExe(TaskListModel taskRec)
{
DateTime dtNext = DateTime.Today;
DateTime adesso = DateTime.Now;
int maxIter = 1000;
try
{
// prendo come partenza la DATA di fine a cui aggiungo l'ora/minuti schedulata precedentemente
TimeSpan oraSched = taskRec.DtNextExec.Subtract(taskRec.DtNextExec.Date);
DateTime baseDT = taskRec.DtLastExec.Date.Add(oraSched);
// calcolo next exec da tipo... con ciclo fino a quando supero dataora attuale...
while (dtNext < adesso && maxIter > 0)
{
switch (taskRec.Freq)
{
case TaskFreqType.ND:
dtNext = baseDT.AddDays(taskRec.Cad);
break;
case TaskFreqType.Sec:
dtNext = baseDT.AddSeconds(taskRec.Cad);
break;
case TaskFreqType.Min:
dtNext = baseDT.AddMinutes(taskRec.Cad);
break;
case TaskFreqType.Hour:
dtNext = baseDT.AddHours(taskRec.Cad);
break;
case TaskFreqType.Day:
dtNext = baseDT.AddDays(taskRec.Cad);
break;
case TaskFreqType.Week:
dtNext = baseDT.AddDays(7 * taskRec.Cad);
break;
case TaskFreqType.Month:
dtNext = baseDT.AddMonths(taskRec.Cad);
break;
case TaskFreqType.Year:
dtNext = baseDT.AddYears(taskRec.Cad);
break;
default:
dtNext = baseDT.AddDays(taskRec.Cad);
break;
}
baseDT = dtNext;
maxIter--;
}
}
catch (Exception exc)
{
Log.Error($"Eccezione in CalcNextExe{Environment.NewLine}{exc}");
}
return dtNext;
}
public void Dispose()
{
}
/// <summary>
/// Chiamata esecuzione di un singolo task programmato
/// </summary>
/// <param name="TaskId"></param>
/// <param name="SchedNext">Se true rischedula successiva chiamata</param>
/// <returns></returns>
public TaskResultModel ExecuteSqlTask(int TaskId, bool SchedNext)
{
TaskResultModel callRes = new TaskResultModel();
using (var dbCtx = new TaskRunContext(connString))
{
// imposto timeout a 5 min
dbCtx.Database.SetCommandTimeout(TimeSpan.FromMinutes(cmdTimeout));
string sqlCall = "";
try
{
DateTime dtStart = DateTime.Now;
// recupero i dati da richiamare...
var currRec = dbCtx
.DbSetTaskList
.Where(x => x.TaskId == TaskId)
.FirstOrDefault();
if (currRec != null)
{
// recupero comando
string sqlCommand = currRec.Command;
string rawParams = currRec.Args;
// salvo la call x eventuale log errore
sqlCall = $"EXEC {sqlCommand} {rawParams}";
var rawData = dbCtx
.DbSetTaskResult
.FromSqlRaw($"EXEC {sqlCommand} {rawParams}")
.ToList();
callRes = rawData.FirstOrDefault() ?? new TaskResultModel();
DateTime dtEnd = DateTime.Now;
// preparo record esecuzione...
TaskExecModel resRec = new TaskExecModel()
{
TaskId = TaskId,
DtStart = dtStart,
DtEnd = dtEnd,
IsError = callRes.ExecResult < 0,
Result = callRes.TextResult
};
dbCtx
.DbSetTaskExe
.Add(resRec);
// aggiorno record chiamata...
currRec.DtLastExec = dtStart;
currRec.LastResult = resRec.Result;
currRec.LastIsError = resRec.IsError;
currRec.LastDuration = dtEnd.Subtract(dtStart).TotalSeconds;
// solo se richiesto rischedulazione ricalcola chiamata
if (SchedNext)
{
// calcolo prossima esecuzione...
currRec.DtNextExec = CalcNextExe(currRec);
}
// segno modificato
dbCtx.Entry(currRec).State = EntityState.Modified;
// salvo modifiche!
dbCtx.SaveChanges();
}
}
catch (Exception exc)
{
string excMsg = $"{tName} | Eccezione in ExecuteSqlTask{Environment.NewLine}Call eseguita:{Environment.NewLine}{sqlCall}{Environment.NewLine}------- Stack Eccezione -------{Environment.NewLine}{exc}";
callRes.ExecResult = -1;
callRes.TextResult = excMsg;
Log.Error(excMsg);
}
}
return callRes;
}
/// <summary>
/// Esegue registrazione di un Task generico (NON SQL)
/// </summary>
/// <param name="TaskId"></param>
/// <param name="SchedNext">Se true rischedula successiva chiamata</param>
/// <param name="ResRec">Record esecuzione task esterno</param>
/// <returns></returns>
public TaskResultModel TaskExecSaveExecuted(int TaskId, bool SchedNext, TaskExecModel ResRec)
{
TaskResultModel callRes = new TaskResultModel();
using (var dbCtx = new TaskRunContext(connString))
{
try
{
// recupero i dati da richiamare...
var currRec = dbCtx
.DbSetTaskList
.Where(x => x.TaskId == TaskId)
.FirstOrDefault();
if (currRec != null)
{
// registro task ricevuto
dbCtx
.DbSetTaskExe
.Add(ResRec);
// aggiorno record chiamata...
currRec.DtLastExec = ResRec.DtStart;
currRec.LastResult = ResRec.Result;
currRec.LastIsError = ResRec.IsError;
currRec.LastDuration = ResRec.DtEnd.Subtract(ResRec.DtStart).TotalSeconds;
// solo se richiesto rischedulazione ricalcola chiamata
if (SchedNext)
{
// calcolo prossima esecuzione...
currRec.DtNextExec = CalcNextExe(currRec);
}
// segno modificato
dbCtx.Entry(currRec).State = EntityState.Modified;
// salvo modifiche!
dbCtx.SaveChanges();
}
}
catch (Exception exc)
{
Log.Error($"Eccezione in TaskExecSaveExecuted{Environment.NewLine}{exc}");
}
}
return callRes;
}
/// <summary>
/// Ricerca task dato tipo e
/// </summary>
/// <param name="TType"></param>
/// <returns></returns>
public List<TaskListModel> TaskListGetAll(Task2ExeType TType)
{
List<TaskListModel> dbResult = new List<TaskListModel>();
using (var dbCtx = new TaskRunContext(connString))
{
dbResult = dbCtx
.DbSetTaskList
.Where(x => (TType == Task2ExeType.ND || x.TType == TType))
.OrderBy(x => x.Ordinal)
.ToList();
}
return dbResult;
}
#endregion Public Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private string connString = "";
private string tName = "";
private int cmdTimeout = 0;
#endregion Private Fields
}
}