首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >每项工作相关/州

每项工作相关/州
EN

Stack Overflow用户
提问于 2022-02-15 07:33:58
回答 1查看 296关注 0票数 1

我在ASP.NET核心运行Hangfire。对于我们的其他项目,我们有在进行API调用时传递的CorrelationIds,以便能够链接调用者和被调用者。我们在TraceIdentifier内核中使用IHttpContextAccessor的ASP.NET。

不幸的是,ASP.NET Core在瞬态IHttpContextAccessor中获取作用域CorrelationId的技巧看起来并不适用于Hangfire作业执行。使用限定作用域的状态关联对象不能工作,因为它必须是瞬态的,才能与系统的其他部分(日志记录等)一起工作。

过去,我可以使用ServiceLocator反模式并在瞬态服务中解析作用域状态对象。在最新的ASP.NET内核中,它不再受支持,并且抛出了一个异常,这使得系统速度太慢,因为抛出了大量的异常。

有没有Hangfire已经提供的东西可以给我每个作业执行一个唯一的ID?

干杯。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-15 13:26:00

感谢jbl的评论,我再次审视了自己正在做的事情,并设法让它通过一个模棱两可的方法来工作。

我得到了瞬态保持器(基本上是重命名的HttpContextAccessor类):

代码语言:javascript
运行
复制
public class StateHolder
{
    private static AsyncLocal<ContextHolder> _contextCurrent = new AsyncLocal<ContextHolder>();

    public string State {
        get {
            return _contextCurrent.Value?.Context;
        }
        set {
            var holder = _contextCurrent.Value;
            if (holder != null)
            {
                holder.Context = null;
            }

            if (value != null)
            {
                _contextCurrent.Value = new ContextHolder { Context = value };
            }
        }
    }

    private class ContextHolder
    {
        public string Context;
    }
}

然后在Hangfire我把它连接到激活

代码语言:javascript
运行
复制
public class LoggingActivator : JobActivator
{
    private readonly IServiceScopeFactory _serviceScopeFactory;
    private readonly ContextAccessor _contextAccessor;

    public LoggingActivator([NotNull] IServiceScopeFactory serviceScopeFactory, ContextAccessor contextAccessor)
    {
        _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
        _contextAccessor = contextAccessor;
    }

    public override JobActivatorScope BeginScope(JobActivatorContext context)
    {
        return new LoggingActivatorScope(_serviceScopeFactory.CreateScope(), _contextAccessor);
    }
}

代码语言:javascript
运行
复制
public class LoggingActivatorScope : JobActivatorScope
{
    private readonly IServiceScope _serviceScope;
    private readonly ContextAccessor _contextAccessor;

    public LoggingActivatorScope(
        [NotNull] IServiceScope serviceScope,
        ContextAccessor contextAccessor)
    {
        _serviceScope = serviceScope ?? throw new ArgumentNullException(nameof(serviceScope));
        _contextAccessor = contextAccessor;
    }

    public override object Resolve(Type type)
    {
        _contextAccessor.Context = Guid.NewGuid().ToString();

        return ActivatorUtilities.GetServiceOrCreateInstance(_serviceScope.ServiceProvider, type);
    }

    public override void DisposeScope()
    {
        _serviceScope.Dispose();
    }
}

看上去挺好的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71122602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档