Beispiel #1
0
        /// <summary>
        /// Starts the compile themes thread.
        /// </summary>
        private static void StartCompileThemesThread()
        {
            // compile less files
            CompileThemesThread = new Thread(() =>
            {
                /* Set to background thread so that this thread doesn't prevent Rock from shutting down. */
                var stopwatchCompileLess = Stopwatch.StartNew();

                Thread.CurrentThread.IsBackground = true;
                string messages = string.Empty;

                // Pass in a CancellationToken so we can stop compiling if Rock shuts down before it is done
                RockTheme.CompileAll(out messages, _threadCancellationTokenSource.Token);
                if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                {
                    if (messages.IsNullOrWhiteSpace())
                    {
                        System.Diagnostics.Debug.WriteLine(string.Format("[{0,5:#} seconds] Less files compiled successfully. ", +stopwatchCompileLess.Elapsed.TotalSeconds));
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("RockTheme.CompileAll messages: " + messages);
                    }
                }
            });

            CompileThemesThread.Start();
        }
Beispiel #2
0
        /// <summary>
        /// Handles the Start event of the Application control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void Application_Start(object sender, EventArgs e)
        {
            try
            {
                var stopwatch = System.Diagnostics.Stopwatch.StartNew();
                LogMessage(APP_LOG_FILENAME, "Application Starting...");

                if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                {
                    System.Diagnostics.Debug.WriteLine(string.Format("Application_Start: {0}", RockDateTime.Now.ToString("hh:mm:ss.FFF")));
                }

                // Clear all cache
                RockMemoryCache.Clear();

                // If not migrating, set up view cache to speed up startup (Not supported when running migrations).
                var fileInfo = new FileInfo(Server.MapPath("~/App_Data/Run.Migration"));
                if (!fileInfo.Exists)
                {
                    RockInteractiveViews.SetViewFactory(Server.MapPath("~/App_Data/RockModelViews.xml"));
                }

                // Get a db context
                using (var rockContext = new RockContext())
                {
                    if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                    {
                        try
                        {
                            // default Initializer is CreateDatabaseIfNotExists, so set it to NULL so that nothing happens if there isn't a database yet
                            Database.SetInitializer <Rock.Data.RockContext>(null);
                            new AttributeService(rockContext).Get(0);
                            System.Diagnostics.Debug.WriteLine(string.Format("ConnectToDatabase {2}/{1} - {0} ms", stopwatch.Elapsed.TotalMilliseconds, rockContext.Database.Connection.Database, rockContext.Database.Connection.DataSource));
                        }
                        catch
                        {
                            // Intentionally Blank
                        }
                    }

                    //// Run any needed Rock and/or plugin migrations
                    //// NOTE: MigrateDatabase must be the first thing that touches the database to help prevent EF from creating empty tables for a new database
                    MigrateDatabase(rockContext);

                    // Preload the commonly used objects
                    stopwatch.Restart();
                    LoadCacheObjects(rockContext);

                    if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                    {
                        System.Diagnostics.Debug.WriteLine(string.Format("LoadCacheObjects - {0} ms", stopwatch.Elapsed.TotalMilliseconds));
                    }

                    // Run any plugin migrations
                    MigratePlugins(rockContext);

                    RegisterRoutes(rockContext, RouteTable.Routes);

                    // Configure Rock Rest API
                    stopwatch.Restart();
                    GlobalConfiguration.Configure(Rock.Rest.WebApiConfig.Register);
                    if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                    {
                        System.Diagnostics.Debug.WriteLine(string.Format("Configure WebApiConfig - {0} ms", stopwatch.Elapsed.TotalMilliseconds));
                        stopwatch.Restart();
                    }

                    // setup and launch the jobs infrastructure if running under IIS
                    bool runJobsInContext = Convert.ToBoolean(ConfigurationManager.AppSettings["RunJobsInIISContext"]);
                    if (runJobsInContext)
                    {
                        ISchedulerFactory sf;

                        // create scheduler
                        sf    = new StdSchedulerFactory();
                        sched = sf.GetScheduler();

                        // get list of active jobs
                        ServiceJobService jobService = new ServiceJobService(rockContext);
                        foreach (ServiceJob job in jobService.GetActiveJobs().ToList())
                        {
                            const string errorLoadingStatus = "Error Loading Job";
                            try
                            {
                                IJobDetail jobDetail  = jobService.BuildQuartzJob(job);
                                ITrigger   jobTrigger = jobService.BuildQuartzTrigger(job);

                                sched.ScheduleJob(jobDetail, jobTrigger);

                                //// if the last status was an error, but we now loaded successful, clear the error
                                // also, if the last status was 'Running', clear that status because it would have stopped if the app restarted
                                if (job.LastStatus == errorLoadingStatus || job.LastStatus == "Running")
                                {
                                    job.LastStatusMessage = string.Empty;
                                    job.LastStatus        = string.Empty;
                                    rockContext.SaveChanges();
                                }
                            }
                            catch (Exception ex)
                            {
                                // log the error
                                LogError(ex, null);

                                // create a friendly error message
                                string message = string.Format("Error loading the job: {0}.\n\n{2}", job.Name, job.Assembly, ex.Message);
                                job.LastStatusMessage = message;
                                job.LastStatus        = errorLoadingStatus;
                                rockContext.SaveChanges();
                            }
                        }

                        // set up the listener to report back from jobs as they complete
                        sched.ListenerManager.AddJobListener(new RockJobListener(), EverythingMatcher <JobKey> .AllJobs());

                        // start the scheduler
                        sched.Start();
                    }

                    // Force the static Liquid class to get instantiated so that the standard filters are loaded prior
                    // to the custom RockFilter.  This is to allow the custom 'Date' filter to replace the standard
                    // Date filter.
                    Liquid.UseRubyDateFormat = false;

                    //// NOTE: This means that template filters will also use CSharpNamingConvention
                    //// For example the dotliquid documentation says to do this for formatting dates:
                    //// {{ some_date_value | date:"MMM dd, yyyy" }}
                    //// However, if CSharpNamingConvention is enabled, it needs to be:
                    //// {{ some_date_value | Date:"MMM dd, yyyy" }}
                    Template.NamingConvention = new DotLiquid.NamingConventions.CSharpNamingConvention();
                    Template.FileSystem       = new RockWeb.LavaFileSystem();
                    Template.RegisterSafeType(typeof(Enum), o => o.ToString());
                    Template.RegisterFilter(typeof(Rock.Lava.RockFilters));

                    // add call back to keep IIS process awake at night and to provide a timer for the queued transactions
                    AddCallBack();

                    Rock.Security.Authorization.Load();
                }

                EntityTypeService.RegisterEntityTypes(Server.MapPath("~"));
                FieldTypeService.RegisterFieldTypes(Server.MapPath("~"));

                BundleConfig.RegisterBundles(BundleTable.Bundles);

                // mark any user login stored as 'IsOnline' in the database as offline
                MarkOnlineUsersOffline();

                SqlServerTypes.Utilities.LoadNativeAssemblies(Server.MapPath("~"));

                LogMessage(APP_LOG_FILENAME, "Application Started Successfully");
                if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                {
                    System.Diagnostics.Debug.WriteLine(string.Format("Application_Started_Successfully: {0}", RockDateTime.Now.ToString("hh:mm:ss.FFF")));
                }
            }
            catch (Exception ex)
            {
                SetError66();
                throw (new Exception("Error occurred during application startup", ex));
            }

            // Update attributes for new workflow actions
            new Thread(() =>
            {
                Rock.Workflow.ActionContainer.Instance.UpdateAttributes();
            }).Start();

            // compile less files
            new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                RockTheme.CompileAll();
            }).Start();
        }
Beispiel #3
0
        /// <summary>
        /// Handles the Start event of the Application control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void Application_Start(object sender, EventArgs e)
        {
            RockApplicationStartupHelper.ShowDebugTimingMessage("Application Start");

            QueueInUse = false;

            /* 2020-05-20 MDP
             * Prior to Application_Start, Rock.WebStartup has an AssemblyInitializer class that runs as a PreApplicationStartMethod.
             *
             * This will call RockApplicationStartupHelper which will take care of the following
             *   -- EF Migrations
             *   -- Rock Plugin Migrations (except for ones that are in App_Code)
             *   -- Sending Version update notifications to Spark
             *   -- Pre-loading EntityTypeCache, FieldTypeCache, and AttributeCache
             *   -- Loading any attributes defined in web.config
             *   -- Registering HttpModules
             *   -- Initializing Lava
             *   -- Starting the Job Scheduler (if configured to run)
             */

            /* 2020-05-20 MDP
             * The remaining items need to be run here in Application_Start since they depend on things that don't happen until now
             * like Routes, plugin stuff in App_Code
             */

            try
            {
                // AssemblyInitializer will catch any exception that it gets and sets AssemblyInitializerException.
                // Doing this lets us do any error handling (now that RockWeb has started)
                if (AssemblyInitializer.AssemblyInitializerException != null)
                {
                    throw AssemblyInitializer.AssemblyInitializerException;
                }

                // register the App_Code assembly in the Rock.Reflection helper so that Reflection methods can search for types in it
                var appCodeAssembly = typeof(Global).Assembly;
                Rock.Reflection.SetAppCodeAssembly(appCodeAssembly);

                // Probably won't be any, but run any migrations that might be in App_Code. (Any that are dll's get run in RockApplicationStartupHelper.RunApplicationStartup())
                RockApplicationStartupHelper.RunPluginMigrations(appCodeAssembly);

                // Register Routes
                RouteTable.Routes.Clear();
                Rock.Web.RockRouteHandler.RegisterRoutes();

                // Configure Rock Rest API
                GlobalConfiguration.Configure(Rock.Rest.WebApiConfig.Register);

                // set the encryption protocols that are permissible for external SSL connections
                System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12;

                RockApplicationStartupHelper.ShowDebugTimingMessage("Register Routes");

                // Perform any Rock startups
                RunStartups();

                // add call back to keep IIS process awake at night and to provide a timer for the queued transactions
                AddCallBack();

                // register any EntityTypes or FieldTypes that are discovered in Rock or any plugins (including ones in ~/App_Code)
                EntityTypeService.RegisterEntityTypes();
                FieldTypeService.RegisterFieldTypes();

                BundleConfig.RegisterBundles(BundleTable.Bundles);

                // mark any user login stored as 'IsOnline' in the database as offline
                MarkOnlineUsersOffline();

                SqlServerTypes.Utilities.LoadNativeAssemblies(Server.MapPath("~"));

                RockApplicationStartupHelper.ShowDebugTimingMessage("Register Types");

                RockApplicationStartupHelper.LogStartupMessage("Application Started Successfully");
                if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                {
                    System.Diagnostics.Debug.WriteLine(string.Format("[{0,5:#} ms] Total Startup Time", (RockDateTime.Now - RockApplicationStartupHelper.StartDateTime).TotalMilliseconds));
                }

                ExceptionLogService.AlwaysLogToFile = false;
            }
            catch (Exception ex)
            {
                if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                {
                    System.Diagnostics.Debug.WriteLine(string.Format("##Startup Exception##: {0}\n{1}", ex.Message, ex.StackTrace));
                }

                SetError66();
                var startupException = new RockStartupException("Error occurred during application startup", ex);
                LogError(startupException, null);
                throw startupException;
            }

            // Update attributes for new workflow actions, instead of doing them on demand
            // Not sure why we did this but this is the commit c23a4021d2ce7be96a30bae8c431c113f942f26f
            new Thread(() =>
            {
                Rock.Workflow.ActionContainer.Instance.UpdateAttributes();
            }).Start();

            // compile less files
            new Thread(() =>
            {
                var stopwatchCompileLess          = Stopwatch.StartNew();
                Thread.CurrentThread.IsBackground = true;
                string messages = string.Empty;
                RockTheme.CompileAll(out messages);
                if (System.Web.Hosting.HostingEnvironment.IsDevelopmentEnvironment)
                {
                    if (messages.IsNullOrWhiteSpace())
                    {
                        System.Diagnostics.Debug.WriteLine(string.Format("[{0,5:#} seconds] Less files compiled successfully. ", +stopwatchCompileLess.Elapsed.TotalSeconds));
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("RockTheme.CompileAll messages: " + messages);
                    }
                }
            }).Start();
        }