schangxiang@126.com
2025-04-29 e71bc24daa8f00768787e18f5daba09128abfc62
HIAWms/server/src/CMS.Plugin.HIAWms/ProjectService/HIAWmsProjectService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,165 @@
using CMS.Plugin.FlowManagement.Abstractions.FlowBusiness;
using CMS.Plugin.HIAWms.Apis;
using CMS.Plugin.HIAWms.Application.Contracts.Dtos.WmsContainers;
using CMS.Plugin.HIAWms.Domain.WmsContainers;
using CMS.Plugin.HIAWms.Jobs;
using CMS.Project;
using CMS.Project.Abstractions;
using CMS.Unit.RuntimeValue.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Uow;
namespace CMS.Plugin.HIAWms.ProjectService
{
    /// <summary>
    /// å·¥ç¨‹æœåŠ¡ï¼Œå’Œå·¥ç¨‹å…³è”çš„åŽå°æœåŠ¡ï¼Œå½“<see cref="IProjectServiceRunner"/>以当前Key调用时会被执行
    /// </summary>
    public class HIAWmsProjectService : BaseProjectService
    {
        private IServiceProvider _serviceProvider;
        private readonly ILogger<HIAWmsProjectService> _logger;
        private readonly IVariableDataCache _variableDataCache;
        private FlowVariableChannelListener _channelListener;
        private Dictionary<string, string> _monitorVariableNames;
        /// <summary>
        /// æœåŠ¡çš„Key,唯一,供<see cref="IProjectServiceRunner"/>使用
        /// </summary>
        public override string Key => "HIAWms";
        /// <summary>
        /// æœåŠ¡æè¿°ï¼Œæ˜¾ç¤ºåœ¨æœåŠ¡åˆ—è¡¨UI上的名称
        /// </summary>
        public override string Description => "HIAWms服务";
        /// <summary>
        /// å¯ç”¨æŽˆæƒ
        /// </summary>
        public override bool AuthRequired => false;
        /// <summary>
        /// Initializes a new instance of the <see cref="HIAWmsProjectService"/> class.
        /// </summary>
        /// <param name="logger">The logger.</param>
        /// <param name="variableDataCache">The variable data cache.</param>
        public HIAWmsProjectService(IServiceProvider serviceProvider, ILogger<HIAWmsProjectService> logger, IVariableDataCache variableDataCache)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
            _variableDataCache = variableDataCache;
        }
        /// <summary>
        /// å¼€å¯æœåŠ¡
        /// </summary>
        /// <param name="serviceProvider">具有工程上下文的实例</param>
        public override async Task StartAsync(IServiceProvider serviceProvider)
        {
            if (State == ProjectServiceState.Started)
            {
                return;
            }
            // ç›‘听变量
            _monitorVariableNames = new Dictionary<string, string>
            {
                { "HIAWms_Variable1", "监听变量1" },
                { "HIAWms_Variable2", "监听变量2" }
            };
            // åˆ›å»ºé€šé“监听
            _channelListener?.Token?.Dispose();
            _channelListener = new FlowVariableChannelListener(_logger, _variableDataCache);
            _channelListener.CreateChannel(Key, waitListener: false, timeout: TimeSpan.FromSeconds(30), variableFilter: _monitorVariableNames.Keys.ToHashSet());
            _channelListener.TagChanged += OnTagValueChanged;
            await base.StartAsync(serviceProvider);
        }
        /// <summary>
        /// åœæ­¢æœåŠ¡
        /// </summary>
        /// <param name="serviceProvider">具有工程上下文的实例</param>
        public override async Task StopAsync(IServiceProvider serviceProvider)
        {
            if (_channelListener != null)
            {
                // é‡Šæ”¾ç›‘听
                _channelListener.TagChanged -= OnTagValueChanged;
                _channelListener.Token.Dispose();
                _channelListener = null;
            }
            // ä½¿ç”¨åŽå°ä½œä¸šå¼‚步处理
            //await _serviceProvider.GetRequiredService<IBackgroundJobManager>().EnqueueAsync(new HIAWmsArgs
            //{
            //    Subject = "HIAWms_Subject",
            //    Body = "HIAWms_Body",
            //});
            await base.StopAsync(serviceProvider);
        }
        /// <summary>
        /// Called when [tag value changed].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="TagChangedEventArgs"/> instance containing the event data.</param>
        private async void OnTagValueChanged(object sender, TagChangedEventArgs e)
        {
            var changeds = e.Changeds.Where(x => _monitorVariableNames != null && _monitorVariableNames.ContainsKey(x.Name));
            if (!changeds.Any())
            {
                return;
            }
            foreach (var changed in changeds)
            {
                var oldValue = changed.Old?.Value;
                var newValue = changed.New?.Value;
                var traceId = e.TraceId;
                _logger.LogInformation($"{changed.Name} å˜é‡å€¼å‘生变化,旧值{oldValue}=新值{newValue},TraceId={traceId}");
                // TODO: å¤„理变量值变化
                // Tips:https://cms-docs.shengyc.com/cms/api/%E5%90%8E%E7%AB%AF#3-%E5%8F%98%E9%87%8F%E6%A8%A1%E5%9D%97
                /* è¯´æ˜Žï¼šé€šè¿‡è®¢é˜… IVariableDataCache.TagChanged äº‹ä»¶ï¼Œæ‚¨å¯ä»¥å®žæ—¶ç›‘控变量的变化。此事件会传递所有变量至事件处理函数,因此,业务层需在函数中筛选关注的变量。
                    æ³¨æ„äº‹é¡¹ï¼š
                    ï¼ˆ1)性能影响: å‘布事件时,事件的发送者将阻塞流程。因此,强烈建议避免在事件处理函数中执行 I/ O æ“ä½œã€HTTP æŽ¥å£è®¿é—®æˆ–其他耗时操作,以防止对系统性能产生严重影响,导致整个系统响应延迟。
                    ï¼ˆ2)高频率触发: ç”±äºŽäº‹ä»¶è®¢é˜…了全量变量,触发频率可能非常高。
                    ï¼ˆ3)异步处理: é‰´äºŽäº‹ä»¶è§¦å‘频率很高,建议业务层在筛选关注变量后,使用 Task å¯åŠ¨æ–°çº¿ç¨‹å¤„ç†ä¸šåŠ¡é€»è¾‘ï¼Œä»¥é¿å…é˜»å¡žæ ¸å¿ƒçš„å˜é‡ç›‘å¬åŠŸèƒ½ï¼Œå®žçŽ°ä¸šåŠ¡å±‚ä¸Žå¹³å°åŸºåº§çš„è§£è€¦ã€‚
                    ï¼ˆ4)并发管理: å¦‚果业务层并发量大,必须优化代码设计和实施,以减少在高并发情况下的系统资源消耗,防止系统性能问题。
                    ï¼ˆ5)代码安全: å®‰è£…并使用 CMS.CodeAnalysis åˆ†æžå™¨æ¥åˆ†æž IVariableDataCache.TagChanged çš„使用情况。该工具能在使用不当时提供编译错误,帮助您提高代码质量。*/
                _ = Task.Run(async () =>
                {
                    // ä¾‹1:同步处理
                    //await ProcessAsync();
                    // ä¾‹2:调用外部API
                    //await ExecuteExternalApiAsync();
                });
            }
        }
        /// <summary>
        /// Processes the asynchronous.
        /// </summary>
        private async Task ProcessAsync()
        {
            using var scope = _serviceProvider.CreateScope();
            var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
            using var uow = unitOfWorkManager.Begin(requiresNew: true);
            var wmscontainerRepository = scope.ServiceProvider.GetRequiredService<IWmsContainerRepository>();
            var count = await wmscontainerRepository.GetCountAsync();
            // å¦‚果有更新数据库操作,需提交保存
            // await uow.SaveChangesAsync();
            _logger.LogInformation($"ProcessAsync,Count={count}");
        }
    }
}