fix: IDeserializer并非线程安全

This commit is contained in:
jackfiled 2024-01-23 14:33:35 +08:00
parent 800f439564
commit 66ecaa4c90
3 changed files with 63 additions and 22 deletions

View File

@ -4,6 +4,8 @@ public class BlogEssay
{ {
public required string Title { get; init; } public required string Title { get; init; }
public required string FileName { get; init; }
public required DateTime PublishTime { get; init; } public required DateTime PublishTime { get; init; }
public List<string> Tags { get; } = []; public List<string> Tags { get; } = [];

View File

@ -6,5 +6,5 @@ public class MarkdownMetadata
public DateTime? Date { get; set; } public DateTime? Date { get; set; }
public List<string> Tags { get; set; } = []; public List<string>? Tags { get; set; }
} }

View File

@ -1,7 +1,9 @@
using Markdig; using System.Diagnostics;
using Markdig;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using YaeBlog.Core.Exceptions; using YaeBlog.Core.Exceptions;
using YaeBlog.Core.Models; using YaeBlog.Core.Models;
using YamlDotNet.Core;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
namespace YaeBlog.Core.Services; namespace YaeBlog.Core.Services;
@ -12,33 +14,61 @@ public class RendererService(ILogger<RendererService> logger,
IDeserializer yamlDeserializer, IDeserializer yamlDeserializer,
EssayContentService essayContentService) EssayContentService essayContentService)
{ {
private readonly Stopwatch _stopwatch = new();
public async Task RenderAsync() public async Task RenderAsync()
{ {
_stopwatch.Start();
logger.LogInformation("Render essays start.");
List<BlogContent> contents = await essayScanService.ScanAsync(); List<BlogContent> contents = await essayScanService.ScanAsync();
Parallel.ForEach(contents, content => List<BlogEssay> essays = [];
await Task.Run(() =>
{ {
MarkdownMetadata? metadata = TryParseMetadata(content); foreach (BlogContent content in contents)
{
MarkdownMetadata? metadata = TryParseMetadata(content);
BlogEssay essay = new()
{
Title = metadata?.Title ?? content.FileName,
FileName = content.FileName,
PublishTime = metadata?.Date ?? DateTime.Now,
HtmlContent = content.FileContent
};
BlogEssay essay = new() if (metadata?.Tags is not null)
{ {
Title = metadata?.Title ?? content.FileName, essay.Tags.AddRange(metadata.Tags);
PublishTime = metadata?.Date ?? DateTime.Now, }
HtmlContent = Markdown.ToHtml(content.FileContent, markdownPipeline) essays.Add(essay);
};
if (metadata is not null)
{
essay.Tags.AddRange(essay.Tags);
} }
});
if (!essayContentService.TryAdd(essay.Title, essay)) Parallel.ForEach(essays, essay =>
{
BlogEssay newEssay = new()
{
Title = essay.Title,
FileName = essay.FileName,
PublishTime = essay.PublishTime,
HtmlContent = Markdown.ToHtml(essay.HtmlContent, markdownPipeline)
};
newEssay.Tags.AddRange(essay.Tags);
if (!essayContentService.TryAdd(newEssay.FileName, newEssay))
{ {
throw new BlogFileException( throw new BlogFileException(
$"There are two essays with the same name: '{content.FileName}'."); $"There are two essays with the same name: '{newEssay.FileName}'.");
} }
logger.LogDebug("Render markdown file {}.", essay); logger.LogDebug("Render markdown file {}.", newEssay);
logger.LogDebug("{}", essay.HtmlContent);
}); });
_stopwatch.Stop();
logger.LogInformation("Render finished, consuming {} s.",
_stopwatch.Elapsed.ToString("s\\.fff"));
} }
private MarkdownMetadata? TryParseMetadata(BlogContent content) private MarkdownMetadata? TryParseMetadata(BlogContent content)
@ -60,14 +90,23 @@ public class RendererService(ILogger<RendererService> logger,
} }
string yamlContent = fileContent[..lastPos]; string yamlContent = fileContent[..lastPos];
MarkdownMetadata metadata = yamlDeserializer.Deserialize<MarkdownMetadata>(yamlContent);
logger.LogDebug("Title: {}, Publish Date: {}.",
metadata.Title, metadata.Date);
// 返回去掉元数据之后的文本 // 返回去掉元数据之后的文本
lastPos += 3; lastPos += 3;
content.FileContent = fileContent[lastPos..]; content.FileContent = fileContent[lastPos..];
return null; try
{
MarkdownMetadata metadata =
yamlDeserializer.Deserialize<MarkdownMetadata>(yamlContent);
logger.LogDebug("Title: {}, Publish Date: {}.",
metadata.Title, metadata.Date);
return metadata;
}
catch (YamlException e)
{
logger.LogWarning("Failed to parse '{}' metadata: {}", yamlContent, e);
return null;
}
} }
} }