Commit b69e355e authored by yangxiaodong's avatar yangxiaodong

Fix Message Received Store Bugs.

parent 03ca87c0
...@@ -41,12 +41,31 @@ namespace DotNetCore.CAP.EntityFrameworkCore ...@@ -41,12 +41,31 @@ namespace DotNetCore.CAP.EntityFrameworkCore
return OperateResult.Success; return OperateResult.Success;
} }
public async Task<OperateResult> ChangeSentMessageStateAsync(CapSentMessage message, string status, bool autoSaveChanges = true)
{
Context.Attach(message);
message.LastRun = DateTime.Now;
message.StatusName = status;
try
{
if (autoSaveChanges)
{
await Context.SaveChangesAsync();
}
}
catch (DbUpdateConcurrencyException ex)
{
return OperateResult.Failed(new OperateError() { Code = "DbUpdateConcurrencyException", Description = ex.Message });
}
return OperateResult.Success;
}
/// <summary> /// <summary>
/// First Enqueued Message. /// First Enqueued Message.
/// </summary> /// </summary>
public async Task<CapSentMessage> GetNextSentMessageToBeEnqueuedAsync() public async Task<CapSentMessage> GetNextSentMessageToBeEnqueuedAsync()
{ {
return await SentMessages.FirstOrDefaultAsync(x => x.StateName == StateName.Enqueued); return await SentMessages.FirstOrDefaultAsync(x => x.StatusName == StatusName.Enqueued);
} }
/// <summary> /// <summary>
...@@ -105,6 +124,30 @@ namespace DotNetCore.CAP.EntityFrameworkCore ...@@ -105,6 +124,30 @@ namespace DotNetCore.CAP.EntityFrameworkCore
return OperateResult.Success; return OperateResult.Success;
} }
public async Task<OperateResult> ChangeReceivedMessageStateAsync(CapReceivedMessage message, string status, bool autoSaveChanges = true)
{
Context.Attach(message);
message.LastRun = DateTime.Now;
message.StatusName = status;
try
{
if (autoSaveChanges)
{
await Context.SaveChangesAsync();
}
}
catch (DbUpdateConcurrencyException ex)
{
return OperateResult.Failed(new OperateError() { Code = "DbUpdateConcurrencyException", Description = ex.Message });
}
return OperateResult.Success;
}
public async Task<CapReceivedMessage> GetNextReceivedMessageToBeExcuted()
{
return await ReceivedMessages.FirstOrDefaultAsync(x => x.StatusName == StatusName.Enqueued);
}
/// <summary> /// <summary>
/// Updates the specified <paramref name="message"/> in the message store. /// Updates the specified <paramref name="message"/> in the message store.
/// </summary> /// </summary>
...@@ -127,5 +170,6 @@ namespace DotNetCore.CAP.EntityFrameworkCore ...@@ -127,5 +170,6 @@ namespace DotNetCore.CAP.EntityFrameworkCore
return OperateResult.Failed(new OperateError() { Code = "DbUpdateConcurrencyException", Description = ex.Message }); return OperateResult.Failed(new OperateError() { Code = "DbUpdateConcurrencyException", Description = ex.Message });
} }
} }
} }
} }
\ No newline at end of file
...@@ -39,12 +39,12 @@ namespace DotNetCore.CAP.EntityFrameworkCore ...@@ -39,12 +39,12 @@ namespace DotNetCore.CAP.EntityFrameworkCore
modelBuilder.Entity<CapSentMessage>(b => modelBuilder.Entity<CapSentMessage>(b =>
{ {
b.HasKey(m => m.Id); b.HasKey(m => m.Id);
b.Property(p => p.StateName).HasMaxLength(50); b.Property(p => p.StatusName).HasMaxLength(50);
}); });
modelBuilder.Entity<CapReceivedMessage>(b => modelBuilder.Entity<CapReceivedMessage>(b =>
{ {
b.Property(p => p.StateName).HasMaxLength(50); b.Property(p => p.StatusName).HasMaxLength(50);
}); });
} }
} }
......
...@@ -90,7 +90,7 @@ namespace DotNetCore.CAP.Kafka ...@@ -90,7 +90,7 @@ namespace DotNetCore.CAP.Kafka
if (message != null) if (message != null)
{ {
var sp = Stopwatch.StartNew(); var sp = Stopwatch.StartNew();
message.StateName = StateName.Processing; message.StatusName = StatusName.Processing;
await messageStore.UpdateSentMessageAsync(message); await messageStore.UpdateSentMessageAsync(message);
var jobResult = ExecuteJob(message.KeyName, message.Content); var jobResult = ExecuteJob(message.KeyName, message.Content);
...@@ -104,7 +104,7 @@ namespace DotNetCore.CAP.Kafka ...@@ -104,7 +104,7 @@ namespace DotNetCore.CAP.Kafka
else else
{ {
//TODO : the state will be deleted when release. //TODO : the state will be deleted when release.
message.StateName = StateName.Succeeded; message.StatusName = StatusName.Succeeded;
await messageStore.UpdateSentMessageAsync(message); await messageStore.UpdateSentMessageAsync(message);
_logger.JobExecuted(sp.Elapsed.TotalSeconds); _logger.JobExecuted(sp.Elapsed.TotalSeconds);
......
...@@ -26,7 +26,6 @@ namespace DotNetCore.CAP.RabbitMQ ...@@ -26,7 +26,6 @@ namespace DotNetCore.CAP.RabbitMQ
public RabbitJobProcessor( public RabbitJobProcessor(
IOptions<CapOptions> capOptions, IOptions<CapOptions> capOptions,
IOptions<RabbitMQOptions> rabbitMQOptions, IOptions<RabbitMQOptions> rabbitMQOptions,
IOptions<RabbitMQOptions> options,
ILogger<RabbitJobProcessor> logger, ILogger<RabbitJobProcessor> logger,
IServiceProvider provider) IServiceProvider provider)
{ {
...@@ -88,7 +87,7 @@ namespace DotNetCore.CAP.RabbitMQ ...@@ -88,7 +87,7 @@ namespace DotNetCore.CAP.RabbitMQ
if (message != null) if (message != null)
{ {
var sp = Stopwatch.StartNew(); var sp = Stopwatch.StartNew();
message.StateName = StateName.Processing; message.StatusName = StatusName.Processing;
await messageStore.UpdateSentMessageAsync(message); await messageStore.UpdateSentMessageAsync(message);
var jobResult = ExecuteJob(message.KeyName, message.Content); var jobResult = ExecuteJob(message.KeyName, message.Content);
...@@ -102,7 +101,7 @@ namespace DotNetCore.CAP.RabbitMQ ...@@ -102,7 +101,7 @@ namespace DotNetCore.CAP.RabbitMQ
else else
{ {
//TODO : the state will be deleted when release. //TODO : the state will be deleted when release.
message.StateName = StateName.Succeeded; message.StatusName = StatusName.Succeeded;
await messageStore.UpdateSentMessageAsync(message); await messageStore.UpdateSentMessageAsync(message);
_logger.JobExecuted(sp.Elapsed.TotalSeconds); _logger.JobExecuted(sp.Elapsed.TotalSeconds);
......
using System.Collections.Generic; using System;
using System.Collections.Generic;
namespace DotNetCore.CAP.Abstractions namespace DotNetCore.CAP.Abstractions
{ {
...@@ -9,11 +10,11 @@ namespace DotNetCore.CAP.Abstractions ...@@ -9,11 +10,11 @@ namespace DotNetCore.CAP.Abstractions
{ {
/// <summary> /// <summary>
/// Selects a set of <see cref="ConsumerExecutorDescriptor"/> candidates for the current message associated with /// Selects a set of <see cref="ConsumerExecutorDescriptor"/> candidates for the current message associated with
/// <paramref name="context"/>. /// <paramref name="provider"/>.
/// </summary> /// </summary>
/// <param name="context">The <see cref="CapStartContext"/> associated with the current message.</param> /// <param name="provider"> <see cref="IServiceProvider"/>.</param>
/// <returns>A set of <see cref="ConsumerExecutorDescriptor"/> candidates or <c>null</c>.</returns> /// <returns>A set of <see cref="ConsumerExecutorDescriptor"/> candidates or <c>null</c>.</returns>
IReadOnlyList<ConsumerExecutorDescriptor> SelectCandidates(CapStartContext context); IReadOnlyList<ConsumerExecutorDescriptor> SelectCandidates(IServiceProvider provider);
/// <summary> /// <summary>
/// Selects the best <see cref="ConsumerExecutorDescriptor"/> candidate from <paramref name="candidates"/> for the /// Selects the best <see cref="ConsumerExecutorDescriptor"/> candidate from <paramref name="candidates"/> for the
......
...@@ -5,6 +5,7 @@ using System.Threading.Tasks; ...@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using DotNetCore.CAP.Infrastructure; using DotNetCore.CAP.Infrastructure;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace DotNetCore.CAP namespace DotNetCore.CAP
...@@ -14,20 +15,23 @@ namespace DotNetCore.CAP ...@@ -14,20 +15,23 @@ namespace DotNetCore.CAP
/// </summary> /// </summary>
public class DefaultBootstrapper : IBootstrapper public class DefaultBootstrapper : IBootstrapper
{ {
private IApplicationLifetime _appLifetime; private readonly ILogger<DefaultBootstrapper> _logger;
private CancellationTokenSource _cts; private readonly IApplicationLifetime _appLifetime;
private CancellationTokenRegistration _ctsRegistration; private readonly CancellationTokenSource _cts;
private readonly CancellationTokenRegistration _ctsRegistration;
private Task _bootstrappingTask; private Task _bootstrappingTask;
public DefaultBootstrapper( public DefaultBootstrapper(
ILogger<DefaultBootstrapper> logger,
IOptions<CapOptions> options, IOptions<CapOptions> options,
ICapMessageStore storage, ICapMessageStore storage,
IApplicationLifetime appLifetime, IApplicationLifetime appLifetime,
IServiceProvider provider) IServiceProvider provider)
{ {
_logger = logger;
_appLifetime = appLifetime;
Options = options.Value; Options = options.Value;
Storage = storage; Storage = storage;
_appLifetime = appLifetime;
Provider = provider; Provider = provider;
Servers = Provider.GetServices<IProcessingServer>(); Servers = Provider.GetServices<IProcessingServer>();
...@@ -39,8 +43,9 @@ namespace DotNetCore.CAP ...@@ -39,8 +43,9 @@ namespace DotNetCore.CAP
{ {
_bootstrappingTask?.Wait(); _bootstrappingTask?.Wait();
} }
catch (OperationCanceledException) catch (OperationCanceledException ex)
{ {
_logger.ExpectedOperationCanceledException(ex);
} }
}); });
} }
...@@ -74,8 +79,9 @@ namespace DotNetCore.CAP ...@@ -74,8 +79,9 @@ namespace DotNetCore.CAP
{ {
item.Start(); item.Start();
} }
catch (Exception) catch (Exception ex)
{ {
_logger.ServerStartedError(ex);
} }
} }
......
...@@ -15,6 +15,14 @@ namespace DotNetCore.CAP ...@@ -15,6 +15,14 @@ namespace DotNetCore.CAP
/// <param name="message">The message to create in the store.</param> /// <param name="message">The message to create in the store.</param>
Task<OperateResult> StoreSentMessageAsync(CapSentMessage message); Task<OperateResult> StoreSentMessageAsync(CapSentMessage message);
/// <summary>
/// Change <see cref="CapSentMessage"/> model status name.
/// </summary>
/// <param name="message">The type of <see cref="CapSentMessage"/>.</param>
/// <param name="statusName">The status name.</param>
/// <returns></returns>
Task<OperateResult> ChangeSentMessageStateAsync(CapSentMessage message, string statusName, bool autoSaveChanges = true);
/// <summary> /// <summary>
/// Fetches the next message to be executed. /// Fetches the next message to be executed.
/// </summary> /// </summary>
...@@ -33,6 +41,9 @@ namespace DotNetCore.CAP ...@@ -33,6 +41,9 @@ namespace DotNetCore.CAP
/// <param name="message">The message to delete in the store.</param> /// <param name="message">The message to delete in the store.</param>
Task<OperateResult> RemoveSentMessageAsync(CapSentMessage message); Task<OperateResult> RemoveSentMessageAsync(CapSentMessage message);
/// <summary> /// <summary>
/// Creates a new message in a store as an asynchronous operation. /// Creates a new message in a store as an asynchronous operation.
/// </summary> /// </summary>
...@@ -40,6 +51,19 @@ namespace DotNetCore.CAP ...@@ -40,6 +51,19 @@ namespace DotNetCore.CAP
/// <returns></returns> /// <returns></returns>
Task<OperateResult> StoreReceivedMessageAsync(CapReceivedMessage message); Task<OperateResult> StoreReceivedMessageAsync(CapReceivedMessage message);
/// <summary>
/// Change <see cref="CapReceivedMessage"/> model status name.
/// </summary>
/// <param name="message">The type of <see cref="CapReceivedMessage"/>.</param>
/// <param name="statusName">The status name.</param>
/// <returns></returns>
Task<OperateResult> ChangeReceivedMessageStateAsync(CapReceivedMessage message, string statusName, bool autoSaveChanges = true);
/// <summary>
/// Fetches the next message to be executed.
/// </summary>
Task<CapReceivedMessage> GetNextReceivedMessageToBeExcuted();
/// <summary> /// <summary>
/// Updates a message in a store as an asynchronous operation. /// Updates a message in a store as an asynchronous operation.
/// </summary> /// </summary>
......
...@@ -48,7 +48,7 @@ namespace DotNetCore.CAP ...@@ -48,7 +48,7 @@ namespace DotNetCore.CAP
Content = content Content = content
}; };
message.StateName = StateName.Enqueued; message.StatusName = StatusName.Enqueued;
await _store.StoreSentMessageAsync(message); await _store.StoreSentMessageAsync(message);
WaitHandleEx.PulseEvent.Set(); WaitHandleEx.PulseEvent.Set();
......
...@@ -5,6 +5,7 @@ using System.Threading.Tasks; ...@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using DotNetCore.CAP.Abstractions; using DotNetCore.CAP.Abstractions;
using DotNetCore.CAP.Infrastructure; using DotNetCore.CAP.Infrastructure;
using DotNetCore.CAP.Internal; using DotNetCore.CAP.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
...@@ -20,12 +21,10 @@ namespace DotNetCore.CAP ...@@ -20,12 +21,10 @@ namespace DotNetCore.CAP
private readonly MethodMatcherCache _selector; private readonly MethodMatcherCache _selector;
private readonly CapOptions _options; private readonly CapOptions _options;
private readonly ICapMessageStore _messageStore;
private readonly CancellationTokenSource _cts; private readonly CancellationTokenSource _cts;
public event EventHandler<CapMessage> MessageReceieved; public event EventHandler<CapMessage> MessageReceieved;
private CapStartContext _context;
private Task _compositeTask; private Task _compositeTask;
private bool _disposed; private bool _disposed;
...@@ -34,7 +33,6 @@ namespace DotNetCore.CAP ...@@ -34,7 +33,6 @@ namespace DotNetCore.CAP
IConsumerInvokerFactory consumerInvokerFactory, IConsumerInvokerFactory consumerInvokerFactory,
IConsumerClientFactory consumerClientFactory, IConsumerClientFactory consumerClientFactory,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
ICapMessageStore messageStore,
MethodMatcherCache selector, MethodMatcherCache selector,
IOptions<CapOptions> options) IOptions<CapOptions> options)
{ {
...@@ -45,7 +43,6 @@ namespace DotNetCore.CAP ...@@ -45,7 +43,6 @@ namespace DotNetCore.CAP
_consumerInvokerFactory = consumerInvokerFactory; _consumerInvokerFactory = consumerInvokerFactory;
_consumerClientFactory = consumerClientFactory; _consumerClientFactory = consumerClientFactory;
_options = options.Value; _options = options.Value;
_messageStore = messageStore;
_cts = new CancellationTokenSource(); _cts = new CancellationTokenSource();
} }
...@@ -56,9 +53,7 @@ namespace DotNetCore.CAP ...@@ -56,9 +53,7 @@ namespace DotNetCore.CAP
public void Start() public void Start()
{ {
_context = new CapStartContext(_serviceProvider, _cts.Token); var matchs = _selector.GetCandidatesMethods(_serviceProvider);
var matchs = _selector.GetCandidatesMethods(_context);
var groupingMatchs = matchs.GroupBy(x => x.Value.Attribute.GroupOrExchange); var groupingMatchs = matchs.GroupBy(x => x.Value.Attribute.GroupOrExchange);
...@@ -86,30 +81,36 @@ namespace DotNetCore.CAP ...@@ -86,30 +81,36 @@ namespace DotNetCore.CAP
{ {
_logger.EnqueuingReceivedMessage(message.KeyName, message.Content); _logger.EnqueuingReceivedMessage(message.KeyName, message.Content);
var capMessage = new CapReceivedMessage(message) using (var scope = _serviceProvider.CreateScope())
{ {
StateName = StateName.Enqueued, var provider = scope.ServiceProvider;
Added = DateTime.Now var messageStore = provider.GetRequiredService<ICapMessageStore>();
};
_messageStore.StoreReceivedMessageAsync(capMessage).Wait();
ConsumerExecutorDescriptor executeDescriptor = null; var capMessage = new CapReceivedMessage(message)
{
StatusName = StatusName.Enqueued,
Added = DateTime.Now
};
messageStore.StoreReceivedMessageAsync(capMessage).Wait();
try ConsumerExecutorDescriptor executeDescriptor = null;
{
executeDescriptor = _selector.GetTopicExector(message.KeyName);
var consumerContext = new ConsumerContext(executeDescriptor, message); try
{
executeDescriptor = _selector.GetTopicExector(message.KeyName);
var invoker = _consumerInvokerFactory.CreateInvoker(consumerContext); var consumerContext = new ConsumerContext(executeDescriptor, message);
invoker.InvokeAsync(); var invoker = _consumerInvokerFactory.CreateInvoker(consumerContext);
_messageStore.UpdateReceivedMessageAsync(capMessage).Wait(); invoker.InvokeAsync();
}
catch (Exception ex) messageStore.ChangeReceivedMessageStateAsync(capMessage,StatusName.Succeeded).Wait();
{ }
_logger.ConsumerMethodExecutingFailed(executeDescriptor.MethodInfo.Name, ex); catch (Exception ex)
{
_logger.ConsumerMethodExecutingFailed(executeDescriptor.MethodInfo.Name, ex);
}
} }
} }
......
...@@ -33,13 +33,13 @@ namespace DotNetCore.CAP.Infrastructure ...@@ -33,13 +33,13 @@ namespace DotNetCore.CAP.Infrastructure
public int Retries { get; set; } public int Retries { get; set; }
public string StateName { get; set; } public string StatusName { get; set; }
} }
/// <summary> /// <summary>
/// The message state name. /// The message status name.
/// </summary> /// </summary>
public struct StateName public struct StatusName
{ {
public const string Enqueued = nameof(Enqueued); public const string Enqueued = nameof(Enqueued);
public const string Processing = nameof(Processing); public const string Processing = nameof(Processing);
......
...@@ -36,9 +36,9 @@ namespace DotNetCore.CAP.Internal ...@@ -36,9 +36,9 @@ namespace DotNetCore.CAP.Internal
return executeDescriptor.FirstOrDefault(x => x.Attribute.Name == key); return executeDescriptor.FirstOrDefault(x => x.Attribute.Name == key);
} }
public IReadOnlyList<ConsumerExecutorDescriptor> SelectCandidates(CapStartContext context) public IReadOnlyList<ConsumerExecutorDescriptor> SelectCandidates(IServiceProvider provider)
{ {
var consumerServices = context.ServiceProvider.GetServices<IConsumerService>(); var consumerServices = provider.GetServices<IConsumerService>();
var executorDescriptorList = new List<ConsumerExecutorDescriptor>(); var executorDescriptorList = new List<ConsumerExecutorDescriptor>();
foreach (var service in consumerServices) foreach (var service in consumerServices)
......
...@@ -13,11 +13,11 @@ namespace DotNetCore.CAP.Internal ...@@ -13,11 +13,11 @@ namespace DotNetCore.CAP.Internal
_selector = selector; _selector = selector;
} }
public ConcurrentDictionary<string, ConsumerExecutorDescriptor> GetCandidatesMethods(CapStartContext routeContext) public ConcurrentDictionary<string, ConsumerExecutorDescriptor> GetCandidatesMethods(IServiceProvider provider)
{ {
if (Entries.Count == 0) if (Entries.Count == 0)
{ {
var executorCollection = _selector.SelectCandidates(routeContext); var executorCollection = _selector.SelectCandidates(provider);
foreach (var item in executorCollection) foreach (var item in executorCollection)
{ {
......
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using DotNetCore.CAP.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using DotNetCore.CAP.Abstractions;
using DotNetCore.CAP.Infrastructure;
namespace DotNetCore.CAP.Job namespace DotNetCore.CAP.Job
{ {
public class CapJob : IJob public class CapJob : IJob
{ {
public Task ExecuteAsync() private readonly MethodMatcherCache _selector;
private readonly IConsumerInvokerFactory _consumerInvokerFactory;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<CapJob> _logger;
private readonly ICapMessageStore _messageStore;
public CapJob(
ILogger<CapJob> logger,
IServiceProvider serviceProvider,
IConsumerInvokerFactory consumerInvokerFactory,
ICapMessageStore messageStore,
MethodMatcherCache selector)
{
_logger = logger;
_serviceProvider = serviceProvider;
_consumerInvokerFactory = consumerInvokerFactory;
_messageStore = messageStore;
_selector = selector;
}
public async Task ExecuteAsync()
{ {
Console.WriteLine("当前时间:" + DateTime.Now.ToString()); var matchs = _selector.GetCandidatesMethods(_serviceProvider);
using (var scope = _serviceProvider.CreateScope())
{
var provider = scope.ServiceProvider;
var messageStore = provider.GetService<ICapMessageStore>();
var nextReceivedMessage = await messageStore.GetNextReceivedMessageToBeExcuted();
if (nextReceivedMessage != null)
{
var executeDescriptor = matchs[nextReceivedMessage.KeyName];
var consumerContext = new ConsumerContext(executeDescriptor, nextReceivedMessage);
var invoker = _consumerInvokerFactory.CreateInvoker(consumerContext);
await messageStore.ChangeReceivedMessageStateAsync(nextReceivedMessage, StatusName.Processing);
await invoker.InvokeAsync();
return Task.CompletedTask; await messageStore.ChangeReceivedMessageStateAsync(nextReceivedMessage,StatusName.Succeeded);
}
}
} }
} }
} }
\ No newline at end of file
...@@ -9,6 +9,7 @@ namespace DotNetCore.CAP ...@@ -9,6 +9,7 @@ namespace DotNetCore.CAP
internal static class LoggerExtensions internal static class LoggerExtensions
{ {
private static Action<ILogger, int, int, Exception> _serverStarting; private static Action<ILogger, int, int, Exception> _serverStarting;
private static Action<ILogger, Exception> _serverStartingError;
private static Action<ILogger, Exception> _serverShuttingDown; private static Action<ILogger, Exception> _serverShuttingDown;
private static Action<ILogger, string, Exception> _expectedOperationCanceledException; private static Action<ILogger, string, Exception> _expectedOperationCanceledException;
...@@ -28,6 +29,11 @@ namespace DotNetCore.CAP ...@@ -28,6 +29,11 @@ namespace DotNetCore.CAP
1, 1,
"Starting the processing server. Detected {MachineProcessorCount} machine processor(s). Initiating {ProcessorCount} job processor(s)."); "Starting the processing server. Detected {MachineProcessorCount} machine processor(s). Initiating {ProcessorCount} job processor(s).");
_serverStartingError = LoggerMessage.Define(
LogLevel.Error,
5,
"Starting the processing server throw an exception.");
_serverShuttingDown = LoggerMessage.Define( _serverShuttingDown = LoggerMessage.Define(
LogLevel.Debug, LogLevel.Debug,
2, 2,
...@@ -94,6 +100,11 @@ namespace DotNetCore.CAP ...@@ -94,6 +100,11 @@ namespace DotNetCore.CAP
_serverStarting(logger, machineProcessorCount, processorCount, null); _serverStarting(logger, machineProcessorCount, processorCount, null);
} }
public static void ServerStartedError(this ILogger logger, Exception ex)
{
_serverStartingError(logger, ex);
}
public static void ServerShuttingDown(this ILogger logger) public static void ServerShuttingDown(this ILogger logger)
{ {
_serverShuttingDown(logger, null); _serverShuttingDown(logger, null);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment