using System;
using System.Collections.Generic;
using System.Text;
using Dapper;
using MySqlConnector;
using CncModels.Entity;
using log4net;
namespace CncCollector.Core
{
///
/// 采集数据批量写入器。
/// 负责写入采集结构化记录、原始JSON日志,更新机床和地址实时状态。
///
public class CollectRecordWriter
{
private static readonly ILog _log = LogManager.GetLogger(typeof(CollectRecordWriter));
///
/// 批量写入采集记录并更新相关状态
///
/// 业务库连接字符串
/// 日志库连接字符串
/// 采集记录列表
/// 原始JSON字符串
/// 采集地址ID
/// 请求开始时间
/// 响应耗时(毫秒)
/// 是否采集成功
/// 错误信息(失败时)
public static long WriteBatch(string businessConnStr, string logConnStr,
List records, string rawJson, int collectAddressId,
DateTime requestTime, long? responseDurationMs, bool isSuccess, string errorMessage, int? statusCode = null)
{
var now = DateTime.Now;
long lastRawLogId = 0;
// 1. 写入原始JSON到日志库
try
{
using (var conn = new MySqlConnection(logConnStr))
{
conn.Open();
conn.Execute(@"INSERT INTO log_collect_raw (collect_address_id, request_time, response_time, response_duration, is_success, status_code, raw_json, error_message, created_at)
VALUES (@CollectAddressId, @RequestTime, @ResponseTime, @ResponseDuration, @IsSuccess, @StatusCode, @RawJson, @ErrorMessage, @CreatedAt)",
new
{
CollectAddressId = collectAddressId,
RequestTime = requestTime,
ResponseTime = now,
ResponseDuration = responseDurationMs,
IsSuccess = isSuccess ? 1 : 0,
StatusCode = statusCode ?? (isSuccess ? (int?)200 : null),
RawJson = rawJson ?? "",
ErrorMessage = errorMessage ?? (string)null,
CreatedAt = now
});
// 记录刚插入的 raw_log 的自增ID
try
{
lastRawLogId = conn.ExecuteScalar("SELECT LAST_INSERT_ID();");
}
catch { lastRawLogId = 0; }
}
}
catch (Exception ex)
{
// 数据库不可用时,详细错误信息通过log4net写入本地日志文件,确保问题可追溯
_log.Error($"写入原始JSON日志失败(地址ID={collectAddressId}, 成功={isSuccess}): {errorMessage}", ex);
}
if (!isSuccess || records == null || records.Count == 0) return lastRawLogId;
// 2. 批量写入采集结构化记录到业务库
try
{
using (var conn = new MySqlConnection(businessConnStr))
{
conn.Open();
using (var tran = conn.BeginTransaction())
{
try
{
foreach (var r in records)
{
conn.Execute(@"INSERT INTO cnc_collect_record (machine_id, collect_time, device_time, program_name, part_count,
device_status, run_status, operate_mode,
power_on_time, run_time, extra_data, created_at)
VALUES (@MachineId, @CollectTime, @DeviceTime, @ProgramName, @PartCount,
@DeviceStatus, @RunStatus, @OperateMode,
@PowerOnTime, @RunTime, @ExtraData, @CreatedAt)",
new
{
r.MachineId,
CollectTime = r.CollectTime,
DeviceTime = r.DeviceTime,
ProgramName = r.ProgramName ?? (string)null,
PartCount = r.PartCount,
DeviceStatus = r.DeviceStatus ?? (string)null,
RunStatus = r.RunStatus ?? (string)null,
OperateMode = r.OperateMode ?? (string)null,
PowerOnTime = r.PowerOnTime,
RunTime = r.RunTime,
ExtraData = r.ExtraData ?? (string)null,
CreatedAt = now
}, tran);
}
tran.Commit();
}
catch
{
tran.Rollback();
throw;
}
}
// 3. 更新每台机床的实时状态字段
foreach (var r in records)
{
try
{
conn.Execute(@"UPDATE cnc_machine SET last_collect_time = @CollectTime,
last_device_status = @DeviceStatus, last_run_status = @RunStatus,
last_program_name = @ProgramName, last_part_count = @PartCount,
last_operate_mode = @OperateMode
WHERE id = @MachineId",
new
{
r.MachineId,
r.CollectTime,
DeviceStatus = r.DeviceStatus ?? (string)null,
RunStatus = r.RunStatus ?? (string)null,
ProgramName = r.ProgramName ?? (string)null,
r.PartCount,
OperateMode = r.OperateMode ?? (string)null
});
}
catch (Exception ex)
{
_log.Error($"更新机床实时状态失败(machine_id={r.MachineId})", ex);
}
}
// 4. 更新采集地址状态
try
{
conn.Execute(@"UPDATE cnc_collect_address SET last_collect_time = @Time, last_collect_status = 'success', fail_count = 0, updated_at = NOW()
WHERE id = @Id",
new { Time = now, Id = collectAddressId });
}
catch (Exception ex)
{
_log.Error($"更新采集地址状态失败(address_id={collectAddressId})", ex);
}
}
}
catch (Exception ex)
{
_log.Error($"批量写入采集记录失败(地址ID={collectAddressId})", ex);
}
return lastRawLogId;
}
///
/// 记录采集失败:更新采集地址的失败计数和状态
///
public static void RecordFailure(string businessConnStr, int collectAddressId, string errorMsg)
{
try
{
using (var conn = new MySqlConnection(businessConnStr))
{
conn.Execute(@"UPDATE cnc_collect_address SET last_collect_status = 'fail', fail_count = fail_count + 1, updated_at = NOW() WHERE id = @Id",
new { Id = collectAddressId });
}
}
catch (Exception ex)
{
_log.Error($"记录采集失败状态时出错(address_id={collectAddressId})", ex);
}
}
}
}