Skip to content

Commit

Permalink
Merge pull request #7 from dotnet-campus/t/lindexi/Comment
Browse files Browse the repository at this point in the history
加上注释
  • Loading branch information
lindexi authored Jun 15, 2022
2 parents 68de303 + f2c96f7 commit fcc8313
Show file tree
Hide file tree
Showing 13 changed files with 182 additions and 27 deletions.
12 changes: 9 additions & 3 deletions src/dotnetCampus.ApplicationStartupManager/IStartupContext.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
using System.Threading.Tasks;
//using dotnetCampus.Configurations;

namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 表示启动任务的上下文接口
/// </summary>
public interface IStartupContext
{
//IAppConfigurator Configs { get; }
//Task<string> ReadCacheAsync(string key, string @default = "");
/// <summary>
/// 等待某个启动任务完成
/// </summary>
/// <param name="startupKey"></param>
/// <returns></returns>
/// 这是框架层需要支持的能力,因此也就放在此
Task WaitStartupTaskAsync(string startupKey);
}
}
17 changes: 17 additions & 0 deletions src/dotnetCampus.ApplicationStartupManager/IStartupLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,27 @@

namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 启动模块的日志
/// </summary>
public interface IStartupLogger
{
/// <summary>
/// 打点某个里程碑,将会自动与上个里程碑记录时间差
/// </summary>
/// <param name="milestoneName"></param>
void RecordTime(string milestoneName);
/// <summary>
/// 记录某个任务的耗时情况
/// </summary>
/// <param name="taskName"></param>
/// <param name="task"></param>
/// <returns></returns>
Task RecordDuration(string taskName, Func<Task<string>> task);
/// <summary>
/// 上报启动结果
/// </summary>
/// <param name="wrappers"></param>
void ReportResult(IReadOnlyList<IStartupTaskWrapper> wrappers);
}
}
14 changes: 14 additions & 0 deletions src/dotnetCampus.ApplicationStartupManager/IStartupManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,24 @@

namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 启动流程管理器
/// </summary>
public interface IStartupManager
{
/// <summary>
/// 等待某个启动项的完成
/// </summary>
/// <param name="startupTaskKey"></param>
/// <returns></returns>
Task WaitStartupTaskAsync(string startupTaskKey);

/// <summary>
/// 获取指定类型的启动项
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// 理论上相同的类型的启动项不会被重复加入,基本都是一个启动项一个类型
StartupTaskBase GetStartupTask<T>() where T : StartupTaskBase;
}
}
15 changes: 15 additions & 0 deletions src/dotnetCampus.ApplicationStartupManager/IStartupTaskWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,26 @@

namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 启动项在启动框架的信息
/// </summary>
public interface IStartupTaskWrapper
{
/// <summary>
/// 跟随等待着当前启动项的其他启动项
/// </summary>
HashSet<string> FollowTasks { get; }
/// <summary>
/// 当前启动项所依赖的其他启动项
/// </summary>
HashSet<string> Dependencies { get; }
/// <summary>
/// 当前启动项的标识
/// </summary>
string StartupTaskKey { get; }
/// <summary>
/// 表示当前启动项是否只能在 UI 线程启动
/// </summary>
bool UIOnly { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 用于启动项里的值提供器,用于多个启动项之间传递参数
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IStartupValueProvider<out T>
{
/// <summary>
/// 获取启动项提供的值
/// </summary>
/// <returns></returns>
T ProvideValue();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 一个表示空白的启动项
/// </summary>
internal sealed class NullObjectStartup : StartupTaskBase
{

Expand Down
16 changes: 3 additions & 13 deletions src/dotnetCampus.ApplicationStartupManager/StartupContext.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
using System;
using System.Threading.Tasks;
//using dotnetCampus.Configurations;
//using dotnetCampus.Configurations.Core;

namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 启动项的上下文信息,业务方可以自己再定义而不需要使用此类型
/// </summary>
internal class StartupContext : IStartupContext
{
public IStartupLogger Logger { get; }

//public FileConfigurationRepo Configuration { get; }

//public IAppConfigurator Configs { get; }

public Func<Exception, Task> FastFail { get; }

private readonly Func<string, Task> _waitStartupTaskAsync;

//public Task<string> ReadCacheAsync(string key, string @default = "")
//{
// return Configuration.TryReadAsync(key, @default);
//}

Task IStartupContext.WaitStartupTaskAsync(string startupKey) => _waitStartupTaskAsync(startupKey);

public StartupContext(IStartupLogger logger, /*FileConfigurationRepo configuration,*/
Func<Exception, Task> fastFailAction, Func<string, Task> waitStartupAsync)
{
Logger = logger;
//Configuration = configuration;
_waitStartupTaskAsync = waitStartupAsync;
//Configs = configuration.CreateAppConfigurator();
FastFail = fastFailAction ?? (exception => StartupTaskBase.CompletedTask);
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/dotnetCampus.ApplicationStartupManager/StartupLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,36 @@

namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 表示启动任务的基础日志,推荐业务方提供更贴合业务的日志,和日志记录的方法
/// </summary>
public class StartupLoggerBase : IStartupLogger
{
private readonly Stopwatch _mainWatch;

/// <summary>
/// 各个启动的里程碑的信息,包括里程碑的所运行的线程名,启动时间和执行时间
/// <para>
/// Key: 启动的里程碑名
/// </para>
/// <para>
/// Value: 启动的信息,包括里程碑的所运行的线程名,启动时间和执行时间。时间都是从 <see cref="Stopwatch.ElapsedTicks"/> 获取
/// </para>
/// </summary>
protected ConcurrentDictionary<string, (string threadName, long start, long elapsed)>
MilestoneDictionary
{ get; } = new ConcurrentDictionary<string, (string, long, long)>();

/// <summary>
/// 创建启动任务的基础日志,此日志的核心功能就是监控启动项的启动时间
/// </summary>
public StartupLoggerBase()
{
_mainWatch = new Stopwatch();
_mainWatch.Start();
}

/// <inheritdoc/>
public void RecordTime(string milestoneName)
{
var start = MilestoneDictionary.Count > 0
Expand All @@ -34,6 +50,7 @@ public void RecordTime(string milestoneName)
start, end - start);
}

/// <inheritdoc/>
public async Task RecordDuration(string taskName, Func<Task<string>> task)
{
var threadName = "null";
Expand All @@ -51,8 +68,10 @@ public async Task RecordDuration(string taskName, Func<Task<string>> task)
}
}

/// <inheritdoc/>
public virtual void ReportResult(IReadOnlyList<IStartupTaskWrapper> wrappers)
{
// 没有实际的可以记录的地方,需要业务方自己实现记录到哪
}
}
}
46 changes: 41 additions & 5 deletions src/dotnetCampus.ApplicationStartupManager/StartupManagerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@

namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 启动任务管理器,这是此框架的入口
/// <para>
/// 期望业务方自己再基于此类型继续实现自己的业务逻辑,例如注入业务方需要的日志模块,以及构建启动任务上下文
/// </para>
/// </summary>
public class StartupManagerBase : IStartupManager
{
private readonly IMainThreadDispatcher _dispatcher;

///// <summary>
///// Builder 模式所需状态:包含当前剩余需要管理的启动任务程序集。
///// </summary>
//private readonly List<Assembly> _assembliesToBeManaged = new List<Assembly>();

/// <summary>
/// Builder 模式所需状态:包含当前所有的关键启动任务。
/// </summary>
Expand All @@ -42,10 +43,25 @@ public class StartupManagerBase : IStartupManager
private List<StartupTaskWrapper>? Graph { get; set; }

private StartupContext Context { get; }

/// <summary>
/// 获取启动任务上下文信息
/// </summary>
protected IStartupContext StartupContext => Context;

/// <summary>
/// 获取启动任务日志
/// </summary>
protected IStartupLogger Logger => Context.Logger;

/// <summary>
/// 创建启动任务管理器
/// </summary>
/// <param name="logger">启动项的日志记录器</param>
/// <param name="fastFailAction">启动过程存在失败时需要执行的逻辑,也就是说此委托被框架执行时,将应该记录失败然后退出应用</param>
/// <param name="dispatcher">传入线程调度器,需要业务方自己实现</param>
/// <param name="shouldSetThreadPool">是否需要在进入启动框架时,让框架设置线程池的线程数</param>
/// <exception cref="ArgumentNullException"></exception>
public StartupManagerBase(IStartupLogger logger, /*FileConfigurationRepo configurationRepo,*/
Func<Exception, Task> fastFailAction, IMainThreadDispatcher dispatcher, bool shouldSetThreadPool = true)
{
Expand Down Expand Up @@ -213,12 +229,20 @@ public StartupManagerBase AddCriticalNodes(string nodeName, string? beforeTasks
// return this;
//}

/// <summary>
/// 加入构建预设启动项
/// </summary>
/// <param name="taskBuilder"></param>
/// <returns></returns>
public StartupManagerBase ForStartupTasksOfCategory(Action<StartupTaskBuilder> taskBuilder)
{
_additionalBuilders.Add(taskBuilder);
return this;
}

/// <summary>
/// 启动框架,开始执行应用程序的启动流程
/// </summary>
public async void Run()
{
if (Graph == null)
Expand Down Expand Up @@ -343,6 +367,10 @@ void AddFollowTasks(StartupTaskWrapper wrapper, string beforeTasks)
}
}

/// <summary>
/// 导出所有的启动任务项,可以给子类继承,用于让子类定制获取启动任务项的方法
/// </summary>
/// <returns></returns>
protected virtual IEnumerable<StartupTaskMetadata> ExportStartupTasks()
{
foreach (var func in _startupTaskMetadataCollectorList)
Expand Down Expand Up @@ -435,6 +463,7 @@ internal StartupTaskWrapper GetStartupTaskWrapper(string startupTaskKey)
throw new InvalidOperationException($"{startupTaskKey}既无法添加至字典,也无法从字典获取对应值");
}

/// <inheritdoc/>
public Task WaitStartupTaskAsync(string startupTaskKey)
=> GetStartupTaskWrapper(startupTaskKey).TaskBase.TaskResult;

Expand All @@ -444,6 +473,13 @@ StartupTaskBase IStartupManager.GetStartupTask<T>()
private static string StartupTypeToKey(Type type)
=> type.Name.Remove(type.Name.Length - "startup".Length);

/// <summary>
/// 实际执行某个具体的启动任务项的函数,可以给子类继承,用来控制具体的启动任务项执行逻辑
/// </summary>
/// <param name="startupTask"></param>
/// <param name="context"></param>
/// <param name="uiOnly"></param>
/// <returns></returns>
protected internal virtual Task<string> ExecuteStartupTaskAsync(StartupTaskBase startupTask, IStartupContext context, bool uiOnly)
{
return startupTask.JoinAsync(context, uiOnly);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;
using System.Diagnostics.CodeAnalysis;

namespace dotnetCampus.ApplicationStartupManager
{
/// <summary>
/// 启动任务的特性,可以让业务方用来对接,如对接预编译框架,从而收集启动任务项
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class StartupTaskAttribute : Attribute
{
Expand Down
Loading

0 comments on commit fcc8313

Please sign in to comment.