Files
zszq-trs/YLErpDAL/Helpers/KafkaProduceHelper.cs
T
tengyufan 336cc3d88b feat: 新增TRS合约日终Kafka推送
- 在日终任务的逐日循环中,于当日收盘、风险监控和日终文件生成完成后,
  按 valueDate 推送一条 TRS 合约全量快照;区间收盘逐日推送,空日推送空快照。
- 基于 eod_swap、trade、eod_swap_position、swap_position 组装合约字段,
  Kafka Key 使用 yyyy-MM-dd 格式的 valueDate。
- 新增带 Key 的 Kafka 发送重载;保留原有无 Key 发送及其吞异常行为,避免影响既有调用。
- 推送失败最多尝试 3 次;最终失败记录 Error 日志,并按 eod_swap.id 写入 push_status,
  空快照失败使用 record_id=0。
- 增加 ContractTopic 配置,默认及各部署环境使用 onederiv.trs.contract.v1。
- 增加定向单测,覆盖空快照、区间逐日推送、重试成功、三次失败和字段映射。
2026-08-25 16:07:21 +08:00

92 lines
3.7 KiB
C#

using Confluent.Kafka;
using Microsoft.Extensions.Options;
using System.Linq;
using YLErp.Abstract;
using YLErp.Model;
namespace YLErp.Helpers
{
public class KafkaProduceHelper: IKafkaProduce
{
private IProducer<string, string> _producer;
private readonly IYcLogger _logger;
public KafkaProduceHelper(IOptions<KafkaConfig> _kafkaConfig) {
_logger = LogFactory.GetLogger("KafkaProduceHelper");
var kfkconfig = _kafkaConfig.Value;
ProducerConfig config = new ProducerConfig();
config.BootstrapServers = kfkconfig.BootstrapServers;
config.Acks = (Acks)kfkconfig.Acks;
config.EnableIdempotence = kfkconfig.EnableIdempotence;
config.MaxInFlight = kfkconfig.MaxInFlight;
config.CompressionType = (CompressionType)kfkconfig.CompressionType;
config.MessageTimeoutMs = kfkconfig.MessageTimeoutMs;
_producer = new ProducerBuilder<string, string>(config).Build(); // 初始化生产者对象
}
public KafkaProduceHelper()
{
_logger = LogFactory.GetLogger("KafkaProduceHelper");
var bootstrapServers = Environment.GetEnvironmentVariable("KafkaConfig_BootstrapServers");
var batchSize = Environment.GetEnvironmentVariable("KafkaConfig_BatchSize");
var acks = Environment.GetEnvironmentVariable("KafkaConfig_Acks");
var enableIdempotence = Environment.GetEnvironmentVariable("KafkaConfig_EnableIdempotence");
var maxInFlight = Environment.GetEnvironmentVariable("KafkaConfig_MaxInFlight");
var compressionType = Environment.GetEnvironmentVariable("KafkaConfig_CompressionType");
var messageTimeoutMs = Environment.GetEnvironmentVariable("KafkaConfig_MessageTimeoutMs");
ProducerConfig config = new ProducerConfig();
config.BootstrapServers = bootstrapServers;
if (!string.IsNullOrEmpty(batchSize))
{
config.BatchSize = Convert.ToInt32(batchSize);
}
if (!string.IsNullOrEmpty(acks))
{
config.Acks = (Acks)(Convert.ToInt32(acks));
}
if (!string.IsNullOrEmpty(acks))
{
config.EnableIdempotence = Convert.ToBoolean(enableIdempotence);
}
if (!string.IsNullOrEmpty(maxInFlight))
{
config.MaxInFlight = Convert.ToInt32(maxInFlight);
}
if (!string.IsNullOrEmpty(compressionType))
{
config.CompressionType = (CompressionType)(Convert.ToInt32(compressionType));
}
if (!string.IsNullOrEmpty(messageTimeoutMs))
{
config.MessageTimeoutMs = Convert.ToInt32(messageTimeoutMs);
}
_producer = new ProducerBuilder<string, string>(config).Build(); // 初始化生产者对象
}
public void Produce(string topic,string message)
{
try
{
ProduceCore(topic, null, message);
}
catch (Exception ex)
{
_logger.Error($"Topic:{topic} send failed",ex);
}
}
public void Produce(string topic, string key, string message)
{
ProduceCore(topic, key, message);
}
private void ProduceCore(string topic, string key, string message)
{
var kafkaMessage = new Message<string, string>
{
Key = key,
Value = message
};
_producer.ProduceAsync(topic, kafkaMessage).GetAwaiter().GetResult();
}
}
}