Beispiel #1
0
        private void CacheJobBinaries(JobBase job, IJobLogger logger)
        {
            bool isInPlaceDefault = job.ScriptHost.GetType() == typeof(NodeScriptHost);
            if (JobSettings.GetIsInPlace(isInPlaceDefault))
            {
                _inPlaceWorkingDirectory = JobBinariesPath;
                SafeKillAllRunningJobInstances(logger);
                UpdateAppConfigs(WorkingDirectory);
                return;
            }

            _inPlaceWorkingDirectory = null;

            if (WorkingDirectory != null)
            {
                try
                {
                    int currentHash = CalculateHashForJob(JobBinariesPath);
                    int lastHash = CalculateHashForJob(WorkingDirectory);

                    if (lastHash == currentHash)
                    {
                        return;
                    }
                }
                catch (Exception ex)
                {
                    // Log error and ignore it as it's not critical to cache job binaries
                    logger.LogWarning("Failed to calculate hash for WebJob, continue to copy WebJob binaries (this will not affect WebJob run)\n" + ex);
                    _analytics.UnexpectedException(ex);
                }
            }

            SafeKillAllRunningJobInstances(logger);

            if (FileSystemHelpers.DirectoryExists(JobTempPath))
            {
                FileSystemHelpers.DeleteDirectorySafe(JobTempPath, ignoreErrors: true);
            }

            if (FileSystemHelpers.DirectoryExists(JobTempPath))
            {
                logger.LogWarning("Failed to delete temporary directory");
            }

            try
            {
                OperationManager.Attempt(() =>
                {
                    var tempJobInstancePath = Path.Combine(JobTempPath, Path.GetRandomFileName());

                    FileSystemHelpers.CopyDirectoryRecursive(JobBinariesPath, tempJobInstancePath);
                    UpdateAppConfigs(tempJobInstancePath);

                    _workingDirectory = tempJobInstancePath;
                });
            }
            catch (Exception ex)
            {
                //Status = "Worker is not running due to an error";
                //TraceError("Failed to copy bin directory: " + ex);
                logger.LogError("Failed to copy job files: " + ex);
                _analytics.UnexpectedException(ex);

                // job disabled
                _workingDirectory = null;
            }
        }
Beispiel #2
0
 private void AssertJob(JobBase expectedJob, JobBase actualJob)
 {
     Assert.NotNull(actualJob);
     Assert.Equal(expectedJob.Name, actualJob.Name);
     Assert.Equal(expectedJob.RunCommand, actualJob.RunCommand);
     Assert.Equal(expectedJob.JobType, actualJob.JobType);
     Assert.NotNull(actualJob.Url);
     Assert.NotNull(actualJob.ExtraInfoUrl);
 }
Beispiel #3
0
            public JobStartedReporter(IAnalytics analytics, JobBase job, string trigger, string siteMode, string jobDataPath)
            {
                _analytics = analytics;
                _job = job;
                _trigger = trigger;
                _siteMode = siteMode;
                _jobDataPath = jobDataPath;

                _timer = new Timer(Report, null, ReportTimeoutInMilliseconds, Timeout.Infinite);
            }
Beispiel #4
0
        protected void RunJobInstance(JobBase job, IJobLogger logger, string runId, string trigger, int port = -1)
        {
            string scriptFileName = Path.GetFileName(job.ScriptFilePath);
            string scriptFileFullPath = Path.Combine(WorkingDirectory, job.RunCommand);
            string workingDirectoryForScript = Path.GetDirectoryName(scriptFileFullPath);

            logger.LogInformation("Run script '{0}' with script host - '{1}'".FormatCurrentCulture(scriptFileName, job.ScriptHost.GetType().Name));

            using (var jobStartedReporter = new JobStartedReporter(_analytics, job, trigger, Settings.GetWebSiteSku(), JobDataPath))
            {
                try
                {
                    var exe = _externalCommandFactory.BuildCommandExecutable(job.ScriptHost.HostPath, workingDirectoryForScript, IdleTimeout, NullLogger.Instance);

                    _shutdownNotificationFilePath = RefreshShutdownNotificationFilePath(job.Name, job.JobType);

                    // Set environment variable to be able to identify all processes spawned for this job
                    exe.EnvironmentVariables[GetJobEnvironmentKey()] = "true";
                    exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsRootPath] = WorkingDirectory;
                    exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsName] = job.Name;
                    exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsType] = job.JobType;
                    exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsDataPath] = JobDataPath;
                    exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsRunId] = runId;
                    exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsCommandArguments] = job.CommandArguments;
                    if (port != -1)
                    {
                        exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsPort] = port.ToString();
                    }

                    if (_shutdownNotificationFilePath != null)
                    {
                        exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsShutdownNotificationFile] = _shutdownNotificationFilePath;
                    }

                    UpdateStatus(logger, "Running");

                    int exitCode =
                        exe.ExecuteReturnExitCode(
                            TraceFactory.GetTracer(),
                            logger.LogStandardOutput,
                            logger.LogStandardError,
                            job.ScriptHost.ArgumentsFormat,
                            scriptFileName,
                            job.CommandArguments != null ? " " + job.CommandArguments : String.Empty);

                    if (exitCode != 0)
                    {
                        string errorMessage = "Job failed due to exit code " + exitCode;
                        logger.LogError(errorMessage);
                        jobStartedReporter.Error = errorMessage;
                    }
                    else
                    {
                        UpdateStatus(logger, "Success");
                    }
                }
                catch (ThreadAbortException)
                {
                    // We kill the process when refreshing the job
                    logger.LogInformation("WebJob process was aborted");
                    UpdateStatus(logger, "Stopped");
                }
                catch (Exception ex)
                {
                    logger.LogError(ex.ToString());
                    jobStartedReporter.Error = ex.Message;
                }
            }
        }
Beispiel #5
0
        protected void InitializeJobInstance(JobBase job, IJobLogger logger)
        {
            if (!String.Equals(JobName, job.Name, StringComparison.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException(
                    "The job runner can only run jobs with the same name it was configured, configured - {0}, trying to run - {1}".FormatInvariant(
                        JobName, job.Name));
            }

            if (!FileSystemHelpers.FileExists(job.ScriptFilePath))
            {
                throw new InvalidOperationException("Missing job script to run - {0}".FormatInvariant(job.ScriptFilePath));
            }

            CacheJobBinaries(job, logger);

            if (WorkingDirectory == null)
            {
                throw new InvalidOperationException("Missing working directory");
            }
        }
Beispiel #6
0
        private void CacheJobBinaries(JobBase job, IJobLogger logger)
        {
            bool isInPlaceDefault = job.ScriptHost.GetType() == typeof(NodeScriptHost);
            if (JobSettings.GetIsInPlace(isInPlaceDefault))
            {
                _inPlaceWorkingDirectory = JobBinariesPath;
                SafeKillAllRunningJobInstances(logger);
                UpdateAppConfigs(WorkingDirectory, _analytics);
                return;
            }

            _inPlaceWorkingDirectory = null;

            Dictionary<string, FileInfoBase> sourceDirectoryFileMap = GetJobDirectoryFileMap(JobBinariesPath);
            if (WorkingDirectory != null)
            {
                try
                {
                    var workingDirectoryFileMap = GetJobDirectoryFileMap(WorkingDirectory);
                    if (!JobDirectoryHasChanged(sourceDirectoryFileMap, workingDirectoryFileMap, _cachedSourceDirectoryFileMap, logger))
                    {
                        // no changes detected, so skip the cache/copy step below
                        return;
                    }
                }
                catch (Exception ex)
                {
                    // Log error and ignore it, since this diff optimization isn't critical.
                    // We'll just do a full copy in this case.
                    logger.LogWarning("Failed to diff WebJob directories for changes. Continuing to copy WebJob binaries (this will not affect the WebJob run)\n" + ex);
                    _analytics.UnexpectedException(ex);
                }
            }

            SafeKillAllRunningJobInstances(logger);

            if (FileSystemHelpers.DirectoryExists(JobTempPath))
            {
                FileSystemHelpers.DeleteDirectorySafe(JobTempPath, ignoreErrors: true);
            }

            if (FileSystemHelpers.DirectoryExists(JobTempPath))
            {
                logger.LogWarning("Failed to delete temporary directory");
            }

            try
            {
                OperationManager.Attempt(() =>
                {
                    var tempJobInstancePath = Path.Combine(JobTempPath, Path.GetRandomFileName());

                    FileSystemHelpers.CopyDirectoryRecursive(JobBinariesPath, tempJobInstancePath);
                    UpdateAppConfigs(tempJobInstancePath, _analytics);

                    _workingDirectory = tempJobInstancePath;

                    // cache the file map snapshot for next time (to aid in detecting
                    // file deletions)
                    _cachedSourceDirectoryFileMap = sourceDirectoryFileMap;
                });
            }
            catch (Exception ex)
            {
                //Status = "Worker is not running due to an error";
                //TraceError("Failed to copy bin directory: " + ex);
                logger.LogError("Failed to copy job files: " + ex);
                _analytics.UnexpectedException(ex);

                // job disabled
                _workingDirectory = null;
            }
        }
Beispiel #7
0
        protected void RunJobInstance(JobBase job, IJobLogger logger, string runId)
        {
            string scriptFileName = Path.GetFileName(job.ScriptFilePath);
            string scriptFileExtension = Path.GetExtension(job.ScriptFilePath);

            logger.LogInformation("Run script '{0}' with script host - '{1}'".FormatCurrentCulture(scriptFileName, job.ScriptHost.GetType().Name));
            string siteMode = Settings.GetWebSitePolicy();
            _analytics.JobStarted(job.Name.Fuzz(), scriptFileExtension, job.JobType, siteMode);

            try
            {
                var exe = _externalCommandFactory.BuildCommandExecutable(job.ScriptHost.HostPath, WorkingDirectory, IdleTimeout, NullLogger.Instance);

                // Set environment variable to be able to identify all processes spawned for this job
                exe.EnvironmentVariables[GetJobEnvironmentKey()] = "true";
                exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsRootPath] = WorkingDirectory;
                exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsName] = job.Name;
                exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsType] = job.JobType;
                exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsDataPath] = JobDataPath;
                exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsRunId] = runId;
                exe.EnvironmentVariables[WellKnownEnvironmentVariables.WebJobsExtraUrlPath] = JobsManagerBase.GetJobExtraInfoUrlFilePath(JobDataPath);

                UpdateStatus(logger, "Running");

                int exitCode =
                    exe.ExecuteReturnExitCode(
                        TraceFactory.GetTracer(),
                        logger.LogStandardOutput,
                        logger.LogStandardError,
                        job.ScriptHost.ArgumentsFormat,
                        job.RunCommand);

                if (exitCode != 0)
                {
                    logger.LogError("Job failed due to exit code " + exitCode);
                }
                else
                {
                    UpdateStatus(logger, "Success");
                }
            }
            catch (Exception ex)
            {
                if (ex is ThreadAbortException)
                {
                    // We kill the process when refreshing the job
                    logger.LogInformation("Job aborted");
                    UpdateStatus(logger, "Aborted");
                    return;
                }

                logger.LogError(ex.ToString());
            }
        }