Run JSON schema validation in separate thread
This commit is contained in:
parent
aa73231f38
commit
6f2ebe5a5a
@ -7,15 +7,14 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Plugin;
|
||||
using Json.Schema;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Questionable.Data;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.V1;
|
||||
using Questionable.QuestPaths;
|
||||
using Questionable.Validation;
|
||||
using Questionable.Validation.Validators;
|
||||
|
||||
namespace Questionable.Controller;
|
||||
|
||||
@ -25,18 +24,19 @@ internal sealed class QuestRegistry
|
||||
private readonly QuestData _questData;
|
||||
private readonly QuestValidator _questValidator;
|
||||
private readonly ILogger<QuestRegistry> _logger;
|
||||
private readonly JsonSchema _questSchema;
|
||||
private readonly JsonSchemaValidator _jsonSchemaValidator;
|
||||
|
||||
private readonly Dictionary<ushort, Quest> _quests = new();
|
||||
|
||||
public QuestRegistry(IDalamudPluginInterface pluginInterface, QuestData questData,
|
||||
QuestValidator questValidator, ILogger<QuestRegistry> logger)
|
||||
QuestValidator questValidator, JsonSchemaValidator jsonSchemaValidator,
|
||||
ILogger<QuestRegistry> logger)
|
||||
{
|
||||
_pluginInterface = pluginInterface;
|
||||
_questData = questData;
|
||||
_questValidator = questValidator;
|
||||
_jsonSchemaValidator = jsonSchemaValidator;
|
||||
_logger = logger;
|
||||
_questSchema = JsonSchema.FromStream(AssemblyQuestLoader.QuestSchema).AsTask().Result;
|
||||
}
|
||||
|
||||
public IEnumerable<Quest> AllQuests => _quests.Values;
|
||||
@ -46,7 +46,7 @@ internal sealed class QuestRegistry
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
_questValidator.ClearIssues();
|
||||
_questValidator.Reset();
|
||||
_quests.Clear();
|
||||
|
||||
LoadQuestsFromAssembly();
|
||||
@ -130,26 +130,8 @@ internal sealed class QuestRegistry
|
||||
if (questId == null)
|
||||
return;
|
||||
|
||||
var questNode = JsonNode.Parse(stream);
|
||||
Task.Run(() =>
|
||||
{
|
||||
var evaluationResult = _questSchema.Evaluate(questNode, new EvaluationOptions
|
||||
{
|
||||
Culture = CultureInfo.InvariantCulture,
|
||||
OutputFormat = OutputFormat.List
|
||||
});
|
||||
if (!evaluationResult.IsValid)
|
||||
{
|
||||
_questValidator.AddIssue(new ValidationIssue
|
||||
{
|
||||
QuestId = questId.Value,
|
||||
Sequence = null,
|
||||
Step = null,
|
||||
Severity = EIssueSeverity.Error,
|
||||
Description = "JSON Validation failed"
|
||||
});
|
||||
}
|
||||
});
|
||||
var questNode = JsonNode.Parse(stream)!;
|
||||
_jsonSchemaValidator.Enqueue(questId.Value, questNode);
|
||||
|
||||
Quest quest = new Quest
|
||||
{
|
||||
|
@ -67,6 +67,23 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
serviceCollection.AddSingleton(new WindowSystem(nameof(Questionable)));
|
||||
serviceCollection.AddSingleton((Configuration?)pluginInterface.GetPluginConfig() ?? new Configuration());
|
||||
|
||||
AddBasicFunctionsAndData(serviceCollection);
|
||||
AddTaskFactories(serviceCollection);
|
||||
AddControllers(serviceCollection);
|
||||
AddWindows(serviceCollection);
|
||||
AddQuestValidators(serviceCollection);
|
||||
|
||||
serviceCollection.AddSingleton<CommandHandler>();
|
||||
serviceCollection.AddSingleton<DalamudInitializer>();
|
||||
|
||||
_serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
_serviceProvider.GetRequiredService<QuestRegistry>().Reload();
|
||||
_serviceProvider.GetRequiredService<CommandHandler>();
|
||||
_serviceProvider.GetRequiredService<DalamudInitializer>();
|
||||
}
|
||||
|
||||
private static void AddBasicFunctionsAndData(ServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddSingleton<GameFunctions>();
|
||||
serviceCollection.AddSingleton<ChatFunctions>();
|
||||
serviceCollection.AddSingleton<AetherCurrentData>();
|
||||
@ -76,12 +93,15 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
serviceCollection.AddSingleton<NavmeshIpc>();
|
||||
serviceCollection.AddSingleton<LifestreamIpc>();
|
||||
serviceCollection.AddSingleton<YesAlreadyIpc>();
|
||||
}
|
||||
|
||||
private static void AddTaskFactories(ServiceCollection serviceCollection)
|
||||
{
|
||||
// individual tasks
|
||||
serviceCollection.AddTransient<MountTask>();
|
||||
serviceCollection.AddTransient<UnmountTask>();
|
||||
|
||||
// tasks with factories
|
||||
// task factories
|
||||
serviceCollection.AddTaskWithFactory<StepDisabled.Factory, StepDisabled.Task>();
|
||||
serviceCollection.AddTaskWithFactory<AetheryteShortcut.Factory, AetheryteShortcut.UseAetheryteShortcut>();
|
||||
serviceCollection.AddTaskWithFactory<SkipCondition.Factory, SkipCondition.CheckTask>();
|
||||
@ -115,7 +135,10 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
WaitAtEnd.WaitObjectAtPosition>();
|
||||
serviceCollection.AddTransient<WaitAtEnd.WaitQuestAccepted>();
|
||||
serviceCollection.AddTransient<WaitAtEnd.WaitQuestCompleted>();
|
||||
}
|
||||
|
||||
private static void AddControllers(ServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddSingleton<MovementController>();
|
||||
serviceCollection.AddSingleton<MovementOverrideController>();
|
||||
serviceCollection.AddSingleton<QuestRegistry>();
|
||||
@ -125,27 +148,27 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
serviceCollection.AddSingleton<CombatController>();
|
||||
|
||||
serviceCollection.AddSingleton<ICombatModule, RotationSolverRebornModule>();
|
||||
}
|
||||
|
||||
private static void AddWindows(ServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddSingleton<QuestWindow>();
|
||||
serviceCollection.AddSingleton<ConfigWindow>();
|
||||
serviceCollection.AddSingleton<DebugOverlay>();
|
||||
serviceCollection.AddSingleton<QuestSelectionWindow>();
|
||||
serviceCollection.AddSingleton<QuestValidationWindow>();
|
||||
}
|
||||
|
||||
private static void AddQuestValidators(ServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddSingleton<QuestValidator>();
|
||||
serviceCollection.AddSingleton<IQuestValidator, QuestDisabledValidator>();
|
||||
serviceCollection.AddSingleton<IQuestValidator, BasicSequenceValidator>();
|
||||
serviceCollection.AddSingleton<IQuestValidator, UniqueStartStopValidator>();
|
||||
serviceCollection.AddSingleton<IQuestValidator, NextQuestValidator>();
|
||||
serviceCollection.AddSingleton<IQuestValidator, CompletionFlagsValidator>();
|
||||
|
||||
serviceCollection.AddSingleton<CommandHandler>();
|
||||
serviceCollection.AddSingleton<DalamudInitializer>();
|
||||
|
||||
_serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
_serviceProvider.GetRequiredService<QuestRegistry>().Reload();
|
||||
_serviceProvider.GetRequiredService<CommandHandler>();
|
||||
_serviceProvider.GetRequiredService<DalamudInitializer>();
|
||||
serviceCollection.AddSingleton<JsonSchemaValidator>();
|
||||
serviceCollection.AddSingleton<IQuestValidator>(sp => sp.GetRequiredService<JsonSchemaValidator>());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -6,4 +6,8 @@ namespace Questionable.Validation;
|
||||
internal interface IQuestValidator
|
||||
{
|
||||
IEnumerable<ValidationIssue> Validate(Quest quest);
|
||||
|
||||
void Reset()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Questionable.Model;
|
||||
@ -26,11 +27,16 @@ internal sealed class QuestValidator
|
||||
public int IssueCount => _validationIssues.Count;
|
||||
public int ErrorCount => _validationIssues.Count(x => x.Severity == EIssueSeverity.Error);
|
||||
|
||||
public void ClearIssues() => _validationIssues.Clear();
|
||||
public void Reset()
|
||||
{
|
||||
foreach (var validator in _validators)
|
||||
validator.Reset();
|
||||
_validationIssues.Clear();
|
||||
}
|
||||
|
||||
public void Validate(IEnumerable<Quest> quests)
|
||||
{
|
||||
Task.Run(() =>
|
||||
Task.Factory.StartNew(() =>
|
||||
{
|
||||
foreach (var quest in quests)
|
||||
{
|
||||
@ -52,8 +58,6 @@ internal sealed class QuestValidator
|
||||
.ThenBy(x => x.Step)
|
||||
.ThenBy(x => x.Description)
|
||||
.ToList();
|
||||
});
|
||||
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
public void AddIssue(ValidationIssue issue) => _validationIssues.Add(issue);
|
||||
}
|
||||
|
44
Questionable/Validation/Validators/JsonSchemaValidator.cs
Normal file
44
Questionable/Validation/Validators/JsonSchemaValidator.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text.Json.Nodes;
|
||||
using Json.Schema;
|
||||
using Questionable.Model;
|
||||
using Questionable.QuestPaths;
|
||||
|
||||
namespace Questionable.Validation.Validators;
|
||||
|
||||
internal sealed class JsonSchemaValidator : IQuestValidator
|
||||
{
|
||||
private readonly Dictionary<ushort, JsonNode> _questNodes = new();
|
||||
private JsonSchema? _questSchema;
|
||||
|
||||
public IEnumerable<ValidationIssue> Validate(Quest quest)
|
||||
{
|
||||
_questSchema ??= JsonSchema.FromStream(AssemblyQuestLoader.QuestSchema).AsTask().Result;
|
||||
|
||||
if (_questNodes.TryGetValue(quest.QuestId, out JsonNode? questNode))
|
||||
{
|
||||
var evaluationResult = _questSchema.Evaluate(questNode, new EvaluationOptions
|
||||
{
|
||||
Culture = CultureInfo.InvariantCulture,
|
||||
OutputFormat = OutputFormat.List
|
||||
});
|
||||
if (!evaluationResult.IsValid)
|
||||
{
|
||||
yield return new ValidationIssue
|
||||
{
|
||||
QuestId = quest.QuestId,
|
||||
Sequence = null,
|
||||
Step = null,
|
||||
Severity = EIssueSeverity.Error,
|
||||
Description = "JSON Validation failed"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Enqueue(ushort questId, JsonNode questNode) => _questNodes[questId] = questNode;
|
||||
|
||||
public void Reset() => _questNodes.Clear();
|
||||
}
|
Loading…
Reference in New Issue
Block a user