Exemple #1
0
        private async Task ExecuteStepAsync(RecipeExecutionContext recipeStep)
        {
            var shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings);

            using (var scope = shellContext.CreateServiceScope())
            {
                if (!shellContext.IsActivated)
                {
                    var eventBus = scope.ServiceProvider.GetService <IEventBus>();
                    await eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatingAsync());

                    await eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatedAsync());

                    shellContext.IsActivated = true;
                }

                var recipeStepHandlers = scope.ServiceProvider.GetRequiredService <IEnumerable <IRecipeStepHandler> >();
                var scriptingManager   = scope.ServiceProvider.GetRequiredService <IScriptingManager>();
                scriptingManager.GlobalMethodProviders.Add(_environmentMethodProvider);

                // Substitutes the script elements by their actual values
                EvaluateScriptNodes(recipeStep, scriptingManager);

                foreach (var recipeStepHandler in recipeStepHandlers)
                {
                    if (Logger.IsEnabled(LogLevel.Information))
                    {
                        Logger.LogInformation("Executing recipe step '{0}'.", recipeStep.Name);
                    }

                    await _eventBus.NotifyAsync <IRecipeEventHandler>(e => e.RecipeStepExecutingAsync(recipeStep));

                    await recipeStepHandler.ExecuteAsync(recipeStep);

                    await _eventBus.NotifyAsync <IRecipeEventHandler>(e => e.RecipeStepExecutedAsync(recipeStep));

                    if (Logger.IsEnabled(LogLevel.Information))
                    {
                        Logger.LogInformation("Finished executing recipe step '{0}'.", recipeStep.Name);
                    }
                }
            }

            // The recipe execution might have invalidated the shell by enabling new features,
            // so the deferred tasks need to run on an updated shell context if necessary.
            shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings);
            using (var scope = shellContext.CreateServiceScope())
            {
                var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>();

                // The recipe might have added some deferred tasks to process
                if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks)
                {
                    var taskContext = new DeferredTaskContext(scope.ServiceProvider);
                    await deferredTaskEngine.ExecuteTasksAsync(taskContext);
                }
            }
        }
        public async Task Invoke(HttpContext httpContext)
        {
            // Ensure all ShellContext are loaded and available.
            _orchardHost.Initialize();

            var shellSetting = _runningShellTable.Match(httpContext);

            // Register the shell settings as a custom feature.
            httpContext.Features[typeof(ShellSettings)] = shellSetting;

            // We only serve the next request if the tenant has been resolved.
            if (shellSetting != null)
            {
                ShellContext shellContext = _orchardHost.GetOrCreateShellContext(shellSetting);

                using (var scope = shellContext.CreateServiceScope())
                {
                    httpContext.RequestServices = scope.ServiceProvider;

                    if (!shellContext.IsActivated)
                    {
                        lock (shellSetting)
                        {
                            // The tenant gets activated here
                            if (!shellContext.IsActivated)
                            {
                                var eventBus = scope.ServiceProvider.GetService <IEventBus>();
                                eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatingAsync()).Wait();
                                eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatedAsync()).Wait();

                                shellContext.IsActivated = true;
                            }
                        }
                    }

                    await _next.Invoke(httpContext);
                }

                using (var scope = shellContext.CreateServiceScope())
                {
                    var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>();

                    if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks)
                    {
                        var context = new DeferredTaskContext(scope.ServiceProvider);
                        await deferredTaskEngine.ExecuteTasksAsync(context);
                    }
                }
            }
        }
Exemple #3
0
        private void DoWork(object group)
        {
            // DoWork is not re-entrant as Timer will not call the callback until the previous callback has returned.
            // This way if a tasks takes longer than the period itself, DoWork is not called while it's still running.
            ShellContext shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings);

            var groupName = group as string ?? "";

            foreach (var task in _tasks[groupName])
            {
                var taskName = task.GetType().FullName;

                using (var scope = shellContext.CreateServiceScope())
                {
                    try
                    {
                        lock (_states)
                        {
                            _states[task] = BackgroundTaskState.Running;
                        }

                        if (Logger.IsEnabled(LogLevel.Information))
                        {
                            Logger.LogInformation("Start processing background task \"{0}\".", taskName);
                        }

                        task.DoWork(scope.ServiceProvider, _applicationLifetime.ApplicationStopping);

                        if (Logger.IsEnabled(LogLevel.Information))
                        {
                            Logger.LogInformation("Finished processing background task \"{0}\".", taskName);
                        }
                    }
                    catch (Exception ex)
                    {
                        if (Logger.IsEnabled(LogLevel.Error))
                        {
                            Logger.LogError($"Error while processing background task \"{taskName}\": {ex.Message}");
                        }
                    }
                    finally
                    {
                        lock (_states)
                        {
                            _states[task] = BackgroundTaskState.Idle;
                        }
                    }
                }
            }
        }
        public async Task Invoke(HttpContext httpContext)
        {
            // Ensure all ShellContext are loaded and available.
            _orchardHost.Initialize();

            var shellSetting = _runningShellTable.Match(httpContext);

            // Register the shell settings as a custom feature.
            httpContext.Features.Set(shellSetting);

            // We only serve the next request if the tenant has been resolved.
            if (shellSetting != null)
            {
                var shellContext = _orchardHost.GetOrCreateShellContext(shellSetting);

                using (var scope = shellContext.CreateServiceScope())
                {
                    httpContext.RequestServices = scope.ServiceProvider;

                    if (!shellContext.IsActivated)
                    {
                        lock (shellContext)
                        {
                            // The tenant gets activated here
                            if (!shellContext.IsActivated)
                            {
                                var tenantEvents = scope.ServiceProvider
                                                   .GetServices <IModularTenantEvents>();

                                foreach (var tenantEvent in tenantEvents)
                                {
                                    tenantEvent.ActivatingAsync().Wait();
                                }

                                httpContext.Items["BuildPipeline"] = true;
                                shellContext.IsActivated           = true;

                                foreach (var tenantEvent in tenantEvents)
                                {
                                    tenantEvent.ActivatedAsync().Wait();
                                }
                            }
                        }
                    }

                    await _next.Invoke(httpContext);
                }
            }
        }
Exemple #5
0
        public async Task <IActionResult> Create(EditTenantViewModel model)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageTenants))
            {
                return(Unauthorized());
            }

            if (!IsDefaultShell())
            {
                return(Unauthorized());
            }

            if (ModelState.IsValid)
            {
                ValidateViewModel(model, true);
            }

            if (ModelState.IsValid)
            {
                var shellSettings = new ShellSettings
                {
                    Name             = model.Name,
                    RequestUrlPrefix = model.RequestUrlPrefix,
                    RequestUrlHost   = model.RequestUrlHost,
                    ConnectionString = model.ConnectionString,
                    TablePrefix      = model.TablePrefix,
                    DatabaseProvider = model.DatabaseProvider,
                    State            = TenantState.Uninitialized
                };

                _shellSettingsManager.SaveSettings(shellSettings);
                var shellContext = _orchardHost.GetOrCreateShellContext(shellSettings);

                return(RedirectToAction(nameof(Index)));
            }

            // If we got this far, something failed, redisplay form
            return(View(model));
        }
        public async Task Invoke(HttpContext httpContext)
        {
            await _next.Invoke(httpContext);

            // Register the shell settings as a custom feature.
            var shellSettings = httpContext.Features[typeof(ShellSettings)] as ShellSettings;

            // We only serve the next request if the tenant has been resolved.
            if (shellSettings != null)
            {
                ShellContext shellContext = _orchardHost.GetOrCreateShellContext(shellSettings);

                using (var scope = shellContext.CreateServiceScope())
                {
                    var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>();

                    if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks)
                    {
                        var context = new DeferredTaskContext(scope.ServiceProvider);
                        await deferredTaskEngine.ExecuteTasksAsync(context);
                    }
                }
            }
        }
Exemple #7
0
        public async Task <string> ExecuteAsync(string executionId, RecipeDescriptor recipeDescriptor)
        {
            await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.RecipeExecutingAsync(executionId, recipeDescriptor));

            try
            {
                var parsersForFileExtension = _recipeOptions
                                              .RecipeFileExtensions
                                              .Where(rfx => Path.GetExtension(rfx.Key) == Path.GetExtension(recipeDescriptor.RecipeFileInfo.PhysicalPath));

                using (var stream = recipeDescriptor.RecipeFileInfo.CreateReadStream())
                {
                    RecipeResult result = new RecipeResult {
                        ExecutionId = executionId
                    };
                    List <RecipeStepResult> stepResults = new List <RecipeStepResult>();

                    foreach (var parserForFileExtension in parsersForFileExtension)
                    {
                        var recipeParser = _recipeParsers.First(x => x.GetType() == parserForFileExtension.Value);

                        await recipeParser.ProcessRecipeAsync(stream, (recipe, recipeStep) =>
                        {
                            // TODO, create Result prior to run
                            stepResults.Add(new RecipeStepResult
                            {
                                ExecutionId = executionId,
                                RecipeName  = recipeDescriptor.Name,
                                StepId      = recipeStep.Id,
                                StepName    = recipeStep.Name
                            });
                            return(Task.CompletedTask);
                        });
                    }

                    result.Steps = stepResults;
                    await _recipeStore.UpdateAsync(result);
                }

                using (var stream = recipeDescriptor.RecipeFileInfo.CreateReadStream())
                {
                    foreach (var parserForFileExtension in parsersForFileExtension)
                    {
                        var recipeParser = _recipeParsers.First(x => x.GetType() == parserForFileExtension.Value);

                        await recipeParser.ProcessRecipeAsync(stream, async (recipe, recipeStep) =>
                        {
                            var shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings);
                            using (var scope = shellContext.CreateServiceScope())
                            {
                                if (!shellContext.IsActivated)
                                {
                                    var eventBus = scope.ServiceProvider.GetService <IEventBus>();
                                    await eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatingAsync());
                                    await eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatedAsync());

                                    shellContext.IsActivated = true;
                                }

                                var recipeStepExecutor = scope.ServiceProvider.GetRequiredService <IRecipeStepExecutor>();

                                if (_applicationLifetime.ApplicationStopping.IsCancellationRequested)
                                {
                                    throw new OrchardException(T["Recipe cancelled, application is restarting"]);
                                }

                                await recipeStepExecutor.ExecuteAsync(executionId, recipeStep);
                            }

                            // The recipe execution might have invalidated the shell by enabling new features,
                            // so the deferred tasks need to run on an updated shell context if necessary.
                            shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings);
                            using (var scope = shellContext.CreateServiceScope())
                            {
                                var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>();

                                // The recipe might have added some deferred tasks to process
                                if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks)
                                {
                                    var taskContext = new DeferredTaskContext(scope.ServiceProvider);
                                    await deferredTaskEngine.ExecuteTasksAsync(taskContext);
                                }
                            }
                        });
                    }
                }

                await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.RecipeExecutedAsync(executionId, recipeDescriptor));

                return(executionId);
            }
            catch (Exception)
            {
                await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.ExecutionFailedAsync(executionId, recipeDescriptor));

                throw;
            }
        }
        public async Task <string> ExecuteAsync(string executionId, RecipeDescriptor recipeDescriptor)
        {
            await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.RecipeExecutingAsync(executionId, recipeDescriptor));

            try
            {
                RecipeResult result = new RecipeResult {
                    ExecutionId = executionId
                };
                List <RecipeStepResult> stepResults = new List <RecipeStepResult>();

                using (StreamReader file = File.OpenText(recipeDescriptor.RecipeFileInfo.PhysicalPath))
                {
                    using (var reader = new JsonTextReader(file))
                    {
                        VariablesMethodProvider variablesMethodProvider = null;

                        // Go to Steps, then iterate.
                        while (reader.Read())
                        {
                            if (reader.Path == "variables")
                            {
                                reader.Read();

                                var variables = JObject.Load(reader);
                                variablesMethodProvider = new VariablesMethodProvider(variables);
                            }

                            if (reader.Path == "steps" && reader.TokenType == JsonToken.StartArray)
                            {
                                int stepId = 0;
                                while (reader.Read() && reader.Depth > 1)
                                {
                                    if (reader.Depth == 2)
                                    {
                                        var child = JToken.Load(reader);

                                        var recipeStep = new RecipeStepDescriptor
                                        {
                                            Id   = (stepId++).ToString(),
                                            Name = child.Value <string>("name"),
                                            Step = child
                                        };

                                        var shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings);
                                        using (var scope = shellContext.CreateServiceScope())
                                        {
                                            if (!shellContext.IsActivated)
                                            {
                                                var eventBus = scope.ServiceProvider.GetService <IEventBus>();
                                                await eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatingAsync());

                                                await eventBus.NotifyAsync <IOrchardShellEvents>(x => x.ActivatedAsync());

                                                shellContext.IsActivated = true;
                                            }

                                            var recipeStepExecutor = scope.ServiceProvider.GetRequiredService <IRecipeStepExecutor>();
                                            var scriptingManager   = scope.ServiceProvider.GetRequiredService <IScriptingManager>();

                                            if (variablesMethodProvider != null)
                                            {
                                                variablesMethodProvider.ScriptingManager = scriptingManager;
                                                scriptingManager.GlobalMethodProviders.Add(variablesMethodProvider);
                                            }

                                            if (_applicationLifetime.ApplicationStopping.IsCancellationRequested)
                                            {
                                                throw new OrchardException(T["Recipe cancelled, application is restarting"]);
                                            }

                                            EvaluateJsonTree(scriptingManager, recipeStep.Step);

                                            await recipeStepExecutor.ExecuteAsync(executionId, recipeStep);
                                        }

                                        // The recipe execution might have invalidated the shell by enabling new features,
                                        // so the deferred tasks need to run on an updated shell context if necessary.
                                        shellContext = _orchardHost.GetOrCreateShellContext(_shellSettings);
                                        using (var scope = shellContext.CreateServiceScope())
                                        {
                                            var recipeStepExecutor = scope.ServiceProvider.GetRequiredService <IRecipeStepExecutor>();

                                            var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>();

                                            // The recipe might have added some deferred tasks to process
                                            if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks)
                                            {
                                                var taskContext = new DeferredTaskContext(scope.ServiceProvider);
                                                await deferredTaskEngine.ExecuteTasksAsync(taskContext);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.RecipeExecutedAsync(executionId, recipeDescriptor));

                return(executionId);
            }
            catch (Exception)
            {
                await _eventBus.NotifyAsync <IRecipeEventHandler>(x => x.ExecutionFailedAsync(executionId, recipeDescriptor));

                throw;
            }
        }