30 Commits

Author SHA1 Message Date
Samuele Locatelli 463898664b Merge tag 'AddCheckEnableAndError_01' into develop
Test errori in esecuzione + raggruppamento task
2025-07-21 12:50:31 +02:00
Samuele Locatelli 2c97b8c3e5 Merge branch 'release/AddCheckEnableAndError_01' 2025-07-21 12:50:12 +02:00
Samuele Locatelli 0cbffd8613 Modifica gestione task
- solo task attivi
- esce da gruppo se fallisce uno step
2025-07-21 12:49:38 +02:00
Samuele Locatelli 403e6df52b Merge tag 'NextSchedCalcUpdate_01' into develop
Update procedura calcolo prossima schedulazione
2025-06-05 09:09:52 +02:00
Samuele Locatelli 40a3f4f385 Merge branch 'release/NextSchedCalcUpdate_01' 2025-06-05 09:09:44 +02:00
Samuele Locatelli 3dd5f03091 Update x nuovo calcolo scadenza NEXT task + timeout cmq sql esplicito 2025-06-05 09:08:57 +02:00
Samuele Locatelli 7003690cb3 note in readme x piattaforma x64 2024-10-30 14:53:20 +01:00
Samuele Locatelli ad5031aed9 Merge tag 'FixYaml04' into develop
Fix errore componente static ed errori concorrenza tra thread
2024-10-30 11:53:59 +01:00
Samuele Locatelli b9c48d673b Merge branch 'release/FixYaml04' 2024-10-30 11:53:34 +01:00
Samuele Locatelli f88cf90d98 Fix obj static x DB 2024-10-30 11:53:06 +01:00
Samuele Locatelli 61984f53ba Merge tag 'FixYaml03' into develop
Sistemazione variabili di build
2024-10-30 10:33:22 +01:00
Samuele Locatelli 0748f0ef88 Merge branch 'release/FixYaml03' 2024-10-30 10:33:12 +01:00
Samuele Locatelli 9d19431748 Yaml fix:
- modifica wixproj: aggiunto target della platformx  output installer
2024-10-30 10:32:16 +01:00
Samuele Locatelli 8538c5e5de Merge tag 'FixYaml02' into develop
Fix chaimata yaml x installer release x64
2024-10-30 10:15:58 +01:00
Samuele Locatelli 28bd7f360c Merge branch 'release/FixYaml02' 2024-10-30 10:15:45 +01:00
Samuele Locatelli f3eccb2da9 YAML:
- fix x64 x compilazione release
2024-10-30 10:15:29 +01:00
Samuele Locatelli a1ebd35418 Merge tag 'FixYaml01' into develop
Fix yaml di produzione (da provare main installando...)
2024-10-30 10:11:30 +01:00
Samuele Locatelli a7bd8ad98a Merge branch 'release/FixYaml01' 2024-10-30 10:11:17 +01:00
Samuele Locatelli 23d00eb9cd Fix chiamata SP con init corretto context x query senza tab
Update DEBUG
2024-10-30 10:01:23 +01:00
Samuele Locatelli a67359d4f6 Maat, modifiche varie
- modifica key x evitare check incrociati tra cache redis diverse
- modifiche x log
- test nuovo installer debug
2024-10-30 09:22:17 +01:00
Samuele Locatelli c178b66d54 Fix yaml config 2024-10-30 07:20:41 +01:00
Samuele Locatelli 1b9252cb67 Fix file2send x x64
Update x gestioen metodo send Rest (da testare!!!)
2024-10-29 19:19:25 +01:00
Samuele Locatelli 46e4815947 YAML:
- test modifica restore nuget
- modifica chiamata installer x solo x64
2024-10-29 18:34:50 +01:00
Samuele Locatelli f9d785cc7c Update versione x test compilazione installer (da validare) + refresh compilazioni (tutte) 2024-10-29 18:08:50 +01:00
Samuele Locatelli e01a0a4689 Merge tag 'AddRestExec02' into develop
Test installer da versione compilata su build..
2024-10-29 12:18:09 +01:00
Samuele Locatelli 78aa7c2efe Merge branch 'release/AddRestExec02' 2024-10-29 12:18:00 +01:00
Samuele Locatelli 75cc0324bb Ancora update installer x test IIS04 2024-10-29 12:17:42 +01:00
Samuele Locatelli 124c16bd01 Merge tag 'AddRestExec01' into develop
Gestione dei task DB --> REST coem prog fatti e testati, da installare
update su IIS01/04
2024-10-25 19:04:44 +02:00
Samuele Locatelli 9ffb3244f5 Merge branch 'release/AddRestExec01' 2024-10-25 19:04:22 +02:00
Samuele Locatelli b897c7fa53 Update con gestione task da DB in formato REST (es PROG) 2024-10-25 19:03:13 +02:00
30 changed files with 779 additions and 189 deletions
+33 -25
View File
@@ -14,13 +14,35 @@ variables:
# helper x fix pacchetti nuget da repo locale nexus.steamware.net
.nuget-fix: &nuget-fix
- |
$hasSource = C:\Tools\nuget.exe sources list | find "`"Steamware Nexus`"" /C
if ($hasSource -eq 0) {
C:\Tools\nuget.exe sources Add -Name "`"Steamware Nexus`"" -Source https://nexus.steamware.net/repository/nuget-group -username "`"nugetUser`"" -password "`"viaDante16`"" -StorePasswordInClearText
} else {
C:\Tools\nuget.exe sources Update -Name "`"Steamware Nexus`"" -Source https://nexus.steamware.net/repository/nuget-group -username "`"nugetUser`"" -password "`"viaDante16`"" -StorePasswordInClearText
echo "esecuzione Nuget FIX steps"
dotnet nuget list source
$hasSource = dotnet nuget list source | Select-String -Pattern "Steamware Nexus Proxy"
if (! [String]::IsNullOrWhiteSpace($hasSource)) {
dotnet nuget remove source "`"Steamware Nexus Proxy`""
}
echo $hasSource
$hasSource = dotnet nuget list source | Select-String -Pattern "Steamware Nexus"
if (! [String]::IsNullOrWhiteSpace($hasSource)) {
dotnet nuget remove source "`"Steamware Nexus`""
}
$hasSource = dotnet nuget list source | Select-String -Pattern "nexus-proxy-v3"
if (! [String]::IsNullOrWhiteSpace($hasSource)) {
dotnet nuget remove source nexus-proxy-v3
}
$hasSource = dotnet nuget list source | Select-String -Pattern "nexus-hosted"
if (! [String]::IsNullOrWhiteSpace($hasSource)) {
dotnet nuget remove source nexus-hosted
}
$hasSource = dotnet nuget list source | Select-String -Pattern "Microsoft Visual Studio Offline Packages"
if (! [String]::IsNullOrWhiteSpace($hasSource)) {
dotnet nuget remove source 'Microsoft Visual Studio Offline Packages'
}
echo "Situazione sorgenti post remove:"
dotnet nuget list source
dotnet nuget add source https://nexus.steamware.net/repository/nuget-proxy-v3/index.json -n nexus-proxy-v3 -u nugetUser -p $NEXUS_PASSWD --store-password-in-clear-text
dotnet nuget add source https://nexus.steamware.net/repository/nuget-hosted/ -n nexus-hosted -u nugetUser -p $NEXUS_PASSWD --store-password-in-clear-text
$hasSource = dotnet nuget list source
echo "Situazione sorgenti FINALE:"
dotnet nuget list source
# helper x fix version number
.version-fix: &version-fix
@@ -47,7 +69,7 @@ variables:
# helper creazione hash files x Nexus
.hashBuild: &hashBuild
- |
$Target = "$env:INST_NAME\bin\" + $env:APP_CONF + "\en-US\" + $env:INST_NAME + ".msi"
$Target = "$env:INST_NAME\bin\x64\" + $env:APP_CONF + "\en-US\" + $env:INST_NAME + ".msi"
$MD5 = Get-FileHash $Target -Algorithm MD5
$SHA1 = Get-FileHash $Target -Algorithm SHA1
New-Item $Target".md5"
@@ -75,7 +97,7 @@ variables:
$fileVers = $env:NUM_DEB
}
echo "Curr Version: $fileVers | $version"
$File2Send = Get-ChildItem("$env:INST_NAME\bin\" + $env:APP_CONF + "\en-US\*")
$File2Send = Get-ChildItem("$env:INST_NAME\bin\x64\" + $env:APP_CONF + "\en-US\*")
ForEach ($File in $File2Send) {
$FileName = Split-Path $File -leaf
mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file $File https://nexus.steamware.net/repository/SWS/$env:INST_NAME/$version/LAST/$FileName
@@ -109,7 +131,6 @@ variables:
stages:
- build
# - staging
- deploy
# - pack
@@ -128,20 +149,7 @@ Runner:build:
script:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
# #--------- Staging --------- #
# UI:staging:
# stage: staging
# tags:
# - win
# variables:
# APP_NAME: MP.MONO.UI
# only:
# - develop
# needs: ["UI:build"]
# script:
# - dotnet publish -p:PublishProfile=IIS01.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:APP_NAME/$env:APP_NAME.csproj
# #--------- Deploy --------- #
#--------- Deploy --------- #
Runner:deploy-dev:
stage: deploy
tags:
@@ -162,7 +170,7 @@ Runner:deploy-dev:
# pubblicazione come singleApp
- dotnet publish -p:PublishProfile=SingleAppDebug.pubxml -p:RunCodeAnalysis=false -p:Configuration=$env:APP_CONF $env:APP_NAME/$env:APP_NAME.csproj
# creazione installer WIX
- dotnet build $env:INST_NAME/$env:INST_NAME.wixproj -p:Configuration=$env:APP_CONF
- dotnet build $env:INST_NAME/$env:INST_NAME.wixproj -p:Configuration=$env:APP_CONF -p:Platform=x64
#- *artifactZipper
- *hashBuild
- *nexusUpload
@@ -187,7 +195,7 @@ Runner:deploy:
# pubblicazione come singleApp
- dotnet publish -p:PublishProfile=SingleApp.pubxml -p:RunCodeAnalysis=false -p:Configuration=$env:APP_CONF $env:APP_NAME/$env:APP_NAME.csproj
# creazione installer WIX
- dotnet build $env:INST_NAME/$env:INST_NAME.wixproj -p:Configuration=$env:APP_CONF
- dotnet build $env:INST_NAME/$env:INST_NAME.wixproj -p:Configuration=$env:APP_CONF -p:Platform=x64
#- *artifactZipper
- *hashBuild
- *nexusUpload
+5
View File
@@ -21,6 +21,11 @@ namespace Maat.Core.CONF
/// </summary>
public MsSqlConf? MsSqlJobs { get; set; } = null;
/// <summary>
/// Area configurazione task RestApi (opzionale)
/// </summary>
public RestApiConf? RestApiJobs { get; set; } = null;
#endregion Public Properties
}
}
+85
View File
@@ -0,0 +1,85 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Maat.Core.Enums;
namespace Maat.Core.CONF
{
/// <summary>
/// Classe gestione configurazione parametri di base x gestione task da API REST
/// </summary>
public class RestApiConf
{
#region Public Properties
/// <summary>
/// Elenco dei server configurati x chiamate REST Api, ogni server ha la stessa base ApiUrl
/// </summary>
public List<SrvConf> ServerList { get; set; } = new List<SrvConf>();
#endregion Public Properties
#region Public Classes
public class SrvConf
{
#region Public Properties
/// <summary>
/// Dizionario dei metodi configurati da chiamare
/// </summary>
public List<CallConfig> CallList { get; set; } = new List<CallConfig>();
/// <summary>
/// Path di base ApiUrl del servizio
/// </summary>
public string ApiUrl { get; set; } = "";
/// <summary>
/// nome univoco del servizio
/// </summary>
public string SrvName { get; set; } = "";
#endregion Public Properties
}
/// <summary>
/// Configurazione singola chiamata
/// </summary>
public class CallConfig
{
/// <summary>
/// Id univoco della chiamata (contatore univoco in ambito SrvName/ApiUrl..)
/// </summary>
public int CallId { get; set; } = 0;
/// <summary>
/// Modalità chiamata tra quelle disponibili
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public RestCallType CallMode { get; set; } = RestCallType.Get;
/// <summary>
/// Risorsa da chiamare
/// </summary>
public string Resource { get; set; } = "";
/// <summary>
/// Payload associato alla risorsa da chiamare
/// </summary>
public string Payload { get; set; } = "";
/// <summary>
/// Tempo di attesa tra le chiamate... default 60 minuti
/// </summary>
public double WaitMinutes { get; set; } = 60;
#endregion Public Classes
}
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ namespace Maat.Core
{
// dati conf REDIS Cache
public static readonly string RedisBaseKey = "EgalWare-Maat";
public static readonly string RedisBaseKey = "Maat";
public static readonly string BASE_PATH = Directory.GetCurrentDirectory();
+40 -2
View File
@@ -26,7 +26,17 @@ namespace Maat.Core
/// <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))]
@@ -74,7 +84,7 @@ namespace Maat.Core
}
/// <summary>
/// Tipologia di chiamata permessa
/// Tipologia di chiamata DB permessa
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum TaskCallType
@@ -89,5 +99,33 @@ namespace Maat.Core
/// </summary>
TaskList
}
/// <summary>
/// Tipologia di chiamata REST permessa
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum RestCallType
{
/// <summary>
/// Metodo Delete
/// </summary>
Delete,
/// <summary>
/// Metodo Get
/// </summary>
Get,
/// <summary>
/// Metodo Post
/// </summary>
Post,
/// <summary>
/// Metodo Put
/// </summary>
Put
}
}
}
+2 -2
View File
@@ -12,8 +12,8 @@
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.2.8" />
<PackageReference Include="StackExchange.Redis" Version="2.7.33" />
<PackageReference Include="NLog" Version="5.3.4" />
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
</ItemGroup>
</Project>
+15
View File
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Maat.Core
{
public class RestWaitConf
{
public int CallId { get; set; } = 0;
public double WaitTime { get; set; } = 0;
public DateTime NextExe { get; set; } = DateTime.Now;
}
}
+119 -42
View File
@@ -20,10 +20,12 @@ namespace Maat.Data.Controllers
/// </summary>
/// <param name="threadName">nome del thread di esecuzione</param>
/// <param name="cString">stringa di connessione da impiegare</param>
public MsSqlController(string threadName, string cString)
/// <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");
}
@@ -34,51 +36,61 @@ namespace Maat.Data.Controllers
public DateTime CalcNextExe(TaskListModel taskRec)
{
DateTime dtNext = DateTime.Today;
DateTime adesso = DateTime.Now;
int maxIter = 1000;
try
{
// calcolo next exec da tipo...
switch (taskRec.Freq)
// 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)
{
case TaskFreqType.ND:
dtNext = taskRec.DtLastExec.AddDays(taskRec.Cad);
break;
switch (taskRec.Freq)
{
case TaskFreqType.ND:
dtNext = baseDT.AddDays(taskRec.Cad);
break;
case TaskFreqType.Sec:
dtNext = taskRec.DtLastExec.AddSeconds(taskRec.Cad);
break;
case TaskFreqType.Sec:
dtNext = baseDT.AddSeconds(taskRec.Cad);
break;
case TaskFreqType.Min:
dtNext = taskRec.DtLastExec.AddMinutes(taskRec.Cad);
break;
case TaskFreqType.Min:
dtNext = baseDT.AddMinutes(taskRec.Cad);
break;
case TaskFreqType.Hour:
dtNext = taskRec.DtLastExec.AddHours(taskRec.Cad);
break;
case TaskFreqType.Hour:
dtNext = baseDT.AddHours(taskRec.Cad);
break;
case TaskFreqType.Day:
dtNext = taskRec.DtLastExec.AddDays(taskRec.Cad);
break;
case TaskFreqType.Day:
dtNext = baseDT.AddDays(taskRec.Cad);
break;
case TaskFreqType.Week:
dtNext = taskRec.DtLastExec.AddDays(7 * taskRec.Cad);
break;
case TaskFreqType.Week:
dtNext = baseDT.AddDays(7 * taskRec.Cad);
break;
case TaskFreqType.Month:
dtNext = taskRec.DtLastExec.AddMonths(taskRec.Cad);
break;
case TaskFreqType.Month:
dtNext = baseDT.AddMonths(taskRec.Cad);
break;
case TaskFreqType.Year:
dtNext = taskRec.DtLastExec.AddYears(taskRec.Cad);
break;
case TaskFreqType.Year:
dtNext = baseDT.AddYears(taskRec.Cad);
break;
default:
dtNext = taskRec.DtLastExec.AddDays(taskRec.Cad);
break;
default:
dtNext = baseDT.AddDays(taskRec.Cad);
break;
}
baseDT = dtNext;
maxIter--;
}
}
catch (Exception exc)
{
Log.Error($"{tName} | Eccezione in CalcNextExe{Environment.NewLine}{exc}");
Log.Error($"Eccezione in CalcNextExe{Environment.NewLine}{exc}");
}
return dtNext;
}
@@ -91,14 +103,16 @@ namespace Maat.Data.Controllers
/// 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 ExecuteTask(int TaskId)
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(5));
dbCtx.Database.SetCommandTimeout(TimeSpan.FromMinutes(cmdTimeout));
string sqlCall = "";
try
{
DateTime dtStart = DateTime.Now;
@@ -112,13 +126,16 @@ namespace Maat.Data.Controllers
// 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}")
.AsNoTracking()
.AsEnumerable()
.FirstOrDefault();
callRes = rawData ?? new TaskResultModel();
.DbSetTaskResult
.FromSqlRaw($"EXEC {sqlCommand} {rawParams}")
.ToList();
callRes = rawData.FirstOrDefault() ?? new TaskResultModel();
DateTime dtEnd = DateTime.Now;
// preparo record esecuzione...
@@ -139,8 +156,12 @@ namespace Maat.Data.Controllers
currRec.LastResult = resRec.Result;
currRec.LastIsError = resRec.IsError;
currRec.LastDuration = dtEnd.Subtract(dtStart).TotalSeconds;
// calcolo prossima esecuzione...
currRec.DtNextExec = CalcNextExe(currRec);
// solo se richiesto rischedulazione ricalcola chiamata
if (SchedNext)
{
// calcolo prossima esecuzione...
currRec.DtNextExec = CalcNextExe(currRec);
}
// segno modificato
dbCtx.Entry(currRec).State = EntityState.Modified;
@@ -150,7 +171,62 @@ namespace Maat.Data.Controllers
}
catch (Exception exc)
{
Log.Error($"{tName} | Eccezione in ExecuteTask{Environment.NewLine}{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;
@@ -182,6 +258,7 @@ namespace Maat.Data.Controllers
private static Logger Log = LogManager.GetCurrentClassLogger();
private string connString = "";
private string tName = "";
private int cmdTimeout = 0;
#endregion Private Fields
}
+12 -1
View File
@@ -20,11 +20,21 @@ namespace Maat.Data.DbModels
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TaskId { get; set; } = 0;
/// <summary>
/// Gruppo task (per gestione precedenze e semaforo exec)
/// </summary>
public int Group { get; set; } = 1;
/// <summary>
/// Ordinale x esecuzione
/// </summary>
public int Ordinal { get; set; } = 0;
/// <summary>
/// Stato Task abilitato / disabilitato
/// </summary>
public bool Enabled { get; set; } = false;
/// <summary>
/// Nome Task
/// </summary>
@@ -64,8 +74,9 @@ namespace Maat.Data.DbModels
/// DataOra ultima esecuzione
/// </summary>
public DateTime DtLastExec { get; set; } = DateTime.Today.AddYears(-10);
/// <summary>
/// DataOra ultima esecuzione
/// DataOra prossima esecuzione (prevista)
/// </summary>
public DateTime DtNextExec { get; set; } = DateTime.Today.AddYears(-9);
+11 -10
View File
@@ -7,23 +7,24 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.28" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="6.0.28" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="6.0.28" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.28">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.35" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="6.0.35" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="6.0.35" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.35">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.28" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.28" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.28">
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.35" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.35" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.35">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.ILLink.Tasks" Version="8.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.2.8" />
<PackageReference Include="StackExchange.Redis" Version="2.7.33" />
<PackageReference Include="NLog" Version="5.3.4" />
<PackageReference Include="RestSharp" Version="112.1.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
</ItemGroup>
<ItemGroup>
+4 -4
View File
@@ -19,7 +19,7 @@ namespace Maat.Data.Services
/// </summary>
protected TimeSpan FastCache
{
get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 999) / 1000);
get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 995) / 1000);
}
/// <summary>
@@ -27,7 +27,7 @@ namespace Maat.Data.Services
/// </summary>
protected TimeSpan LongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 999) / 1000);
get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 995) / 1000);
}
/// <summary>
@@ -35,7 +35,7 @@ namespace Maat.Data.Services
/// </summary>
protected TimeSpan UltraFastCache
{
get => TimeSpan.FromSeconds(cacheTtlShort / 6 * rnd.Next(900, 999) / 1000);
get => TimeSpan.FromSeconds(cacheTtlShort / 6 * rnd.Next(900, 995) / 1000);
}
/// <summary>
@@ -43,7 +43,7 @@ namespace Maat.Data.Services
/// </summary>
protected TimeSpan UltraLongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 999) / 1000);
get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 995) / 1000);
}
#endregion Protected Properties
+112 -25
View File
@@ -7,29 +7,26 @@ using static Maat.Core.Enums;
using System.Diagnostics;
using Newtonsoft.Json;
using System.Xml.Linq;
using Newtonsoft.Json.Linq;
namespace Maat.Data.Services
{
public class MsSqlTaskService : BaseServ, IDisposable
{
#region Public Fields
public static MsSqlController dbController = null!;
#endregion Public Fields
#region Public Constructors
/// <summary>
/// Servizio gestione Task su DB
/// </summary>
/// <param name="threadName"></param>
/// <param name="dbConnString"></param>
/// <param name="redisConnString"></param>
public MsSqlTaskService(string threadName, string dbConnString, string redisConnString)
/// <param name="threadName">nome del thread</param>
/// <param name="dbConnString">stringa completa di connessione</param>
/// <param name="redisConnString">stringa completa REDIS</param>
/// <param name="apiUrl">url x chiamate api REST</param>
/// <param name="execTimeOut">timeout esecuzione comandi sql (in minuti)</param>
public MsSqlTaskService(string threadName, string dbConnString, string redisConnString, string apiUrl, int execTimeOut)
{
Log.Info($"{tName} | Starting MsSqlTaskService");
tName = threadName;
Log.Info($"{tName} | Starting MsSqlTaskService");
connString = dbConnString;
// setup compoenti REDIS
@@ -43,9 +40,12 @@ namespace Maat.Data.Services
}
else
{
dbController = new MsSqlController(tName, dbConnString);
dbController = new MsSqlController(tName, dbConnString, execTimeOut);
Log.Info($"{tName} | DbController OK");
}
// conf rest call service
RCallService = new RestCallService(apiUrl);
}
#endregion Public Constructors
@@ -64,27 +64,58 @@ namespace Maat.Data.Services
public List<TaskResultModel> CheckExecute()
{
List<TaskResultModel> answ = new List<TaskResultModel>();
List<TaskListModel> listTask = TaskListAll(Enums.Task2ExeType.ND, "");
List<TaskListModel> listTask = TaskListAll(tName, Enums.Task2ExeType.ND, "");
// verifico SE ci siano task in scadenza...
DateTime adesso = DateTime.Now;
var task2exe = listTask.Where(x => x.DtNextExec <= adesso).ToList();
List<TaskListModel> task2exe = listTask.Where(x => x.Enabled && x.DtNextExec <= adesso).ToList();
int numDone = 0;
if (task2exe != null && task2exe.Count > 0)
{
Log.Info($"{tName} | Found {task2exe.Count} task to execute");
// suddivisione x gruppi
var ListGrouped = task2exe
.OrderBy(x => x.Group)
.ThenBy(x => x.Ordinal)
.GroupBy(x => x.Group)
.ToDictionary(g => g.Key, g => g.ToList());
// ciclo, e all'interno del gruppo SE non passa uno step si ferma....
foreach (var taskGroup in ListGrouped)
{
foreach (var taskRec in taskGroup.Value)
{
TaskResultModel result = ExecuteTask(taskRec);
answ.Add(result);
numDone++;
// SE non eseguito --> esce, come anche se passato timeout (e ultima esecuzione è prima della scadenza..
if (result.ExecResult < 0)
{
break;
}
}
}
#if false
foreach (var taskRec in task2exe)
{
TaskResultModel result = ExecuteTask(taskRec.TaskId);
TaskResultModel result = ExecuteTask(taskRec);
answ.Add(result);
}
}
#endif
}
else
{
Log.Trace($"{tName} | Chiamata CheckExecute");
Log.Trace($"{tName} | Chiamata CheckExecute | eseguiti {numDone} task");
}
// resituisco
return answ;
}
public string CheckRestServer()
{
return RCallService.CheckServer();
}
public void Dispose()
{
// Clear database controller
@@ -96,13 +127,61 @@ namespace Maat.Data.Services
/// <summary>
/// Chiamata esecuzione di un singolo task programmato
/// </summary>
/// <param name="tName">Nome del thread</param>
/// <param name="TaskId">TaskId</param>
/// <param name="TaskRec">Task richiesto</param>
/// <returns></returns>
public TaskResultModel ExecuteTask(int TaskId)
public TaskResultModel ExecuteTask(TaskListModel TaskRec)
{
TaskResultModel dbResult = dbController.ExecuteTask(TaskId);
Log.Info($"{tName} | Executed | TaskId: {TaskId}");
TaskResultModel dbResult = 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:
dbResult = dbController.ExecuteSqlTask(TaskRec.TaskId, true);
Log.Info($"{tName} | Executed | TaskRec: {TaskRec}");
break;
case Task2ExeType.RestCallGet:
// in primis testo la chiamata al servizio Health
string rAnsw = RCallService.CheckServer();
DateTime dtStart = DateTime.Now;
// se ok effettuo vera chiamata...
if (rAnsw.ToUpper() == "OK")
{
var callResp = RCallService.CallRestGet(TaskRec.Command, TaskRec.Args);
DateTime dtEnd = DateTime.Now;
string formattedJson = "";
if (!string.IsNullOrEmpty(callResp.Content))
{
formattedJson = JValue.Parse(callResp.Content).ToString(Formatting.Indented);
}
TaskExecModel tExeMod = new TaskExecModel()
{
DtEnd = dtEnd,
DtStart = dtStart,
IsError = callResp.StatusCode != System.Net.HttpStatusCode.OK,
TaskId = TaskRec.TaskId,
// deserializzazione come json indentato?!?
Result = formattedJson// $"{callResp.Content}".Replace("\"", ""),
};
// salvo su DB
dbResult = dbController.TaskExecSaveExecuted(TaskRec.TaskId, true, tExeMod);
}
break;
default:
break;
}
// svuoto cache!
FlushCache("Task");
return dbResult;
@@ -150,7 +229,7 @@ namespace Maat.Data.Services
/// <param name="CurrFilter"></param>
/// <param name="searchVal"></param>
/// <returns></returns>
public List<TaskListModel> TaskListAll(Task2ExeType TType, string searchVal = "")
public List<TaskListModel> TaskListAll(string threadName, Task2ExeType TType, string searchVal = "")
{
// setup parametri costanti
string source = "DB";
@@ -159,9 +238,9 @@ namespace Maat.Data.Services
List<TaskListModel> result = new List<TaskListModel>();
// cerco in redis...
DateTime adesso = DateTime.Now;
string currKey = $"{Const.RedisBaseKey}:Task:List:{TType}";
string currKey = $"{Const.RedisBaseKey}:Task:{threadName.Replace("_", ":")}:List:{TType}";
RedisValue rawData = redisDb.StringGet(currKey);
if (rawData.HasValue)
if (false && rawData.HasValue && rawData.Length() > 4)
{
var rawResult = JsonConvert.DeserializeObject<List<TaskListModel>>($"{rawData}");
result = rawResult ?? new List<TaskListModel>();
@@ -215,6 +294,14 @@ namespace Maat.Data.Services
#endregion Private Fields
#region Private Properties
private MsSqlController dbController { get; set; } = null!;
private RestCallService RCallService { get; set; } = null!;
#endregion Private Properties
#region Private Methods
/// <summary>
+124
View File
@@ -0,0 +1,124 @@
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Maat.Data.Services
{
public class RestCallService
{
#region Public Constructors
/// <summary>
/// Init classe
/// </summary>
/// <param name="ApiUrl"></param>
public RestCallService(string ApiUrl)
{
apiUrl = ApiUrl;// _configuration.GetValue<string>("SrvConf:Prog.ApiUrl") ?? "http://office.egalware.com/MP/PROG";
// fix opzioni base del RestClient
restOptStd = new RestClientOptions
{
Timeout = TimeSpan.FromSeconds(60),
BaseUrl = new Uri(apiUrl),
ThrowOnAnyError = true,
ThrowOnDeserializationError = true
};
}
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 string CheckServer()
{
string answ = "ND";
// cerco online
using (RestClient client = new RestClient(restOptStd))
{
var request = new RestRequest($"api/health", Method.Get);
try
{
var response = client.ExecuteGet(request);
//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("\"", "");
//answ= JValue.Parse(response.Content).ToString(Formatting.Indented);
}
}
}
catch (Exception exc)
{
Log.Error($"Eccezione in CheckServer{Environment.NewLine}{exc}");
}
}
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 RestResponse CallRestGet(string ApiUrl, string ApiRequest)
{
RestResponse response;
var currOpt = new RestClientOptions
{
Timeout = TimeSpan.FromSeconds(60),
BaseUrl = new Uri(ApiUrl),
ThrowOnAnyError = true,
ThrowOnDeserializationError = true
};
// cerco online
using (RestClient client = new RestClient(currOpt))
{
var request = new RestRequest(ApiRequest, Method.Get);
response = client.Get(request);
}
return response;
}
#endregion Public Methods
#region Private Fields
/// <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
View File
@@ -61,6 +61,10 @@ namespace Maat.Data
{
modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
// fix x ritorno tracciato senza tabella corrispondente:
// https://stackoverflow.com/questions/50276906/dbcontext-set-cannot-create-a-dbset-for-entity-because-this-type-is-not-includ
modelBuilder.Entity<TaskResultModel>().HasNoKey();
OnModelCreatingPartial(modelBuilder);
}
+2 -2
View File
@@ -18,8 +18,8 @@
<Compile Remove="stdin.wxs" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
<SuppressPdbOutput>true</SuppressPdbOutput>
</PropertyGroup>
</Project>
+19 -11
View File
@@ -5,7 +5,7 @@
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>1.0.2404.1009</Version>
<Version>1.2.2507.2112</Version>
</PropertyGroup>
<ItemGroup>
@@ -19,16 +19,21 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.ILLink.Tasks" Version="8.0.3" />
<None Include="Properties\PublishProfiles\SingleApp.pubxml.user" />
<None Include="Properties\PublishProfiles\SingleAppDebug.pubxml.user" />
<None Include="Properties\PublishProfiles\SingleAppManual.pubxml.user" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.2.8" />
<PackageReference Include="StackExchange.Redis" Version="2.7.33" />
<PackageReference Include="NLog" Version="5.3.4" />
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
</ItemGroup>
<ItemGroup>
@@ -37,11 +42,14 @@
</ItemGroup>
<ItemGroup>
<None Update="conf\JobConfig.PROG.json">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Update="conf\JobConfig-demo.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="conf\JobConfig.json">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="logs\stderr.log">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
+87 -39
View File
@@ -4,6 +4,7 @@ using Maat.Data;
using Maat.Data.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileSystemGlobbing.Internal;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
@@ -12,6 +13,7 @@ using System.Diagnostics;
using System.Reflection;
using System.Threading;
using System.Xml.Linq;
using static Maat.Core.CONF.RestApiConf;
// init parte config, vedere https://blog.hildenco.com/2020/05/configuration-in-net-core-console.html
@@ -29,6 +31,12 @@ string redisConf = config.GetConnectionString("Redis") ?? "?????????????????????
string confPath = Path.Combine(Directory.GetCurrentDirectory(), "conf");
Logger Log = LogManager.GetCurrentClassLogger();
string apiUrlStd = config.GetValue<string>("SrvConf:Prog.ApiUrl") ?? "";
if (string.IsNullOrEmpty(apiUrlStd))
{
Log.Error($"Errore: ApiUrl vuota!");
}
// gestore della configurazione principale da cui derivare gestione...
JobConfigConf currConf = new JobConfigConf();
@@ -44,6 +52,7 @@ bool verboseLog = false;
bool logWriting = false;
string appName = "Maat";
int MinSaveIntSec = 60;
int SqlCmdTimeoutMinutes = 10;
int StepSec = 60;
string JobConfigFile = "";
@@ -78,7 +87,7 @@ setupConf();
if (currConf != null)
{
Log.Info("Starting job threads...");
// cero i thread x tipo...
// cero i thread x tipo MsSql...
if (currConf.MsSqlJobs == null)
{
Log.Info("No MsSqlJob, skipping...");
@@ -105,8 +114,8 @@ if (currConf != null)
{
// compongo connstring
string dbConnStr = $"Server={currSrv.ServerName}; Database={dbName}; User ID={currSrv.DbUser}; Password={currSrv.DbPasswd}; integrated security=False; MultipleActiveResultSets=True; App={appName}";
string threadName = $"ThdMsSql_{dbName}"; ;
Thread newThread = new Thread(() => doCronDB(threadName, dbConnStr));
string threadName = $"ThdMsSql_{currSrv.ServerName}_{dbName}";
Thread newThread = new Thread(() => doCronDB(threadName, dbConnStr, SqlCmdTimeoutMinutes));
newThread.Name = threadName;
jobsThreadList.Add(newThread);
Log.Info($"Added {newThread.Name} to jobsThreadList");
@@ -115,6 +124,41 @@ if (currConf != null)
}
}
}
// cero i thread x tipo Rest...
if (currConf.RestApiJobs == null)
{
Log.Info("No RestApiJobs, skipping...");
}
else
{
if (currConf.RestApiJobs.ServerList == null || currConf.RestApiJobs.ServerList.Count == 0)
{
Log.Info("No Servers found in RestApiJobs.ServerList, skipping...");
}
else
{
foreach (var currSrv in currConf.RestApiJobs.ServerList)
{
// verifico di avere i singoli DB da processare...
if (currSrv.CallList == null || currSrv.CallList.Count == 0)
{
Log.Info("No DB found in RestApiJobs.ServerList.CallList, skipping...");
}
else
{
// thread unico x ogni server
string threadName = $"ThdRest_{currSrv.SrvName}";
Thread newThread = new Thread(() => doCronRest(threadName, currSrv.ApiUrl, currSrv.CallList));
newThread.Name = threadName;
jobsThreadList.Add(newThread);
Log.Info($"Added {newThread.Name} to jobsThreadList");
}
}
}
}
// avvio tutti i thread preparati...
foreach (var cThread in jobsThreadList)
{
@@ -149,6 +193,7 @@ void setupConf()
StepSec = config.GetValue<int>("SrvConf:StepSec");
MinSaveIntSec = config.GetValue<int>("SrvConf:MinSaveIntSec");
var rawJCF = config.GetValue<string>("SrvConf:JobConfigFile");
SqlCmdTimeoutMinutes = config.GetValue<int>("SrvConf:SqlCmdTimeoutMinutes");
if (string.IsNullOrEmpty(rawJCF))
{
Log.Error($"Cannot start: missing JobConfigFile configuration");
@@ -160,7 +205,7 @@ void setupConf()
}
}
void saveAndSendMessage(string memKey, string notifyChannel, string message)
void saveAndSendMessage(string memKey, string channelName, string message)
{
// effettuo la scrittura nell'area di memoria indicata SE passato intervallo minimo
bool doSave = true;
@@ -186,10 +231,11 @@ void saveAndSendMessage(string memKey, string notifyChannel, string message)
}
// invio notifica tramite il canale richiesto
RedisChannel notifyChannel = new RedisChannel(channelName, RedisChannel.PatternMode.Auto);
sub.Publish(notifyChannel, message);
if (verboseLog)
{
Log.Info($"[{notifyChannel}] key: {memKey} | val/message: {message}");
Log.Info($"[{channelName}] key: {memKey} | val/message: {message}");
}
else
{
@@ -197,16 +243,6 @@ void saveAndSendMessage(string memKey, string notifyChannel, string message)
{
if (!logWriting)
{
#if false
if (LogSimulator.ContainsKey(notifyChannel))
{
LogSimulator[notifyChannel]++;
}
else
{
LogSimulator.Add(notifyChannel, 1);
}
#endif
logWriting = true;
// vedo se loggare...
DateTime adesso = DateTime.Now;
@@ -214,16 +250,6 @@ void saveAndSendMessage(string memKey, string notifyChannel, string message)
{
lastLog = adesso;
Log.Info(lineSep);
#if false
// lavoro su copia...
var LogSimulatorCopy = new Dictionary<string, int>(LogSimulator);
foreach (var item in LogSimulatorCopy)
{
Log.Info($"Redis mQueue {item.Key,-20}{item.Value,12}");
}
Log.Info(lineSep);
#endif
}
logWriting = false;
}
@@ -236,16 +262,17 @@ void saveAndSendMessage(string memKey, string notifyChannel, string message)
}
void doCronDB(string threadName, string dbConnStr)
void doCronDB(string threadName, string dbConnStr, int cmdTimeOut)
{
string tName = threadName;
Log.Info($"{tName} | Starting dbCronDb task");
// periodo standard 1 minuto
int stepPeriod = 60000;
MsSqlTaskService tRun = new MsSqlTaskService(tName, dbConnStr, redisConf);
MsSqlTaskService tRun = new MsSqlTaskService(tName, dbConnStr, redisConf, apiUrlStd, cmdTimeOut);
// ciclo infinito esegue task poi attende quanto manca a prox scadenza...
do
{
//var testServer = tRun.CheckRestServer();
// eseguo i miei task e recupero esito
var newStatus = tRun.CheckExecute();
@@ -277,21 +304,43 @@ void doCronDB(string threadName, string dbConnStr)
}
void doCronTaskRest(string baseUrl)
void doCronRest(string threadName, string baseUrl, List<CallConfig> callList)
{
string tName = threadName;
Log.Info($"{tName} | Starting doCronRest task");
// periodo standard 1 minuto
int stepPeriod = 60000;
// nuovo runner x chiamate REST... si aspetta una lista di URL da chiamare
#if false
// per ora un db CABLATO, poi saranno tanti DB (o tanti thread?)
TaskRunnerService tRun = new TaskRunnerService(dbConnStr, redisConf);
#endif
// init servizio x chiamate REST...
RestCallService sRun = new RestCallService(baseUrl);
// il servizio usa la callList di oggetti da chiamare con indicazione tempistiche, inizializzo la tabella delle attese...
DateTime adesso = DateTime.Now;
var waitList = callList.Select(x => new RestWaitConf()
{
CallId = x.CallId,
WaitTime = x.WaitMinutes,
NextExe = adesso.AddMinutes(x.WaitMinutes)
}).ToList();
// ciclo infinito esegue task poi attende quanto manca al prox minuto...
do
{
// verifico in primis quale servizio sia eventualmente scaduto...
DateTime exeTime = DateTime.Now;
foreach (var item in waitList)
{
if (item.NextExe < exeTime)
{
// recupero la call...
var currCall = callList.Where(x => x.CallId == item.CallId).FirstOrDefault();
if (currCall != null)
{
// eseguo call
var callResp = sRun.CallRestGet(baseUrl, currCall.Resource);
}
// rischedulo!
item.NextExe = exeTime.AddMinutes(item.WaitTime);
}
}
#if false
// eseguo i miei task e recupero esito
var newStatus = tRun.CheckExecute();
@@ -310,10 +359,9 @@ void doCronTaskRest(string baseUrl)
#endif
// calcolo quanto manca al prossimo step
DateTime adesso = DateTime.Now;
DateTime nextDt = adesso.Ceil(TimeSpan.FromMilliseconds(stepPeriod));
double waitTime = nextDt.Subtract(adesso).TotalMilliseconds;
if (waitTime == 0)
DateTime nextDt = exeTime.Ceil(TimeSpan.FromMilliseconds(stepPeriod));
double waitTime = nextDt.Subtract(exeTime).TotalMilliseconds;
if (waitTime <= 0)
{
waitTime = stepPeriod * 90 / 100;
}
@@ -1,6 +1,6 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<History>False|2024-04-05T06:22:12.1466170Z;False|2024-04-04T09:20:19.1194551+02:00;False|2024-04-04T07:54:11.6078436+02:00;False|2024-04-03T18:57:56.8357860+02:00;False|2024-04-03T18:57:31.1394991+02:00;False|2024-04-03T18:56:30.3461610+02:00;False|2024-04-03T18:55:50.6292479+02:00;False|2024-04-03T18:54:46.2558736+02:00;False|2024-04-03T18:53:40.5084714+02:00;False|2024-04-03T18:52:58.5201680+02:00;</History>
<History>True|2024-10-29T13:34:44.2509436Z||;False|2024-04-05T08:22:12.1466170+02:00||;False|2024-04-04T09:20:19.1194551+02:00||;False|2024-04-04T07:54:11.6078436+02:00||;False|2024-04-03T18:57:56.8357860+02:00||;False|2024-04-03T18:57:31.1394991+02:00||;False|2024-04-03T18:56:30.3461610+02:00||;False|2024-04-03T18:55:50.6292479+02:00||;False|2024-04-03T18:54:46.2558736+02:00||;False|2024-04-03T18:53:40.5084714+02:00||;False|2024-04-03T18:52:58.5201680+02:00||;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>
+17 -2
View File
@@ -1,5 +1,20 @@
Per installare il simulatore come servizio impiegare nssm come gestore servizio.
Per installare come servizio impiegare nssm come gestore servizio.
IN particolare installare con
nssm.exe install MP-MONO-SIM
nssm.exe install MP-MONO-SIM
nota compilazione: aggiunta forzatura progetto a 64bit:
- vedere yaml
# creazione installer WIX
- dotnet build $env:INST_NAME/$env:INST_NAME.wixproj -p:Configuration=$env:APP_CONF -p:Platform=x64
- vedere wixproject
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
<SuppressPdbOutput>true</SuppressPdbOutput>
</PropertyGroup>
+9 -6
View File
@@ -7,7 +7,8 @@
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Redis": "localhost:26379, serviceName=devel, DefaultDatabase=15, connectTimeout=5000, syncTimeout=5000, asyncTimeout=5000, abortConnect=false, ssl=false, allowAdmin=true"
"Redis": "localhost:6379, DefaultDatabase=14, connectTimeout=5000, syncTimeout=5000, asyncTimeout=5000, abortConnect=false, ssl=false, allowAdmin=true"
//"Redis": "redis.ufficio:26379, serviceName=devel, DefaultDatabase=14, connectTimeout=5000, syncTimeout=5000, asyncTimeout=5000, abortConnect=false, ssl=false, allowAdmin=true"
},
"DbConfig": {
"Server": "localhost",
@@ -18,10 +19,10 @@
"MailKit": {
"SMTP": {
"Address": "smtp.gmail.com",
"Port": "465",
"Account": "steamwarebot@gmail.com",
"Password": "drmfsls16",
"SenderEmail": "steamwarebot@gmail.com",
"Port": "587",
"Account": "services@steamware.net",
"Password": "rzdwvdhvyxtbrzoq",
"SenderEmail": "services@steamware.net",
"SenderName": "Steamware Email BOT"
}
}
@@ -30,6 +31,8 @@
"AppName": "Maat.Runner",
"StepSec": 60,
"MinSaveIntSec": 15,
"JobConfigFile": "JobConfig.json"
"JobConfigFile": "JobConfig.json",
"Prog.ApiUrl": "https://office.egalware.com/MP/PROG",
"SqlCmdTimeoutMinutes": 5
}
}
+4 -2
View File
@@ -4,10 +4,12 @@
{
"CallMode": "TaskList",
"DbList": [
"MoonPro",
"MoonPro_PROG",
"MoonPro_STATS"
],
"DbPasswd": "utente",
"DbUser": "password",
"DbPasswd": "db_password_here",
"DbUser": "db_user_here",
"ServerName": "SQL2016DEV"
}
]
@@ -0,0 +1,16 @@
{
"MsSqlJobs": {
"ServerList": [
{
"CallMode": "TaskList",
"DbList": [
"MoonPro_PROG",
"MoonPro_STATS"
],
"DbPasswd": "viadante16",
"DbUser": "steamware",
"ServerName": "SQL2016DEV"
}
]
}
}
+15
View File
@@ -0,0 +1,15 @@
{
"MsSqlJobs": {
"ServerList": [
{
"CallMode": "TaskList",
"DbList": [
"MoonPro_PROG"
],
"DbPasswd": "viadante16",
"DbUser": "steamware",
"ServerName": "SQL2016DEV"
}
]
}
}
+15
View File
@@ -0,0 +1,15 @@
{
"MsSqlJobs": {
"ServerList": [
{
"CallMode": "TaskList",
"DbList": [
"MoonPro_STATS"
],
"DbPasswd": "viadante16",
"DbUser": "steamware",
"ServerName": "SQL2016DEV"
}
]
}
}
+1
View File
@@ -4,6 +4,7 @@
{
"CallMode": "TaskList",
"DbList": [
"MoonPro_PROG",
"MoonPro_STATS"
],
"DbPasswd": "viadante16",
+1 -1
View File
@@ -1 +1 @@
1.1.
1.2.
+7 -1
View File
@@ -8,7 +8,13 @@
<ul>{{LAST-CHANGES}}</ul>
</li>
<li>
<b>v.1.* &rarr;</b>
<b>v.1.2.* &rarr;</b>
<ul>
<li>Aggiunta gestione task REST (es MP-PROG)</li>
</ul>
</li>
<li>
<b>v.1.1.* &rarr;</b>
<ul>
<li>Prima release applicazione</li>
<li>Installer WIX</li>
+14 -8
View File
@@ -1,6 +1,6 @@
<body>
<i>MagMan - Wood Warehouse Management System</i>
<h4>Versione: 1.0.2404.0412</h4>
<i>Maat.Installer - Manager for Application & Applicative Task</i>
<h4>Versione: 1.2.2507.2112</h4>
<br /> Note di rilascio:
<ul>
<li>
@@ -8,20 +8,26 @@
<ul>{{LAST-CHANGES}}</ul>
</li>
<li>
<b>v.1.* &rarr;</b>
<b>v.1.2.* &rarr;</b>
<ul>
<li>Prima release dotnet6</li>
<li>Integrazione EFCore</li>
<li>Integrazione EgtB&W</li>
<li>Aggiunta gestione task REST (es MP-PROG)</li>
</ul>
</li>
<li>
<b>v.1.1.* &rarr;</b>
<ul>
<li>Prima release applicazione</li>
<li>Installer WIX</li>
<li>Integrazione processo gestione servizi</li>
</ul>
</li>
</ul>
<div>
<div style="float: left;">
<img src="logoSteamware.png" />
<img src="LogoEgw.png" />
</div>
<div style="float: right;">
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2021</a>
<a href="https://www.egalware.net/support" target="_blank">&copy; EgalWare 2021-2025</a>
</div>
</div>
</body>
+1 -1
View File
@@ -1 +1 @@
1.0.2404.0412
1.2.2507.2112
+3 -3
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>1.0.2404.0412</version>
<url>http://nexus.steamware.net/repository/SWS/MagMan/stable/0/MagMan.UI.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/MagMan/stable/0/ChangeLog.html</changelog>
<version>1.2.2507.2112</version>
<url>http://nexus.steamware.net/repository/SWS/Maat.Installer/stable/LAST/Maat.Installer.msi</url>
<changelog>http://nexus.steamware.net/repository/SWS/Maat.Installer/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
</item>