Files
2026-08-19 19:27:41 +02:00

146 lines
5.8 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace FileInterface.Scheduler
{
public sealed class CronJobExecutor
{
private readonly ICustomFunctionInvoker _invoker;
private readonly JobLog _log;
public CronJobExecutor(ICustomFunctionInvoker invoker, JobLog log)
{
_invoker = invoker;
_log = log;
}
public void Execute(CronJobConfig job)
{
if (job.CallOnceWithoutFile)
{
ExecuteSingle(job, null);
return;
}
if (!Directory.Exists(job.SourceDirectory))
{
_log.Error(job, "Source directory does not exist: " + job.SourceDirectory);
return;
}
SearchOption option = job.IncludeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
string[] files;
try
{
files = Directory.GetFiles(job.SourceDirectory, String.IsNullOrWhiteSpace(job.SearchPattern) ? "*.*" : job.SearchPattern, option)
.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)
.ToArray();
}
catch (Exception ex)
{
_log.Error(job, "Cannot enumerate source files: " + ex.Message);
return;
}
_log.Info(job, "Found " + files.Length + " file(s).");
foreach (string file in files)
{
try { ExecuteSingle(job, file); }
catch (Exception ex) { _log.Error(job, "File failed: " + file + " - " + ex.Message); }
}
}
private void ExecuteSingle(CronJobConfig job, string file)
{
string rawContent = "";
string processedContent = "";
if (file != null)
{
// Opening with FileShare.ReadWrite prevents common producer/consumer lock issues.
using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var reader = new StreamReader(stream, Encoding.UTF8, true))
rawContent = reader.ReadToEnd();
processedContent = ProcessContent(rawContent, job.RemoveEmptyLines, job.JoinSeparator);
}
string[] inArgs = (job.InArgs ?? new List<string>())
.Select(arg => Expand(arg, job, file, rawContent, processedContent))
.ToArray();
_log.Info(job, "Calling CustomFunction '" + job.CustomFunction + "' with " + inArgs.Length + " inArg(s)" + (file == null ? "." : " for " + Path.GetFileName(file) + "."));
CustomFunctionCallResult result = _invoker.Invoke(job.CustomFunction, inArgs);
if (result == null) result = CustomFunctionCallResult.Fail("Invoker returned null.");
if (!result.Success)
{
_log.Error(job, "CustomFunction failed: " + result.Message);
return;
}
_log.Info(job, "CustomFunction succeeded: " + result.Message);
if (file != null && job.MoveFileAfterSuccess)
{
string movedTo = MoveProcessedFile(file, job.MoveTargetDirectory, job.OverwriteTargetFile);
_log.Info(job, "Moved file to: " + movedTo);
}
}
private static string ProcessContent(string text, bool removeEmptyLines, string separator)
{
if (!removeEmptyLines) return text ?? "";
string[] lines = (text ?? "").Replace("\r\n", "\n").Replace('\r', '\n').Split('\n');
return String.Join(separator ?? ";", lines.Where(l => !String.IsNullOrWhiteSpace(l)).Select(l => l.Trim()));
}
private static string Expand(string template, CronJobConfig job, string file, string rawContent, string processedContent)
{
string value = template ?? "";
string fullPath = file ?? "";
string fileName = file == null ? "" : Path.GetFileName(file);
string extension = file == null ? "" : Path.GetExtension(file);
string directory = file == null ? "" : Path.GetDirectoryName(file);
return value
.Replace("{{CONTENT}}", processedContent ?? "")
.Replace("{{RAW_CONTENT}}", rawContent ?? "")
.Replace("{{FILE_NAME}}", fileName ?? "")
.Replace("{{FILE_PATH}}", fullPath)
.Replace("{{FILE_DIR}}", directory ?? "")
.Replace("{{FILE_EXT}}", extension ?? "")
.Replace("{{JOB_NAME}}", job.Name ?? "")
.Replace("{{NOW}}", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffK"));
}
private static string MoveProcessedFile(string source, string targetDirectory, bool overwrite)
{
Directory.CreateDirectory(targetDirectory);
string target = Path.Combine(targetDirectory, Path.GetFileName(source));
if (File.Exists(target))
{
if (overwrite) File.Delete(target);
else
{
string name = Path.GetFileNameWithoutExtension(source);
string ext = Path.GetExtension(source);
target = Path.Combine(targetDirectory, name + "_" + DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + ext);
int i = 1;
while (File.Exists(target))
{
target = Path.Combine(targetDirectory, name + "_" + DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + "_" + i + ext);
i++;
}
}
}
File.Move(source, target);
return target;
}
}
}