From 5921d29139bad937a3393a12bc3144a666691a9d Mon Sep 17 00:00:00 2001 From: Jayson Maxson Date: Tue, 19 Nov 2024 09:17:17 -0800 Subject: [PATCH] Enable custom processor environments in the Engine. (#383) * Add ProcessorEnvironmentFactory * ProcessEnvironmentFactory => ProcessorEnvironmentFactory * Small cleanup. --- .../Engine.cs | 66 ++-------------- .../EngineCreateInfo.cs | 42 ++++++++++- .../ProcessorEnvironment.cs | 26 +++++++ .../ProcessorEnvironmentFactory.cs | 33 ++++++++ .../RuntimeProcessorEnvironmentFactory.cs | 75 +++++++++++++++++++ 5 files changed, 180 insertions(+), 62 deletions(-) create mode 100644 src/Microsoft.Performance.Toolkit.Engine/ProcessorEnvironment.cs create mode 100644 src/Microsoft.Performance.Toolkit.Engine/ProcessorEnvironmentFactory.cs create mode 100644 src/Microsoft.Performance.Toolkit.Engine/RuntimeProcessorEnvironmentFactory.cs diff --git a/src/Microsoft.Performance.Toolkit.Engine/Engine.cs b/src/Microsoft.Performance.Toolkit.Engine/Engine.cs index 68e6ffc..ec228fa 100644 --- a/src/Microsoft.Performance.Toolkit.Engine/Engine.cs +++ b/src/Microsoft.Performance.Toolkit.Engine/Engine.cs @@ -1065,9 +1065,9 @@ namespace Microsoft.Performance.Toolkit.Engine foreach (var psDsgPair in processingOptionsMap) { - var processingSource = psDsgPair.Key.Item1; - var dsg = psDsgPair.Key.Item2; - var processorOptions = psDsgPair.Value; + ProcessingSourceReference processingSource = psDsgPair.Key.Item1; + IDataSourceGroup dsg = psDsgPair.Key.Item2; + ProcessorOptions processorOptions = psDsgPair.Value; try { @@ -1087,11 +1087,11 @@ namespace Microsoft.Performance.Toolkit.Engine var executionContext = new SDK.Runtime.ExecutionContext( new DataProcessorProgress(), - x => ConsoleLogger.Create(x.GetType()), + x => ConsoleLogger.Create(x.GetType()), // todo: this shouldn't be using a console logger by default processingSource, dsg, // todo #214 processingSource.Instance.MetadataTables, - new RuntimeProcessorEnvironment(this.Extensions, this.compositeCookers, this.CreateLogger), + this.CreateInfo.ProcessEnvironmentFactory.CreateProcessorEnvironment(processingSource.Guid, dsg), processorOptions); var executor = new ProcessingSourceExecutor(); @@ -1221,62 +1221,6 @@ namespace Microsoft.Performance.Toolkit.Engine } } - private sealed class RuntimeProcessorEnvironment - : IProcessorEnvironment - { - private readonly ProcessingSystemCompositeCookers compositeCookers; - private readonly IDataExtensionRepository repository; - private readonly Func loggerFactory; - private readonly object loggerLock = new object(); - - private ILogger logger; - private Type processorType; - - public RuntimeProcessorEnvironment( - IDataExtensionRepository repository, - ProcessingSystemCompositeCookers compositeCookers, - Func loggerFactory) - { - Debug.Assert(repository != null); - Debug.Assert(compositeCookers != null); - Debug.Assert(loggerFactory != null); - - this.compositeCookers = compositeCookers; - this.repository = repository; - this.loggerFactory = loggerFactory; - } - - public ILogger CreateLogger(Type processorType) - { - Guard.NotNull(processorType, nameof(processorType)); - - lock (this.loggerLock) - { - if (logger != null) - { - if (this.processorType != processorType) - { - throw new ArgumentException( - $"{nameof(CreateLogger)} cannot be called with multiple types in a single instance.", - nameof(processorType)); - } - - return this.logger; - } - - this.processorType = processorType; - this.logger = this.loggerFactory(processorType); - return this.logger; - } - } - - public IDynamicTableBuilder RequestDynamicTableBuilder( - TableDescriptor descriptor) - { - return null; - } - } - private abstract class RuntimeMessageBox : IMessageBox { diff --git a/src/Microsoft.Performance.Toolkit.Engine/EngineCreateInfo.cs b/src/Microsoft.Performance.Toolkit.Engine/EngineCreateInfo.cs index 0735b73..c019978 100644 --- a/src/Microsoft.Performance.Toolkit.Engine/EngineCreateInfo.cs +++ b/src/Microsoft.Performance.Toolkit.Engine/EngineCreateInfo.cs @@ -7,6 +7,7 @@ using System.Collections.ObjectModel; using Microsoft.Performance.SDK; using Microsoft.Performance.SDK.Auth; using Microsoft.Performance.SDK.Processing; +using Microsoft.Performance.SDK.Runtime; namespace Microsoft.Performance.Toolkit.Engine { @@ -16,10 +17,12 @@ namespace Microsoft.Performance.Toolkit.Engine /// public sealed class EngineCreateInfo { - private static string DefaultRuntimeName; + private static readonly string DefaultRuntimeName; private readonly Dictionary authProviders = new Dictionary(); + private ProcessorEnvironmentFactory processEnvironmentFactory; + /// /// Initializes the statc members of the /// class. @@ -134,6 +137,27 @@ namespace Microsoft.Performance.Toolkit.Engine return this; } + /// + /// Registers a to use for generating a custom processor + /// environment. + /// + /// + /// Factory for generating a . + /// + /// + /// The instance of . + /// + /// + /// is null. + /// + public EngineCreateInfo WithProcessorEnvironmentFactory(ProcessorEnvironmentFactory factory) + { + Guard.NotNull(factory, nameof(factory)); + + this.ProcessEnvironmentFactory = factory; + return this; + } + /// /// Gets or sets the name of the runtime on which the application is built. /// @@ -174,6 +198,22 @@ namespace Microsoft.Performance.Toolkit.Engine /// public bool IsInteractive { get; set; } + internal ProcessorEnvironmentFactory ProcessEnvironmentFactory + { + get + { + // Wrap any custom factory in the default factory. If there is no custom factory, or if it returns null, + // then a default runtime will be created. + return new RuntimeProcessorEnvironmentFactory( + (type) => this.LoggerFactory?.Invoke(type) ?? Logger.Create(type), + this.processEnvironmentFactory); + } + private set + { + this.processEnvironmentFactory = value; + } + } + internal ReadOnlyDictionary AuthProviders => new ReadOnlyDictionary(this.authProviders); } } diff --git a/src/Microsoft.Performance.Toolkit.Engine/ProcessorEnvironment.cs b/src/Microsoft.Performance.Toolkit.Engine/ProcessorEnvironment.cs new file mode 100644 index 0000000..0a45b43 --- /dev/null +++ b/src/Microsoft.Performance.Toolkit.Engine/ProcessorEnvironment.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using Microsoft.Performance.SDK.Processing; + +namespace Microsoft.Performance.Toolkit.Engine +{ + /// + public abstract class ProcessorEnvironment + : IProcessorEnvironment + { + /// + public abstract ILogger CreateLogger(Type processorType); + + /// + /// + /// This implementation does not support the concept of dynamic table builder and always returns + /// null. + /// + public virtual IDynamicTableBuilder RequestDynamicTableBuilder(TableDescriptor descriptor) + { + return null; + } + } +} diff --git a/src/Microsoft.Performance.Toolkit.Engine/ProcessorEnvironmentFactory.cs b/src/Microsoft.Performance.Toolkit.Engine/ProcessorEnvironmentFactory.cs new file mode 100644 index 0000000..c466c83 --- /dev/null +++ b/src/Microsoft.Performance.Toolkit.Engine/ProcessorEnvironmentFactory.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using Microsoft.Performance.SDK.Processing; +using Microsoft.Performance.SDK.Processing.DataSourceGrouping; + +namespace Microsoft.Performance.Toolkit.Engine +{ + /// + /// This is used to generate processor environments. + /// + public abstract class ProcessorEnvironmentFactory + { + /// + /// Creates a for a processor. + /// + /// + /// Identifies the source processor used to generate the data processor. + /// + /// + /// A collection of s that a can process together + /// in a specified . + /// + /// + /// A or null. When null is returned, a default processor + /// environment will be used. + /// + public abstract ProcessorEnvironment CreateProcessorEnvironment( + Guid processingSourceIdentifier, + IDataSourceGroup dataSourceGroup); + } +} diff --git a/src/Microsoft.Performance.Toolkit.Engine/RuntimeProcessorEnvironmentFactory.cs b/src/Microsoft.Performance.Toolkit.Engine/RuntimeProcessorEnvironmentFactory.cs new file mode 100644 index 0000000..aa37cce --- /dev/null +++ b/src/Microsoft.Performance.Toolkit.Engine/RuntimeProcessorEnvironmentFactory.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; +using Microsoft.Performance.SDK; +using Microsoft.Performance.SDK.Processing; +using Microsoft.Performance.SDK.Processing.DataSourceGrouping; + +namespace Microsoft.Performance.Toolkit.Engine +{ + internal sealed class RuntimeProcessorEnvironmentFactory + : ProcessorEnvironmentFactory + { + private readonly Func loggerFactory; + private readonly ProcessorEnvironmentFactory wrappedFactory; + + public RuntimeProcessorEnvironmentFactory(Func loggerFactory, ProcessorEnvironmentFactory wrappedFactory) + { + Debug.Assert(loggerFactory != null); + this.loggerFactory = loggerFactory; + this.wrappedFactory = wrappedFactory; + } + + public override ProcessorEnvironment CreateProcessorEnvironment( + Guid processingSourceIdentifier, + IDataSourceGroup dataSourceGroup) + { + return this.wrappedFactory?.CreateProcessorEnvironment(processingSourceIdentifier, dataSourceGroup) + ?? new RuntimeProcessorEnvironment(this.loggerFactory); + } + + private sealed class RuntimeProcessorEnvironment + : ProcessorEnvironment + { + private readonly Func loggerFactory; + private readonly object loggerLock = new object(); + + private ILogger logger; + private Type processorType; + + public RuntimeProcessorEnvironment( + Func loggerFactory) + { + Debug.Assert(loggerFactory != null); + + this.loggerFactory = loggerFactory; + } + + public override ILogger CreateLogger(Type processorType) + { + Guard.NotNull(processorType, nameof(processorType)); + + lock (this.loggerLock) + { + if (logger != null) + { + if (this.processorType != processorType) + { + throw new ArgumentException( + $"{nameof(CreateLogger)} cannot be called with multiple types in a single instance.", + nameof(processorType)); + } + + return this.logger; + } + + this.processorType = processorType; + this.logger = this.loggerFactory(processorType); + return this.logger; + } + } + } + } +}