- continuo modifiche x gestione task eseguiti
This commit is contained in:
Samuele Locatelli
2024-10-25 16:52:45 +02:00
parent e4fd85c9cb
commit d3c95a9fe1
23 changed files with 341 additions and 50 deletions
+2 -2
View File
@@ -24,8 +24,8 @@ Global
{D949AB45-9B65-4594-A97E-182BC3831707}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D949AB45-9B65-4594-A97E-182BC3831707}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D949AB45-9B65-4594-A97E-182BC3831707}.Release|Any CPU.Build.0 = Release|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Debug_LiManDebug|Any CPU.ActiveCfg = Debug|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Debug_LiManDebug|Any CPU.Build.0 = Debug|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Debug_LiManDebug|Any CPU.ActiveCfg = Debug_LiManDebug|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Debug_LiManDebug|Any CPU.Build.0 = Debug_LiManDebug|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8B1E617-87BC-4638-A8B6-04EEBA3B8F47}.Release|Any CPU.ActiveCfg = Release|Any CPU
+1 -1
View File
@@ -10,7 +10,7 @@ namespace MP.AppAuth
{
#region Private Fields
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private static Logger Log = LogManager.GetCurrentClassLogger();
private IConfiguration _configuration;
+4
View File
@@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Configurations>Debug;Release;Debug_LiManDebug</Configurations>
</PropertyGroup>
<ItemGroup>
@@ -16,7 +17,10 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.3.3" />
<PackageReference Include="RestSharp" Version="112.0.0" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
</ItemGroup>
<ItemGroup>
@@ -1,7 +1,4 @@
using Egw.Core;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using MP.AppAuth.DTO;
using MP.AppAuth.Models;
using Newtonsoft.Json;
@@ -11,12 +8,12 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using static Egw.Core.LiManObj;
using static System.Net.Mime.MediaTypeNames;
namespace MP.Land.Data
namespace MP.AppAuth.Services
{
public class SyncService
{
@@ -31,15 +28,17 @@ namespace MP.Land.Data
_configuration = configuration;
// sistemo conf secondo Target compilazione
#if DEBUG_LIMANDEBUG
apiUrl = "https://localhost:5003/";
#else
apiUrl = "https://liman.egalware.com/ELM.API/";
#endif
// fix opzioni base del RestClient
restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60), BaseUrl = new Uri(apiUrl) };
restOptStd = new RestClientOptions
{
Timeout = TimeSpan.FromSeconds(60),
BaseUrl = new Uri(apiUrl)
};
}
#endregion Public Constructors
@@ -82,7 +81,7 @@ namespace MP.Land.Data
answ = response.Content.Replace("\"", "");
}
}
return await Task.FromResult(answ);
return answ;
}
/// <summary>
@@ -241,16 +240,20 @@ namespace MP.Land.Data
private static IConfiguration? _configuration;
/// <summary>
/// URL dell'API x chiamate gestione licenze
/// </summary>
private string apiUrl { get; set; } = "https://localhost:5003/";
/// <summary>
/// Classe logger
/// </summary>
private static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
#region Private Properties
/// <summary>
/// URL dell'API x chiamate gestione licenze
/// </summary>
private string apiUrl { get; set; } = "https://localhost:5003/";
/// <summary>
/// Conf client RestSharp standard:
/// - base URI al sito
@@ -258,6 +261,6 @@ namespace MP.Land.Data
/// </summary>
private RestClientOptions restOptStd { get; set; } = new RestClientOptions();
#endregion Private Fields
#endregion Private Properties
}
}
+55 -2
View File
@@ -127,7 +127,7 @@ namespace MP.Data.Controllers
/// <param name="TaskId"></param>
/// <param name="SchedNext">Se true rischedula successiva chiamata</param>
/// <returns></returns>
public TaskResultModel ExecuteTask(int TaskId, bool SchedNext)
public TaskResultModel ExecuteSqlTask(int TaskId, bool SchedNext)
{
TaskResultModel callRes = new TaskResultModel();
using (var dbCtx = new MoonPro_STATSContext(_configuration))
@@ -195,6 +195,7 @@ namespace MP.Data.Controllers
return callRes;
}
/// <summary>
/// Annulla modifiche su una specifica entity (cancel update)
/// </summary>
@@ -302,6 +303,58 @@ namespace MP.Data.Controllers
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 MoonProContext(_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>
@@ -374,7 +427,7 @@ namespace MP.Data.Controllers
{
var currData = dbCtx
.DbSetTaskList
.Where(x => x.TaskId == rec2upd.TaskId)
.Where(x => x.TaskId == rec2upd.TaskId && rec2upd.TaskId > 0)
.FirstOrDefault();
if (currData != null)
{
+1 -1
View File
@@ -541,7 +541,7 @@ namespace MP.Data.Controllers
}
/// <summary>
/// Ricerca task dato tipo e
/// Ricerca task dato tipo
/// </summary>
/// <param name="TType"></param>
/// <returns></returns>
+2
View File
@@ -34,6 +34,8 @@
<PackageReference Include="MongoDB.Driver" Version="2.19.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.3.4" />
<PackageReference Include="RestSharp" Version="112.0.0" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
</ItemGroup>
</Project>
+11 -1
View File
@@ -271,7 +271,17 @@ namespace MP.Data.Objects
/// <summary>
/// Chiamata a SQL Stored Procedure
/// </summary>
SqlStored
SqlStored,
/// <summary>
/// Chiamata REST tipo Get
/// </summary>
RestCallGet,
///// <summary>
///// Chiamata REST tipo Post
///// </summary>
//RestCallPost
}
//[JsonConverter(typeof(StringEnumConverter))]
+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.AppAuth.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(apiUrl))
{
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
}
}
+51 -5
View File
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using MP.AppAuth.Services;
using MP.Data.Controllers;
using MP.Data.DatabaseModels;
using Newtonsoft.Json;
@@ -61,6 +62,9 @@ namespace MP.Data.Services
DataSource = connStrParams["Server"];
DataBase = connStrParams["Database"];
}
// conf rest call service
RCallService = new RestCallService(_configuration);
}
#endregion Public Constructors
@@ -88,15 +92,56 @@ namespace MP.Data.Services
/// <summary>
/// Chiamata esecuzione di un singolo task programmato
/// </summary>
/// <param name="TaskId"></param>
/// <param name="TaskRec">Task richiesto</param>
/// <param name="SchedNext">Se true rischedula successiva chiamata</param>
/// <returns></returns>
public async Task<TaskResultModel> ExecuteTask(int TaskId, bool SchedNext)
public async Task<TaskResultModel> ExecuteTask(TaskListModel TaskRec, bool SchedNext)
{
TaskResultModel dbResult = MLController.ExecuteTask(TaskId, SchedNext);
TaskResultModel answ = new TaskResultModel()
{
Task = $"TaskId: {TaskRec.TaskId} | {TaskRec.TType}",
ExecResult = -1,
TextResult = "Task Not recognized"
};
// verifico tipo di task ed eseguo di conseguenza...
switch (TaskRec.TType)
{
//case Task2ExeType.ND:
// break;
//case Task2ExeType.Exe:
// break;
//case Task2ExeType.SqlCommand:
// break;
case Task2ExeType.SqlStored:
answ = MLController.ExecuteSqlTask(TaskRec.TaskId, SchedNext);
break;
case Task2ExeType.RestCallGet:
DateTime dtStart = DateTime.Now;
// in primis testo la chiamata al servizio Health
string rAnsw = await RCallService.CheckServer();
// se ok effettuo vera chiamata...
if (rAnsw.ToUpper() == "OK")
{
var callResp = await RCallService.CallRestGet(TaskRec.Command, TaskRec.Args);
DateTime dtEnd = DateTime.Now;
TaskExecModel tExeMod = new TaskExecModel()
{
DtEnd = dtEnd,
DtStart = dtStart,
IsError = callResp.StatusCode != System.Net.HttpStatusCode.OK,
TaskId = TaskRec.TaskId,
Result = $"{callResp.Content}".Replace("\"", ""),
};
// salvo su DB
answ = MLController.TaskExecSaveExecuted(TaskRec.TaskId, SchedNext, tExeMod);
}
break;
default:
break;
}
// svuoto cache!
await FlushCache("Task");
return dbResult;
return answ;
}
/// <summary>
@@ -246,7 +291,7 @@ namespace MP.Data.Services
bool dbResult = MLController.TaskListUpsert(rec2upd);
// svuoto cache!
await FlushCache("Task");
return await Task.FromResult(dbResult);
return dbResult;
}
#endregion Public Methods
@@ -286,6 +331,7 @@ namespace MP.Data.Services
#region Private Properties
private static MpLandController MLController { get; set; } = null!;
private RestCallService RCallService { get; set; } = null!;
#endregion Private Properties
+11 -2
View File
@@ -2,8 +2,17 @@
<div class="card text-bg-light shadow">
<div class="card-header table-primary p-1">
<div class="d-flex justify-content-between">
<div class="px-2">
<b class="fs-4">History</b>
<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">
+18
View File
@@ -1,6 +1,12 @@
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;
@@ -70,10 +76,22 @@ namespace MP.Land.Components
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;
+1 -1
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Land</RootNamespace>
<Version>6.16.2410.2319</Version>
<Version>6.16.2410.2516</Version>
<Configurations>Debug;Release;Debug_LiManDebug</Configurations>
</PropertyGroup>
+1
View File
@@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration;
using MP.AppAuth;
using MP.AppAuth.Models;
using MP.AppAuth.Services;
using MP.Land.Data;
using System;
using System.Collections.Generic;
+21 -8
View File
@@ -10,13 +10,20 @@
</div>
<div class="px-2">
<div class="input-group">
@if (currRecord == null)
@if (TypeSel != MP.Data.Objects.Enums.Task2ExeType.ND)
{
<button class="btn btn-success" @onclick="addNew" title="Add New"><i class="fas fa-plus"></i> Add New</button>
@if (currRecord == null)
{
<button class="btn btn-success" @onclick="addNew" title="Add New"><i class="fas fa-plus"></i> Add New</button>
}
else
{
<button class="btn btn-secondary" @onclick="doCancel" title="Cancel"><i class="fas fa-undo"></i> Cancel</button>
}
}
else
{
<button class="btn btn-secondary" @onclick="doCancel" title="Cancel"><i class="fas fa-undo"></i> Cancel</button>
<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)))
@@ -58,7 +65,10 @@
<th>Ord</th>
<th>Task</th>
<th>Tipo</th>
<th>Command</th>
@if (detRecord == null)
{
<th>Command</th>
}
<th>Sched.</th>
@if (detRecord == null)
{
@@ -117,15 +127,18 @@
</td>
<td class="text-nowrap">
<div>@record.Name</div>
<div class="small">@record.Descript</div>
<div class="small text-truncate">@record.Descript</div>
</td>
<td>
@record.TType
</td>
<td>
<div>@record.Command</div>
<div class="small text-break">@record.Args</div>
@if (detRecord == null)
{
<td class="small text-truncate text-break">
<div title="@record.Command">@TextReduce(record.Command, 32)</div>
<div class="small text-break" title="@record.Args">@TextReduce(record.Args, 40)</div>
</td>
}
<td>@record.Freq &times; @record.Cad</td>
@if (detRecord == null)
{
+21 -4
View File
@@ -105,7 +105,14 @@ namespace MP.Land.Pages
protected async Task addNew()
{
currRecord = new TaskListModel() { Name = "Nuovo Task", Descript = "Descrizione", DtLastExec = DateTime.Today, DtNextExec = DateTime.Today.AddDays(1) };
currRecord = new TaskListModel()
{
Name = "Nuovo Task",
TType = TypeSel,
Descript = "Descrizione Task",
DtLastExec = DateTime.Today,
DtNextExec = DateTime.Today.AddDays(1)
};
await ReloadData();
}
@@ -139,7 +146,7 @@ namespace MP.Land.Pages
Command = selRec.Command,
Descript = $"Copia di {selRec.Descript}",
DtNextExec = DateTime.Today.AddDays(1),
DtLastExec = DateTime.MinValue,
DtLastExec = DateTime.Today.AddYears(-10),
Freq = selRec.Freq,
LastDuration = 0,
LastIsError = false,
@@ -192,7 +199,7 @@ namespace MP.Land.Pages
await Task.Delay(100);
await advStep(currStep++);
// chiama esecuzione task
var result = await TService.ExecuteTask(selRec.TaskId, false);
var result = await TService.ExecuteTask(selRec, false);
await advStep(currStep++);
isLoading = false;
await Task.Delay(100);
@@ -220,7 +227,7 @@ namespace MP.Land.Pages
await Task.Delay(100);
foreach (var taskRec in SearchRecords)
{
var result = await TService.ExecuteTask(taskRec.TaskId, false);
var result = await TService.ExecuteTask(taskRec, false);
}
isLoading = false;
await Task.Delay(100);
@@ -283,6 +290,16 @@ namespace MP.Land.Pages
return answ;
}
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
+2 -1
View File
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using MP.AppAuth;
using MP.AppAuth.Services;
using MP.Land.Data;
using Newtonsoft.Json;
using NLog;
@@ -501,7 +502,7 @@ namespace MP.Land.Pages
/// <exception cref="NotImplementedException"></exception>
private async Task<bool> UploadZip()
{
// chiamo SendZipFile di SyncService...
// chiamo SendZipFile di RestCallService...
FileInfo zFileInfo = new FileInfo(zFileName);
var fatto = await SyncServ.SendZipFile(LicServ.Applicazione, LicServ.Installazione, true, false, zFileInfo);
Log.Info($"Richiesto invio file | Applicazione: {LicServ.Applicazione} | Installazione: {LicServ.Installazione}");
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo Tablet MAPO - DotNet6</i>
<h4>Versione: 6.16.2410.2319</h4>
<h4>Versione: 6.16.2410.2516</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.16.2410.2319
6.16.2410.2516
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.16.2410.2319</version>
<version>6.16.2410.2516</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>
+2 -2
View File
@@ -13,11 +13,11 @@
</div>
<CascadingValue Name="ShowSearch" Value=@ShowSearch>
<div class="main mr-1">
<div class="main pe-1">
<div class="top-row d-print-none">
<CmpTop></CmpTop>
</div>
<div class="content pt-1 pt-lg-2 mb-5">
<div class="content pt-1 pt-lg-2 mb-5 px-3">
@Body
</div>
<div class="fixed-bottom @cssRow">
+2
View File
@@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MP.AppAuth.Services;
using MP.Data.Services;
using MP.Land.Data;
using StackExchange.Redis;
@@ -134,6 +135,7 @@ namespace MP.Land
services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton<LicenseService>();
services.AddSingleton<SyncService>();
services.AddSingleton<RestCallService>();
services.AddScoped<AppAuthService>();
services.AddScoped<TaskService>();
+2 -1
View File
@@ -72,6 +72,7 @@
"CodModulo": "MP-LAND",
"IobUploadPath": "C:\\inetpub\\wwwroot\\MP\\fileUpload",
"Modulo": "MoonPro",
"downloadPath": "C:\\Steamware\\installers\\MP"
"downloadPath": "C:\\Steamware\\installers\\MP",
"Prog.ApiUrl": "https://office.egalware.com/MP/PROG"
}
}