Пример #1
0
        private async Task Seed(SeedingPlan seedingPlan)
        {
            SeedInfo currentSeedInfo = null;
            int      seedingStep     = 0;

            try
            {
                var serviceCollection = new ServiceCollection();

                var seedingSetup = seedingPlan.SeedingSetup;

                if (seedingSetup == null && seedingPlan.SeedingSetupType != null)
                {
                    seedingSetup = (ISeedingSetup)Activator.CreateInstance(seedingPlan.SeedingSetupType);
                }

                if (seedingSetup != null)
                {
                    RaiseMessageEvent($"Configuring services by using the seeding setup '{seedingPlan.SeedingSetupType}'.");
                    seedingSetup.ConfigureServices(serviceCollection, seedingSetup.BuildConfiguration(new string[0]));
                    RaiseMessageEvent("Services configured.");
                }
                else
                {
                    RaiseMessageEvent($"No seeding setup found.");
                }

                var serviceProvider = serviceCollection.BuildServiceProvider();

                for (int i = 0; i < seedingPlan.Seeds.Count; i++)
                {
                    currentSeedInfo = seedingPlan.Seeds[i];
                    seedingStep     = i + 1;
                    await SeedSingleSeed(seedingStep, serviceProvider, currentSeedInfo);
                }
            }
            catch (SeedContractViolationException exception)
            {
                SeedContractViolation?.Invoke(this, new SeedContractViolationEventArgs(seedingStep, currentSeedInfo, exception.Message));
                SeedingAborted?.Invoke(this, new SeedingEventArgs(seedingStep, currentSeedInfo));
            }
            catch (Exception exception)
            {
                RaiseMessageEvent($"Exception: {exception}");
                SeedingAborted?.Invoke(this, new SeedingEventArgs(seedingStep, currentSeedInfo));
            }
        }
Пример #2
0
        private async Task <SeedingReport> Seed(SeedBucketInfo seedBucketInfo, SeedBucketStartup?seedBucketStartup, ISeedableFilter filter)
        {
            if (seedBucketInfo.HasAnyErrors)
            {
                return(SeedingReport.CreateForSeedBucketHasErrors(seedBucketInfo));
            }

            var seedingPlan = SeedingPlan.CreateFor(seedBucketInfo, filter);

            // TODO: Check if the seeding plan is empty and return appropriate report.
            //       In the report show the used filter. "... no seeds or scenarios that satisfied the given filter: ...". Add the FriendlyDescription property to the ISeedablesFilter.

            return(await SeedSeedingPlan());

            async Task <SeedingReport> SeedSeedingPlan()
            {
                var singleSeedSeedingResults = new List <SingleSeedSeedingReport>();

                IServiceCollection serviceCollection = new ServiceCollection(); // TODO: We should have more of them. Think about lifecycle of the engine services, services in the different stages in the execution, etc.

                serviceCollection.AddSingleton(outputSink);
                try
                {
                    // TODO: Add creation of SeedingStartup and registration of services.
                    if (seedBucketStartup != null)
                    {
                        outputSink.WriteVerboseMessage($"Configuring service collection");

                        seedBucketStartup.ConfigureServices(serviceCollection);

                        // TODO: Check that the configuration does not override IOutputSink. Only the engine can add it. It must be singleton and the same one we have here.

                        outputSink.WriteVerboseMessage($"Initializing seeding");

                        using (var serviceScope = serviceCollection.BuildServiceProvider().CreateScope())
                        {
                            seedBucketStartup.InitializeSeeding(serviceScope.ServiceProvider);
                        }
                    }

                    // TODO: Add finer granulation of errors and seeding result - CreatingSeedingStartupFailed.
                }
                catch (Exception exception)
                {
                    outputSink.WriteError(exception.ToString()); // TODO: Output sink for exceptions.

                    return(SeedingReport.CreateForBuildingServiceProviderFailed(seedBucketInfo, seedingPlan));
                }

                var serviceProvider = serviceCollection.BuildServiceProvider();

                SeedInfo?currentSeedInfo;
                int      seedingStepNumber;

                for (int i = 0; i < seedingPlan.SeedingSteps.Count; i++)
                {
                    currentSeedInfo   = seedingPlan.SeedingSteps[i];
                    seedingStepNumber = i + 1;
                    try
                    {
                        bool hasSeeded;
                        using (var serviceScope = serviceProvider.CreateScope())
                        {
                            hasSeeded = await SeedSingleSeed(seedingStepNumber, serviceScope.ServiceProvider, currentSeedInfo);
                        }

                        singleSeedSeedingResults.Add(new SingleSeedSeedingReport(hasSeeded ? SingleSeedSeedingStatus.Seeded : SingleSeedSeedingStatus.Skipped, currentSeedInfo));
                    }
                    catch (Exception exception)
                    {
                        outputSink.WriteError(exception.ToString()); // TODO: Output sink that supports exceptions.

                        // TODO: Add finer granulation of errors and seeding result - CreatingSeedFailed.
                        // TODO: Add seed contract violation.
                        singleSeedSeedingResults.Add(new SingleSeedSeedingReport(SingleSeedSeedingStatus.Failed, currentSeedInfo));
                        return(SeedingReport.CreateForSeedingSingleSeedFailed(seedBucketInfo, seedingPlan, singleSeedSeedingResults));
                    }
                }

                outputSink.WriteConfirmation($"Seeding completed");

                return(SeedingReport.CreateForSucceeded(seedBucketInfo, seedingPlan, singleSeedSeedingResults));

                // Returns true if Seed() is called or false if the seed HasAlreadyYielded().
                async Task <bool> SeedSingleSeed(int seedingStep, IServiceProvider serviceProvider, SeedInfo seedInfo)
                {
                    System.Diagnostics.Debug.Assert(seedingStep > 0);

                    outputSink.WriteVerboseMessage($"Creating seed {seedInfo.FriendlyName}");

                    // TODO: Check if seedInfo.Type exists. Where to check that? Seeding should work only if Type exists. Where to add those checks?
                    var seed = (ISeed)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, seedInfo.Type);

                    // TODO: Create YieldOf objects and assign them to YieldOf properties.
                    // TODO: Think what to do if the Type or PropertyInfo is null.
                    foreach (var requiredYield in seedInfo.RequiredYields)
                    {
                        // TODO: Check if it is already created. If we have two properties of the same yield type. This must never be the case it should be an error in the seed definition.
                        // TOOD: Yield access property must be public or internal or protected. It also must have non private setter.

                        var yieldingSeed = (ISeed)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, requiredYield.YieldingSeed.Type);

                        var yield = ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, requiredYield.Type);

                        var seedPropertyOnYield = yield.GetType().GetProperty("Seed", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance);

                        // seedPropertyOnYield.SetValue(yield, yieldingSeed, BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.SetProperty, null, null, null);
                        seedPropertyOnYield.SetValue(yield, yieldingSeed);

                        requiredYield.YieldAccessProperty !.SetValue(seed, yield);
                    }

                    if (await seed.HasAlreadyYielded())
                    {
                        outputSink.WriteMessage($"Skipping {seedInfo.FriendlyName}");
                        return(false);
                    }

                    outputSink.WriteMessage($"Seeding {seedInfo.FriendlyName}");

                    await seed.Seed();

                    outputSink.WriteMessage($"Seeding {seedInfo.FriendlyName} completed");

                    return(true);
                }
            }
        }
Пример #3
0
 public static SeedingReport CreateForSucceeded(SeedBucketInfo seedBucketInfo, SeedingPlan seedingPlan, IReadOnlyCollection <SingleSeedSeedingReport> singleSeedSeedingResults)
 {
     return(new SeedingReport
            (
                seedBucketInfo,
                seedingPlan,
                singleSeedSeedingResults,
                SeedingStatus.Succeeded
            ));
 }
Пример #4
0
 public static SeedingReport CreateForBuildingServiceProviderFailed(SeedBucketInfo seedBucketInfo, SeedingPlan seedingPlan)
 {
     return(new SeedingReport
            (
                seedBucketInfo,
                seedingPlan,
                Array.Empty <SingleSeedSeedingReport>(),
                SeedingStatus.BuildingServiceProviderFailed
            ));
 }
Пример #5
0
        public async Task <SeedingReport> Seed(Type seedBucketType)
        {
            System.Diagnostics.Debug.Assert(typeof(SeedBucket).IsAssignableFrom(seedBucketType));

            // We know that the seed bucket info builder always returns
            // a seed bucket info and never null; threfore "!".
            var seedBucketInfo = seedBucketInfoBuilder.BuildFrom(seedBucketType) !;

            if (seedBucketInfo.HasAnyErrors)
            {
                return(SeedingReport.CreateForSeedBucketHasErrors(seedBucketInfo));
            }

            var seedingPlan = SeedingPlan.CreateFor(seedBucketInfo);

            return(await SeedSeedingPlan());

            async Task <SeedingReport> SeedSeedingPlan()
            {
                SeedInfo?       currentSeedInfo;
                int             seedingStepNumber;
                var             serviceCollection = new ServiceCollection();
                ServiceProvider?serviceProvider;
                var             singleSeedSeedingResults = new List <SingleSeedSeedingReport>();

                try
                {
                    // TODO: Add creation of SeedingStartup and registration of services.

                    // TODO: Add finer granulation of errors and seeding result - CreatingSeedingStartupFailed.

                    serviceProvider = serviceCollection.BuildServiceProvider();
                }
                catch
                {
                    // TODO: Output sink.
                    return(SeedingReport.CreateForBuildingServiceProviderFailed(seedBucketInfo, seedingPlan));
                }

                for (int i = 0; i < seedingPlan.SeedingSteps.Count; i++)
                {
                    currentSeedInfo   = seedingPlan.SeedingSteps[i];
                    seedingStepNumber = i + 1;
                    try
                    {
                        var hasSeeded = await SeedSingleSeed(seedingStepNumber, serviceProvider, currentSeedInfo);

                        singleSeedSeedingResults.Add(new SingleSeedSeedingReport(hasSeeded ? SingleSeedSeedingStatus.Seeded : SingleSeedSeedingStatus.Skipped, currentSeedInfo));
                    }
                    catch
                    {
                        // TODO: Output sink.
                        // TODO: Add finer granulation of errors and seeding result - CreatingSeedFailed.
                        // TODO: Add seed contract violation.
                        singleSeedSeedingResults.Add(new SingleSeedSeedingReport(SingleSeedSeedingStatus.Failed, currentSeedInfo));
                        return(SeedingReport.CreateForSeedingSingleSeedFailed(seedBucketInfo, seedingPlan, singleSeedSeedingResults));
                    }
                }

                return(SeedingReport.CreateForSucceeded(seedBucketInfo, seedingPlan, singleSeedSeedingResults));

                // Returns true if Seed() is called or false if the seed HasAlreadyYielded().
                async Task <bool> SeedSingleSeed(int seedingStep, ServiceProvider serviceProvider, SeedInfo seedInfo)
                {
                    System.Diagnostics.Debug.Assert(seedingStep > 0);

                    // TODO: Output sink.

                    // TODO: Check if seedInfo.Type exists. Where to check that? Seeding should work only if Type exists. Where to add those checks?
                    var seed = (ISeed)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, seedInfo.Type);

                    // TODO: Create YieldOf objects and assign them to YieldOf properties.

                    if (await seed.HasAlreadyYielded())
                    {
                        // TODO: Output sink.
                        return(false);
                    }

                    // TODO: Output sink.

                    await seed.Seed();

                    // TODO: Output sink.

                    return(true);
                }
            }
        }