Skip to content

Commit

Permalink
Implement lazy concurrency
Browse files Browse the repository at this point in the history
Use Task.WaitAll to spread out workload.

Note: This is a bad implementation; however, we are limited by the DocFx's synchronous context - we cannot use Task.WhenAll
  • Loading branch information
Still Hsu committed Oct 20, 2018
1 parent aafdab6 commit 93e4835
Showing 1 changed file with 34 additions and 26 deletions.
60 changes: 34 additions & 26 deletions DocFX.Plugin.DescriptionGenerator/DescriptionPostProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using HtmlAgilityPack;
using Microsoft.DocAsCode.Common;
using Microsoft.DocAsCode.Plugins;
Expand All @@ -17,37 +18,43 @@ public class DescriptionPostProcessor : IPostProcessor
private const string FullStopDelimiter = ". ";
private int _savedFiles;

public ImmutableDictionary<string, object> PrepareMetadata(ImmutableDictionary<string, object> metadata) =>
metadata;
public ImmutableDictionary<string, object> PrepareMetadata(ImmutableDictionary<string, object> metadata)
=> metadata;

public Manifest Process(Manifest manifest, string outputFolder)
{
string versionInfo = Assembly.GetExecutingAssembly()
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
?.InformationalVersion ??
Assembly.GetExecutingAssembly().GetName().Version.ToString();
var versionInfo = Assembly.GetExecutingAssembly()
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
?.InformationalVersion ??
Assembly.GetExecutingAssembly().GetName().Version.ToString();
Logger.LogInfo($"Version: {versionInfo}");
foreach (var manifestItem in manifest.Files.Where(x => !string.IsNullOrEmpty(x.SourceRelativePath)))
var taskQueue = manifest.Files.Where(x => !string.IsNullOrEmpty(x.SourceRelativePath)).Select(manifestItem =>
{
Logger.LogVerbose($"Document type for {manifestItem.SourceRelativePath} is {manifestItem.DocumentType}.");
foreach (var manifestItemOutputFile in manifestItem.OutputFiles.Where(x =>
!string.IsNullOrEmpty(x.Value.RelativePath)))
return Task.Run(() =>
{
string sourcePath = Path.Combine(manifest.SourceBasePath, manifestItem.SourceRelativePath);
string outputPath = Path.Combine(outputFolder, manifestItemOutputFile.Value.RelativePath);
if (manifestItem.DocumentType == "Conceptual")
WriteMetadataTag(sourcePath, outputPath, ArticleType.Conceptual);
if (manifestItem.DocumentType == "ManagedReference")
WriteMetadataTag(sourcePath, outputPath, ArticleType.Reference);
}
}
Logger.LogVerbose(
$"Document type for {manifestItem.SourceRelativePath} is {manifestItem.DocumentType}.");
foreach (var manifestItemOutputFile in manifestItem.OutputFiles.Where(x =>
!string.IsNullOrEmpty(x.Value.RelativePath)))
{
var sourcePath = Path.Combine(manifest.SourceBasePath, manifestItem.SourceRelativePath);
var outputPath = Path.Combine(outputFolder, manifestItemOutputFile.Value.RelativePath);
if (manifestItem.DocumentType == "Conceptual")
WriteMetadataTag(sourcePath, outputPath, ArticleType.Conceptual);
if (manifestItem.DocumentType == "ManagedReference")
WriteMetadataTag(sourcePath, outputPath, ArticleType.Reference);
}
});
}).ToArray();

Task.WaitAll(taskQueue);

Logger.LogInfo($"Added description tags to {_savedFiles} items.");
return manifest;
}

/// <summary>
/// Injects the description tag according to the type of article.
/// Injects the description tag according to the <paramref name="type" /> of article.
/// </summary>
/// <param name="sourcePath">The original article path.</param>
/// <param name="outputPath">The output path.</param>
Expand All @@ -57,22 +64,24 @@ private void WriteMetadataTag(string sourcePath, string outputPath, ArticleType
Logger.LogVerbose($"Processing metadata from {sourcePath} to {outputPath}...");
var htmlDoc = new HtmlDocument();
htmlDoc.Load(outputPath);

// Write description
string descriptionText = string.Empty;
var descriptionText = string.Empty;
switch (type)
{
case ArticleType.Conceptual:
var articleInnerText = htmlDoc.DocumentNode.SelectSingleNode("//article[@id='_content']/p")?.InnerText;
var articleInnerText =
htmlDoc.DocumentNode.SelectSingleNode("//article[@id='_content']/p")?.InnerText;
if (string.IsNullOrEmpty(articleInnerText)) return;

int articlePunctuationPos = articleInnerText.IndexOf(FullStopDelimiter, StringComparison.Ordinal);
var articlePunctuationPos = articleInnerText.IndexOf(FullStopDelimiter, StringComparison.Ordinal);
descriptionText = articlePunctuationPos <= FixedDescriptionLength && articlePunctuationPos > 0
? articleInnerText.Remove(articlePunctuationPos + FullStopDelimiter.Length).Trim()
: articleInnerText.Truncate(FixedDescriptionLength, "...");
break;
case ArticleType.Reference:
var memberDescription = htmlDoc.DocumentNode.SelectSingleNode("//div[contains(@class, 'level0 summary')]/p")?.InnerText;
var memberDescription = htmlDoc.DocumentNode
.SelectSingleNode("//div[contains(@class, 'level0 summary')]/p")?.InnerText;
if (!string.IsNullOrEmpty(memberDescription)) descriptionText = memberDescription;
break;
}
Expand All @@ -88,10 +97,9 @@ private void WriteMetadataTag(string sourcePath, string outputPath, ArticleType
/// Appends the description text into the meta tag of the document.
/// </summary>
/// <param name="htmlDoc">The document to be modified.</param>
/// <param name="type">The type of metadata to inject.</param>
/// <param name="value">The text to append.</param>
/// <returns>
/// The modified <see cref="HtmlDocument"/>.
/// The modified <see cref="HtmlDocument" /> .
/// </returns>
private static HtmlDocument AppendMetadata(HtmlDocument htmlDoc, string value)
{
Expand Down

0 comments on commit 93e4835

Please sign in to comment.