MP.TaskMan:

- Completato aggiunta progetto
- porting classi servizi/controlli/db a progetto
- compilazione OK
- manca gestione connString ottimizzata x il DB di origine CORRETTO (LAND/PROG/STATS)
This commit is contained in:
Samuele Locatelli
2024-10-26 11:02:26 +02:00
parent 880df2a180
commit ffec555e85
30 changed files with 797 additions and 421 deletions
+12 -2
View File
@@ -13,6 +13,10 @@ using static MP.Data.Objects.Enums;
namespace MP.Data.Controllers
{
/// <summary>
/// Controller specifico x LAND
/// FixMe ToDo !!! è ancora necessario con obj task estratti?!?!?
/// </summary>
public class MpLandController : IDisposable
{
#region Public Constructors
@@ -27,6 +31,7 @@ namespace MP.Data.Controllers
#region Public Methods
#if false
public DateTime CalcNextExe(TaskListModel taskRec)
{
DateTime dtNext = DateTime.Today;
@@ -77,7 +82,8 @@ namespace MP.Data.Controllers
Log.Error($"Eccezione in CalcNextExe{Environment.NewLine}{exc}");
}
return dtNext;
}
}
#endif
/// <summary>
/// Elenco da tabella Config
@@ -121,6 +127,7 @@ namespace MP.Data.Controllers
return dbResult;
}
#if false
/// <summary>
/// Chiamata esecuzione di un singolo task programmato
/// </summary>
@@ -195,6 +202,7 @@ namespace MP.Data.Controllers
return callRes;
}
#endif
/// <summary>
/// Annulla modifiche su una specifica entity (cancel update)
@@ -221,6 +229,7 @@ namespace MP.Data.Controllers
return answ;
}
#if false
/// <summary>
/// Ricerca task dato tipo + num max (desc)
/// </summary>
@@ -459,7 +468,8 @@ namespace MP.Data.Controllers
}
}
return done;
}
}
#endif
#endregion Public Methods
+9 -3
View File
@@ -63,6 +63,7 @@ namespace MP.Data.Controllers
return dbResult;
}
#if false
public DateTime CalcNextExe(TaskListModel taskRec)
{
DateTime dtNext = DateTime.Today;
@@ -113,7 +114,8 @@ namespace MP.Data.Controllers
Log.Error($"Eccezione in CalcNextExe{Environment.NewLine}{exc}");
}
return dtNext;
}
}
#endif
/// <summary>
/// Elenco tabella Articoli da filtro
@@ -140,6 +142,7 @@ namespace MP.Data.Controllers
{
}
#if false
/// <summary>
/// Chiamata esecuzione di un singolo task programmato
/// </summary>
@@ -212,7 +215,8 @@ namespace MP.Data.Controllers
}
}
return callRes;
}
}
#endif
/// <summary>
/// Elenco da tabella Macchine
@@ -477,6 +481,7 @@ namespace MP.Data.Controllers
return dbResult;
}
#if false
/// <summary>
/// Ricerca task dato tipo + num max (desc)
/// </summary>
@@ -663,7 +668,8 @@ namespace MP.Data.Controllers
}
}
return done;
}
}
#endif
#endregion Public Methods
+5
View File
@@ -7,10 +7,15 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="DatabaseModels\TaskExecModel.cs" />
<Compile Remove="DatabaseModels\TaskListModel.cs" />
<Compile Remove="DatabaseModels\TaskResultModel.cs" />
<Compile Remove="DatabaseModels\TurniPareto.cs" />
<Compile Remove="DatabaseModels\TurniParetoOdl.cs" />
<Compile Remove="MailKitEmailSender.cs" />
<Compile Remove="MailKitEmailSenderOptions.cs" />
<Compile Remove="Services\RestCallService.cs" />
<Compile Remove="Services\TaskService.cs" />
</ItemGroup>
<ItemGroup>
+3 -1
View File
@@ -99,9 +99,11 @@ namespace MP.Data
public virtual DbSet<ParetoFluxLogDTO> DbSetParetoFluxLog { get; set; }
#if false
public virtual DbSet<TaskListModel> DbSetTaskList { get; set; }
public virtual DbSet<TaskExecModel> DbSetTaskExe { get; set; }
public virtual DbSet<TaskResultModel> DbSetTaskResult { get; set; }
public virtual DbSet<TaskResultModel> DbSetTaskResult { get; set; }
#endif
#endregion Public Properties
+3 -1
View File
@@ -46,9 +46,11 @@ namespace MP.Data
public virtual DbSet<TurniOee> DbSetTurniOee { get; set; }
public virtual DbSet<UserActionLog> DbSetUserLog { get; set; }
public virtual DbSet<OdlEnergyModel> DbSetOdlEnergy { get; set; }
#if false
public virtual DbSet<TaskListModel> DbSetTaskList { get; set; }
public virtual DbSet<TaskExecModel> DbSetTaskExe { get; set; }
public virtual DbSet<TaskResultModel> DbSetTaskResult { get; set; }
public virtual DbSet<TaskResultModel> DbSetTaskResult { get; set; }
#endif
#endregion Public Properties
+3 -1
View File
@@ -250,6 +250,7 @@ namespace MP.Data.Objects
SS
}
#if false
//[JsonConverter(typeof(StringEnumConverter))]
public enum Task2ExeType
{
@@ -326,7 +327,8 @@ namespace MP.Data.Objects
/// Anni
/// </summary>
Year
}
}
#endif
/// <summary>
/// Elenco task ammessi (x IOB-WIN da eseguire...)
+4
View File
@@ -6,6 +6,10 @@ using System.Threading.Tasks;
namespace MP.Data.Services
{
/// <summary>
/// Gestione eventi reload da forzare via mesaggio
/// FixMe ToDo !!! è ancora necessario con obj task estratti?!?!?
/// </summary>
public class ReloadEventArgs : EventArgs
{
#region Public Constructors
+4
View File
@@ -13,6 +13,10 @@ using static System.Net.Mime.MediaTypeNames;
namespace MP.AppAuth.Services
{
/// <summary>
/// Servizio gestione chaimate REST xTaskMan
/// FixMe ToDo !!! è ancora necessario con obj task estratti?!?!?
/// </summary>
public class RestCallService
{
#region Public Constructors
-101
View File
@@ -1,101 +0,0 @@
@if (CurrRecord != null)
{
<hr />
<div class="row g-1">
<div class="col-md-2">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Name">
<label class="small">Nome Task</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<select class="form-select" @bind="@CurrRecord.TType">
@foreach (var option in Enum.GetValues(typeof(MP.Data.Objects.Enums.Task2ExeType)))
{
<option value="@option">
@option
</option>
}
</select>
<label class="small">Tipo Task</label>
</div>
</div>
<div class="col-md-8">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Descript">
<label class="small">Descrizione Task</label>
</div>
</div>
@* <div class="col-md-2">
<div class="form-floating">
<select class="form-select" @bind="@CurrRecord.Freq">
@foreach (var option in Enum.GetValues(typeof(MP.Data.Objects.Enums.TaskFreqType)))
{
<option value="@option">
@option
</option>
}
</select>
<label class="small">Frequenza</label>
</div>
</div>
<div class="col-md-1">
<div class="form-floating">
<input type="number" class="form-control" @bind="@CurrRecord.Cad">
<label class="small">Cadenza</label>
</div>
</div> *@
</div>
<div class="row g-1">
<div class="col-md-4">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Command">
<label class="small">Comando</label>
</div>
</div>
<div class="col-md-8">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Args">
<label class="small">Parametri</label>
</div>
</div>
</div>
<div class="row g-1">
<div class="col-md-3">
<div class="form-floating">
<input type="number" class="form-control" @bind="@CurrRecord.Ordinal">
<label class="small">Ordine Esecuzione</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<input type="datetime-local" class="form-control" @bind="@CurrRecord.DtNextExec">
<label class="small">Prossima Esecuzione</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<select class="form-select" @bind="@CurrRecord.Freq">
@foreach (var option in Enum.GetValues(typeof(MP.Data.Objects.Enums.TaskFreqType)))
{
<option value="@option">
@option
</option>
}
</select>
<label class="small">Frequenza</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<input type="number" class="form-control" @bind="@CurrRecord.Cad">
<label class="small">Cadenza</label>
</div>
</div>
<div class="col-md-2 pt-2">
<button class="btn btn-lg w-100 btn-success" @onclick="()=>doSave()" title="Save"><i class="far fa-save"></i> Save</button>
</div>
</div>
}
-47
View File
@@ -1,47 +0,0 @@
using Microsoft.AspNetCore.Components;
using MP.Data.DatabaseModels;
using MP.Data.Services;
using System.Threading.Tasks;
namespace MP.Land.Components
{
public partial class TaskEdit
{
#region Public Properties
[Parameter]
public TaskListModel? CurrRecord { get; set; } = null;
[Parameter]
public EventCallback<bool> EC_update { get; set; }
#endregion Public Properties
#region Protected Properties
[Inject]
protected TaskService TService { get; set; }
#endregion Protected Properties
#region Protected Methods
protected async Task doCancel()
{
await EC_update.InvokeAsync(false);
}
protected async Task doSave()
{
bool fatto = false;
await Task.Delay(1);
if (CurrRecord != null)
{
fatto = await TService.TaskListUpsert(CurrRecord);
}
await EC_update.InvokeAsync(fatto);
}
#endregion Protected Methods
}
}
-100
View File
@@ -1,100 +0,0 @@

<div class="card text-bg-light shadow">
<div class="card-header table-primary p-1">
<div class="d-flex justify-content-between">
<div class="ps-2 d-flex">
<div class="px-0">
<b class="fs-4">History</b>
</div>
<div class="px-2">
@if (CurrRecord != null)
{
<div title="@CurrRecord.Command">@TextReduce(CurrRecord.Command, 40)</div>
<div class="small text-break" title="@CurrRecord.Args">@TextReduce(CurrRecord.Args, 60)</div>
}
</div>
</div>
<div class="px-2">
<div class="input-group">
<select class="form-select" @bind="@ShowErrorMode">
<option value="0">--- ALL ---</option>
<option value="1">Solo Errori</option>
<option value="2">Solo OK</option>
</select>
</div>
</div>
</div>
</div>
<div class="card-body py-0 px-1">
@if (ListRecords == null)
{
<LoadingData></LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-warning text-center display-6">Nessun record trovato</div>
}
else
{
<div class="row">
<div class="col-12">
<table class="table table-sm table-striped">
<thead>
<tr>
<th>#</th>
<th>Inizio</th>
<th>Fine</th>
<th class="text-right">Esito</th>
</tr>
</thead>
<tbody>
@foreach (var record in ListRecords)
{
<tr>
<td>
@record.TaskExecId
</td>
<td>
@($"{record.DtStart:HH:mm:ss.fff}")
<div class="small">@($"{record.DtStart:yyyy-MM.dd ddd}")</div>
</td>
<td>
@($"{record.DtEnd:HH:mm:ss.fff}")
<div class="small">@($"{record.DtEnd:yyyy-MM.dd ddd}")</div>
</td>
<td class="text-right">
<div class="d-flex justify-content-between">
<div class="px-0">
@if (@record.IsError)
{
<i class="far fa-thumbs-down text-danger"></i>
}
else
{
<i class="far fa-thumbs-up text-success"></i>
}
</div>
<div class="px-0">
<b>@($"{record.Duration:N3}")</b> <sub>sec</sub>
</div>
</div>
</td>
</tr>
<tr>
<td colspan="4">
<div class="p-1 small text-truncate alert @alCss(record) mb-0" style="max-width: 60rem;">
<pre>@record.Result</pre>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}
</div>
<div class="card-footer py-1">
<DataPager PageSize="numRecord" currPage="currPage" numRecordChanged="ForceReload" numPageChanged="ForceReloadPage" exportEnabled="false" totalCount="totalCount" showLoading="isLoading" />
</div>
</div>
-136
View File
@@ -1,136 +0,0 @@
using MailKit;
using Microsoft.AspNetCore.Components;
using MongoDB.Bson;
using MP.Data.DatabaseModels;
using MP.Data.Services;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MP.Land.Components
{
public partial class TaskExeList
{
#region Public Properties
[Parameter]
public TaskListModel? CurrRecord { get; set; } = null;
#endregion Public Properties
#region Protected Fields
protected bool isLoading = false;
#endregion Protected Fields
#region Protected Properties
[Inject]
protected NavigationManager NavManager { get; set; }
/// <summary>
/// Show error mode: 0 = tutti 1 = solo errori 2 = solo ok
/// </summary>
protected int ShowErrorMode
{
get => showErrorMode;
set
{
if (showErrorMode != value)
{
showErrorMode = value;
var pUpd = Task.Run(async () => await ReloadData());
pUpd.Wait();
}
}
}
protected int totalCount { get; set; } = 0;
[Inject]
protected TaskService TService { get; set; }
#endregion Protected Properties
#region Protected Methods
protected string alCss(TaskExecModel TaskRec)
{
return TaskRec.IsError ? "alert-danger" : "alert-success";
}
protected async Task ForceReload(int newNum)
{
numRecord = newNum;
await ReloadData();
}
protected async Task ForceReloadPage(int newNum)
{
currPage = newNum;
await ReloadData();
}
protected override async Task OnInitializedAsync()
{
await ReloadData();
}
protected string TextReduce(string textOriginal, int maxChar)
{
string answ = textOriginal;
if (answ.Length > maxChar)
{
answ = $"{textOriginal.Substring(0, maxChar / 2)} ... {textOriginal.Substring(answ.Length - maxChar / 2)}";
}
return answ;
}
#endregion Protected Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private List<TaskExecModel> ListRecords;
private List<TaskExecModel> SearchRecords;
#endregion Private Fields
#region Private Properties
private int currPage { get; set; } = 1;
private int numRecord { get; set; } = 10;
private int showErrorMode { get; set; } = 0;
#endregion Private Properties
#region Private Methods
private async Task ReloadData()
{
SearchRecords = await TService.TaskExecGetFilt(CurrRecord.TaskId, 1000, "");
// se non tutti filtro...
if (ShowErrorMode != 0)
{
if (ShowErrorMode == 1)
{
SearchRecords = SearchRecords.FindAll(x => x.IsError);
}
else if (ShowErrorMode == 2)
{
SearchRecords = SearchRecords.FindAll(x => !x.IsError);
}
}
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
}
#endregion Private Methods
}
}
+8 -1
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Land</RootNamespace>
<Version>6.16.2410.2519</Version>
<Version>6.16.2410.2611</Version>
<Configurations>Debug;Release;Debug_LiManDebug</Configurations>
</PropertyGroup>
@@ -11,9 +11,12 @@
<Compile Remove="Components\ArchiveStatus.razor.cs" />
<Compile Remove="Components\FileEditor.razor.cs" />
<Compile Remove="Components\TagSearch.razor.cs" />
<Compile Remove="Components\TaskEdit.razor.cs" />
<Compile Remove="Components\TaskExeList.razor.cs" />
<Compile Remove="Data\FileArchDataService.cs" />
<Compile Remove="Pages\Archive.razor.cs" />
<Compile Remove="Pages\Setup.razor.cs" />
<Compile Remove="Pages\UpdateManager.razor.cs" />
</ItemGroup>
<ItemGroup>
@@ -21,8 +24,11 @@
<Content Remove="Components\CodArtSelector.razor" />
<Content Remove="Components\FileEditor.razor" />
<Content Remove="Components\TagSearch.razor" />
<Content Remove="Components\TaskEdit.razor" />
<Content Remove="Components\TaskExeList.razor" />
<Content Remove="Pages\Archive.razor" />
<Content Remove="Pages\Setup.razor" />
<Content Remove="Pages\UpdateManager.razor" />
</ItemGroup>
<ItemGroup>
@@ -63,6 +69,7 @@
<ItemGroup>
<ProjectReference Include="..\MP.AppAuth\MP.AppAuth.csproj" />
<ProjectReference Include="..\MP.Data\MP.Data.csproj" />
<ProjectReference Include="..\MP.TaskMan\MP.TaskMan.csproj" />
</ItemGroup>
<ItemGroup>
+3 -3
View File
@@ -10,7 +10,7 @@
</div>
<div class="px-2">
<div class="input-group">
@if (TypeSel != MP.Data.Objects.Enums.Task2ExeType.ND)
@if (TypeSel != MP.TaskMan.Objects.Enums.Task2ExeType.ND)
{
@if (currRecord == null)
{
@@ -26,7 +26,7 @@
<button class="btn btn-outline-secondary">Sel &rarr;</button>
}
<select class="form-select" @bind="@TypeSel">
@foreach (var option in Enum.GetValues(typeof(MP.Data.Objects.Enums.Task2ExeType)))
@foreach (var option in Enum.GetValues(typeof(MP.TaskMan.Objects.Enums.Task2ExeType)))
{
<option value="@option">
@option
@@ -185,7 +185,7 @@
@if (detRecord != null && !isLoading)
{
<div class="col-6">
<TaskExeList CurrRecord="detRecord"></TaskExeList>
<TaskExeList CurrRecord="@detRecord"></TaskExeList>
</div>
}
</div>
+3 -2
View File
@@ -1,8 +1,8 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MP.Data.DatabaseModels;
using MP.TaskMan.Models;
using MP.Land.Data;
using static MP.Data.Objects.Enums;
using static MP.TaskMan.Objects.Enums;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@@ -10,6 +10,7 @@ using System;
using System.Linq;
using MP.Data.Services;
using DnsClient.Protocol;
using MP.TaskMan.Services;
namespace MP.Land.Pages
{
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo Tablet MAPO - DotNet6</i>
<h4>Versione: 6.16.2410.2519</h4>
<h4>Versione: 6.16.2410.2611</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.16.2410.2519
6.16.2410.2611
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.16.2410.2519</version>
<version>6.16.2410.2611</version>
<url>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/MP.Land.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+1 -1
View File
@@ -45,7 +45,7 @@ namespace MP.Land.Shared
protected override async Task OnInitializedAsync()
{
await ReloadData();
}
}
protected List<PermessiModel> UserPerm { get; set; } = new List<PermessiModel>();
protected List<UserDirittiModel> UserRight { get; set; } = new List<UserDirittiModel>();
+1
View File
@@ -13,6 +13,7 @@ using Microsoft.Extensions.Hosting;
using MP.AppAuth.Services;
using MP.Data.Services;
using MP.Land.Data;
using MP.TaskMan.Services;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
+1
View File
@@ -9,6 +9,7 @@
@using MP.Land
@using MP.Land.Components
@using MP.Land.Shared
@using MP.TaskMan
@using EgwCoreLib
@using EgwCoreLib.Razor
@using EgwCoreLib.Razor.Data
+438
View File
@@ -0,0 +1,438 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using MP.TaskMan.Models;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static MP.TaskMan.Objects.Enums;
namespace MP.TaskMan.Controllers
{
public class MpTaskController: IDisposable
{
public MpTaskController(IConfiguration configuration)
{
_configuration = configuration;
Log.Info("Avviato MpTaskController");
}
private static IConfiguration _configuration;
private static Logger Log = LogManager.GetCurrentClassLogger();
public DateTime CalcNextExe(TaskListModel taskRec)
{
DateTime dtNext = DateTime.Today;
try
{
// calcolo next exec da tipo...
switch (taskRec.Freq)
{
case TaskFreqType.ND:
dtNext = taskRec.DtLastExec.AddDays(taskRec.Cad);
break;
case TaskFreqType.Sec:
dtNext = taskRec.DtLastExec.AddSeconds(taskRec.Cad);
break;
case TaskFreqType.Min:
dtNext = taskRec.DtLastExec.AddMinutes(taskRec.Cad);
break;
case TaskFreqType.Hour:
dtNext = taskRec.DtLastExec.AddHours(taskRec.Cad);
break;
case TaskFreqType.Day:
dtNext = taskRec.DtLastExec.AddDays(taskRec.Cad);
break;
case TaskFreqType.Week:
dtNext = taskRec.DtLastExec.AddDays(7 * taskRec.Cad);
break;
case TaskFreqType.Month:
dtNext = taskRec.DtLastExec.AddMonths(taskRec.Cad);
break;
case TaskFreqType.Year:
dtNext = taskRec.DtLastExec.AddYears(taskRec.Cad);
break;
default:
dtNext = taskRec.DtLastExec.AddDays(taskRec.Cad);
break;
}
}
catch (Exception exc)
{
Log.Error($"Eccezione in CalcNextExe{Environment.NewLine}{exc}");
}
return dtNext;
}
/// <summary>
/// Elenco da tabella Config
/// </summary>
/// <returns></returns>
public List<ConfigModel> ConfigGetAll()
{
List<ConfigModel> dbResult = new List<ConfigModel>();
using (var dbCtx = new TaskContext(_configuration))
{
dbResult = dbCtx
.DbSetConfig
.AsNoTracking()
.OrderBy(x => x.Chiave)
.ToList();
}
return dbResult;
}
public void Dispose()
{
_configuration = null;
}
/// <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 TaskContext(_configuration))
{
// imposto timeout a 5 min
//var currTimeout = dbCtx.Database.GetCommandTimeout();
dbCtx.Database.SetCommandTimeout(TimeSpan.FromMinutes(5));
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;
callRes = dbCtx
.DbSetTaskResult
.FromSqlRaw($"EXEC {sqlCommand} {rawParams}")
.AsNoTracking()
.AsEnumerable()
.FirstOrDefault();
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)
{
Log.Error($"Eccezione in ExecuteSqlCommand{Environment.NewLine}{exc}");
}
}
return callRes;
}
/// <summary>
/// Annulla modifiche su una specifica entity (cancel update)
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool RollBackEntity(object item)
{
bool answ = false;
using (var dbCtx = new TaskContext(_configuration))
{
try
{
if (dbCtx.Entry(item).State == Microsoft.EntityFrameworkCore.EntityState.Deleted || dbCtx.Entry(item).State == Microsoft.EntityFrameworkCore.EntityState.Modified)
{
dbCtx.Entry(item).Reload();
}
}
catch (Exception exc)
{
Log.Error($"Eccezione in rollBackEntity{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Ricerca task dato tipo + num max (desc)
/// </summary>
/// <param name="TaskId">TaskId da cui deriva</param>
/// <returns></returns>
public List<TaskExecModel> TaskExecGetFilt(int TaskId, int maxRec)
{
List<TaskExecModel> dbResult = new List<TaskExecModel>();
using (var dbCtx = new TaskContext(_configuration))
{
dbResult = dbCtx
.DbSetTaskExe
.Include(x => x.TaskListNav)
.Where(x => (x.TaskId == TaskId))
.OrderByDescending(x => x.DtStart)
.Take(maxRec)
.ToList();
}
return dbResult;
}
/// <summary>
/// Upsert record TaskExec
/// </summary>
/// <param name="rec2upd">Record da aggiornare/inserire</param>
/// <returns></returns>
public bool TaskExecUpsert(TaskExecModel rec2upd)
{
bool done = false;
using (var dbCtx = new TaskContext(_configuration))
{
try
{
var currData = dbCtx
.DbSetTaskExe
.Where(x => x.TaskExecId == rec2upd.TaskExecId)
.FirstOrDefault();
if (currData != null)
{
currData.TaskId = rec2upd.TaskId;
currData.DtStart = rec2upd.DtStart;
currData.DtEnd = rec2upd.DtEnd;
currData.IsError = rec2upd.IsError;
currData.Result = rec2upd.Result;
dbCtx.Entry(currData).State = EntityState.Modified;
}
else
{
dbCtx
.DbSetTaskExe
.Add(rec2upd);
}
dbCtx.SaveChanges();
done = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione in TaskExecUpsert{Environment.NewLine}{exc}");
}
}
return done;
}
/// <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 TaskContext(_configuration))
{
dbResult = dbCtx
.DbSetTaskList
.Where(x => (TType == Task2ExeType.ND || x.TType == TType))
.OrderBy(x => x.Ordinal)
.ToList();
}
return dbResult;
}
/// <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 TaskContext(_configuration))
{
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>
/// Update ordinamento task
/// </summary>
/// <param name="rec2upd">Record da spostare x priorità</param>
/// <returns></returns>
public bool TaskListMove(TaskListModel rec2upd, bool moveUp)
{
bool done = false;
using (var dbCtx = new TaskContext(_configuration))
{
try
{
var currData = dbCtx
.DbSetTaskList
.Where(x => x.TaskId == rec2upd.TaskId)
.FirstOrDefault();
if (currData != null)
{
int actOrdinal = currData.Ordinal;
TaskListModel? otherRec = null;
// cerco, secondo richiesta, precedente o successivo
if (moveUp)
{
otherRec = dbCtx
.DbSetTaskList
.Where(x => x.Ordinal < currData.Ordinal)
.OrderByDescending(x => x.Ordinal)
.FirstOrDefault();
}
else
{
otherRec = dbCtx
.DbSetTaskList
.Where(x => x.Ordinal > currData.Ordinal)
.OrderBy(x => x.Ordinal)
.FirstOrDefault();
}
// inverto ordinale SE ho record
if (otherRec != null)
{
currData.Ordinal = otherRec.Ordinal;
otherRec.Ordinal = actOrdinal;
dbCtx.Entry(currData).State = EntityState.Modified;
dbCtx.Entry(otherRec).State = EntityState.Modified;
}
}
//salvo
dbCtx.SaveChanges();
done = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione in TaskListUpsert{Environment.NewLine}{exc}");
}
}
return done;
}
/// <summary>
/// Upsert record TaskList
/// </summary>
/// <param name="rec2upd">Record da aggiornare/inserire</param>
/// <returns></returns>
public bool TaskListUpsert(TaskListModel rec2upd)
{
bool done = false;
using (var dbCtx = new TaskContext(_configuration))
{
try
{
var currData = dbCtx
.DbSetTaskList
.Where(x => x.TaskId == rec2upd.TaskId && rec2upd.TaskId > 0)
.FirstOrDefault();
if (currData != null)
{
currData.Ordinal = rec2upd.Ordinal;
currData.Name = rec2upd.Name;
currData.Descript = rec2upd.Descript;
currData.Command = rec2upd.Command;
currData.Args = rec2upd.Args;
currData.Freq = rec2upd.Freq;
currData.Cad = rec2upd.Cad;
currData.DtLastExec = rec2upd.DtLastExec;
currData.DtNextExec = rec2upd.DtNextExec;
currData.LastDuration = rec2upd.LastDuration;
currData.LastResult = rec2upd.LastResult;
dbCtx.Entry(currData).State = EntityState.Modified;
}
else
{
dbCtx
.DbSetTaskList
.Add(rec2upd);
}
dbCtx.SaveChanges();
done = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione in TaskListUpsert{Environment.NewLine}{exc}");
}
}
return done;
}
}
}
+11 -9
View File
@@ -6,14 +6,6 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Compile Remove="TaskExeList.razor.cs" />
</ItemGroup>
<ItemGroup>
<Content Remove="TaskExeList.razor" />
</ItemGroup>
<ItemGroup>
<SupportedPlatform Include="browser" />
@@ -21,6 +13,13 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.33" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.33" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.33" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.33" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.3.4" />
@@ -30,7 +29,10 @@
<ItemGroup>
<Folder Include="Migrations\" />
<Folder Include="Controllers\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Egw.Core\Egw.Core.csproj" />
</ItemGroup>
</Project>
+22
View File
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.TaskMan.Models
{
[Table("Config")]
public partial class ConfigModel
{
public string Chiave { get; set; }
public string Valore { get; set; }
/// <summary>
/// Valore di default/riferimento per la variabile
/// </summary>
public string ValoreStd { get; set; }
public string Note { get; set; }
}
}
+26
View File
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.TaskMan.Services
{
public class ReloadEventArgs : EventArgs
{
#region Public Constructors
public ReloadEventArgs(string messaggio)
{
this.ReloadMessage = messaggio;
}
#endregion Public Constructors
#region Public Properties
public string ReloadMessage { get; set; } = "";
#endregion Public Properties
}
}
+111
View File
@@ -0,0 +1,111 @@
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using RestSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using static System.Net.Mime.MediaTypeNames;
namespace MP.TaskMan.Services
{
public class RestCallService
{
#region Public Constructors
/// <summary>
/// Init classe
/// </summary>
/// <param name="configuration"></param>
public RestCallService(IConfiguration configuration)
{
_configuration = configuration;
// verifico la url base
apiUrl = _configuration.GetValue<string>("ServerConf:Prog.ApiUrl");
// fix opzioni base del RestClient
restOptStd = new RestClientOptions
{
Timeout = TimeSpan.FromSeconds(60),
BaseUrl = new Uri(apiUrl)
};
}
private string apiUrl = "";
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Stato server da chiamare x verifiche preliminari stato API REST
/// </summary>
/// <param name="ApiUrl"></param>
/// <returns></returns>
public async Task<string> CheckServer()
{
string answ = "ND";
// cerco online
using (RestClient client = new RestClient(restOptStd))
{
var request = new RestRequest($"api/health", Method.Get);
var response = await client.GetAsync(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
if (response.Content != null)
{
answ = response.Content.Replace("\"", "");
}
}
}
return answ;
}
/// <summary>
/// Effettua una generica chiamata ApiRest
/// </summary>
/// <param name="ApiUrl">URL Api di base</param>
/// <param name="ApiRequest">Richiesta completa</param>
/// <returns></returns>
public async Task<RestResponse> CallRestGet(string ApiUrl, string ApiRequest)
{
RestResponse response;
// cerco online
using (RestClient client = new RestClient(ApiUrl))
{
var request = new RestRequest(ApiRequest, Method.Get);
response = await client.GetAsync(request);
}
return response;
}
#endregion Public Methods
#region Private Fields
private static IConfiguration? _configuration;
/// <summary>
/// Classe logger
/// </summary>
private static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
#region Private Properties
/// <summary>
/// Conf client RestSharp standard:
/// - base URI al sito
/// - timeout 1 min
/// </summary>
private RestClientOptions restOptStd { get; set; } = new RestClientOptions();
#endregion Private Properties
}
}
+4 -5
View File
@@ -1,8 +1,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using MP.AppAuth.Services;
using MP.TaskMan.Controllers;
using MP.TaskMan.DatabaseModels;
using MP.TaskMan.Models;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
@@ -41,8 +40,8 @@ namespace MP.TaskMan.Services
else
{
StringBuilder sb = new StringBuilder();
MLController = new MpLandController(configuration);
sb.AppendLine($"TaskService | MpLandController OK");
MLController = new MpTaskController(configuration);
sb.AppendLine($"TaskService | MpTaskController OK");
Log.Info(sb.ToString());
// sistemo i parametri x redHas...
CodModulo = _configuration.GetValue<string>("ServerConf:CodModulo");
@@ -330,7 +329,7 @@ namespace MP.TaskMan.Services
#region Private Properties
private static MpLandController MLController { get; set; } = null!;
private static MpTaskController MLController { get; set; } = null!;
private RestCallService RCallService { get; set; } = null!;
#endregion Private Properties
+116
View File
@@ -0,0 +1,116 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Configuration;
using MP.TaskMan.Models;
using NLog;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.TaskMan
{
public partial class TaskContext : DbContext
{
#region Private Fields
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private IConfiguration _configuration;
#endregion Private Fields
#region Public Constructors
public TaskContext(IConfiguration configuration)
{
_configuration = configuration;
}
public TaskContext(DbContextOptions<TaskContext> options) : base(options)
{
}
#endregion Public Constructors
#region Public Properties
public virtual DbSet<ConfigModel> DbSetConfig { get; set; }
public virtual DbSet<TaskListModel> DbSetTaskList { get; set; }
public virtual DbSet<TaskExecModel> DbSetTaskExe { get; set; }
public virtual DbSet<TaskResultModel> DbSetTaskResult { get; set; }
#endregion Public Properties
#region Private Methods
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
#endregion Private Methods
#region Protected Methods
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string connString = _configuration.GetConnectionString("MP.TaskMan");
if (string.IsNullOrEmpty(connString))
{
connString = _configuration.GetConnectionString("MP.All");
}
if (string.IsNullOrEmpty(connString))
{
connString = _configuration.GetConnectionString("MP.Data");
}
if (string.IsNullOrEmpty(connString))
{
connString = _configuration.GetConnectionString("MP.Mon");
}
if (string.IsNullOrEmpty(connString))
{
connString = _configuration.GetConnectionString("MP.STATS");
}
if (string.IsNullOrEmpty(connString))
{
connString = _configuration.GetConnectionString("MP.Land");
}
optionsBuilder.UseSqlServer(connString);
//optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro;Trusted_Connection=True;");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
modelBuilder.Entity<ConfigModel>(entity =>
{
entity.HasKey(e => e.Chiave);
entity.ToTable("Config");
entity.Property(e => e.Chiave)
.HasMaxLength(50)
.HasColumnName("chiave");
entity.Property(e => e.Note).HasColumnName("note");
entity.Property(e => e.Valore).HasColumnName("valore");
entity.Property(e => e.ValoreStd)
.HasColumnName("valoreStd")
.HasComment("Valore di default/riferimento per la variabile");
});
OnModelCreatingPartial(modelBuilder);
}
#endregion Protected Methods
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using MP.TaskMan.Models;
using MP.TaskMan.Services;
namespace MP.TaskMan
{
@@ -18,7 +19,7 @@ namespace MP.TaskMan
#region Protected Properties
[Inject]
protected TaskService TService { get; set; }
protected TaskService TService { get; set; } = null!;
#endregion Protected Properties
+4 -4
View File
@@ -1,6 +1,6 @@
using MailKit;
using Microsoft.AspNetCore.Components;
using MongoDB.Bson;
using MP.TaskMan.Models;
using MP.TaskMan.Services;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
@@ -29,7 +29,7 @@ namespace MP.TaskMan
#region Protected Properties
[Inject]
protected NavigationManager NavManager { get; set; }
protected NavigationManager NavManager { get; set; } = null!;
/// <summary>
/// Show error mode: 0 = tutti 1 = solo errori 2 = solo ok
@@ -51,7 +51,7 @@ namespace MP.TaskMan
protected int totalCount { get; set; } = 0;
[Inject]
protected TaskService TService { get; set; }
protected TaskService TService { get; set; } = null!;
#endregion Protected Properties