Exemple #1
0
        private static async Task SyncFunctionsTriggers(string requestId, string functionsPath, string tracePath)
        {
            int syncTriggersDelaySeconds = ScmHostingConfigurations.FunctionsSyncTriggersDelaySeconds;

            if (syncTriggersDelaySeconds == 0)
            {
                await AttemptSyncTriggerAndSetTriggers(requestId, functionsPath);

                return;
            }

            if (ScmHostingConfigurations.FunctionsSyncTriggersDelayBackground)
            {
                await NotifyFrontEndOfFunctionsUpdate(requestId);

                Trace(TraceEventType.Verbose, "Scheduling background sync triggers after delay");

                // create background tracer independent of request lifetime if possible
                ITracer bgTracer = null;
                if (!string.IsNullOrEmpty(tracePath))
                {
                    bgTracer = new CascadeTracer(new XmlTracer(tracePath, TraceLevel.Verbose), new ETWTracer(requestId, "POST"));
                }

                // schedule sync triggers call in the background
                _ = ScheduleBackgroundSyncTriggers(syncTriggersDelaySeconds, requestId, functionsPath, bgTracer);
            }
            else
            {
                await NotifyFrontEndOfFunctionsUpdate(requestId);
                await WaitForFunctionsSiteRestart(syncTriggersDelaySeconds);

                await AttemptSyncTriggerAndSetTriggers(requestId, functionsPath);
            }
        }
Exemple #2
0
        public async Task <HttpResponseMessage> InstallExtension(string id, SiteExtensionInfo requestInfo)
        {
            var startTime = DateTime.UtcNow;
            var tracer    = _traceFactory.GetTracer();

            // If there is an id redirect for it, switch to the new id
            if (_packageIdRedirects.TryGetValue(id, out string newId))
            {
                tracer.Trace($"Package id '{id}' was redirected to id '{newId}.");
                id = newId;
            }

            if (IsInstallationLockHeldSafeCheck(id))
            {
                tracer.Trace("{0} is installing with another request, reject current request with Conflict status.", id);
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Conflict, id));
            }

            if (requestInfo == null)
            {
                requestInfo = new SiteExtensionInfo();
            }

            tracer.Trace("Installing {0}, version: {1} from feed: {2}", id, requestInfo.Version, requestInfo.FeedUrl);
            SiteExtensionInfo result = await InitInstallSiteExtension(id, requestInfo.Type);

            if (ArmUtils.IsArmRequest(Request))
            {
                // create a context free tracer
                ITracer backgroundTracer = NullTracer.Instance;
                IDictionary <string, string> traceAttributes = new Dictionary <string, string>();

                if (tracer.TraceLevel > TraceLevel.Off)
                {
                    backgroundTracer = new CascadeTracer(new XmlTracer(_environment.TracePath, tracer.TraceLevel), new ETWTracer(_environment.RequestId, "PUT"));
                    traceAttributes  = new Dictionary <string, string>()
                    {
                        { "url", Request.RequestUri.AbsolutePath },
                        { "method", Request.Method.Method }
                    };

                    foreach (var item in Request.Headers)
                    {
                        if (!traceAttributes.ContainsKey(item.Key))
                        {
                            traceAttributes.Add(item.Key, string.Join(",", item.Value));
                        }
                    }
                }

                AutoResetEvent installationSignal = new AutoResetEvent(false);

                // trigger installation, but do not wait. Expecting poll for status
                ThreadPool.QueueUserWorkItem((object stateInfo) =>
                {
                    using (backgroundTracer.Step(XmlTracer.BackgroundTrace, attributes: traceAttributes))
                    {
                        try
                        {
                            using (backgroundTracer.Step("Background thread started for {0} installation", id))
                            {
                                _manager.InstallExtension(id, requestInfo.Version, requestInfo.FeedUrl, requestInfo.Type, backgroundTracer, requestInfo.InstallationArgs).Wait();
                            }
                        }
                        finally
                        {
                            installationSignal.Set();

                            // will be a few millionseconds off if task finshed within 15 seconds.
                            LogEndEvent(id, (DateTime.UtcNow - startTime), backgroundTracer);
                        }
                    }
                });

                SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, id, tracer);
                if (installationSignal.WaitOne(TimeSpan.FromSeconds(15)))
                {
                    if (!armSettings.IsRestartRequired(_siteExtensionRoot))
                    {
                        // only skip polling if current installation doesn`t require restart, to avoid making race condition common
                        // TODO: re-visit if we want to skip polling for case that need to restart
                        tracer.Trace("Installation finish quick and not require restart, skip async polling, invoking GET to return actual status to caller.");
                        return(await GetLocalExtension(id));
                    }
                }

                // do not log end event here, since it is not done yet
                return(Request.CreateResponse(HttpStatusCode.Created, ArmUtils.AddEnvelopeOnArmRequest <SiteExtensionInfo>(result, Request)));
            }
            else
            {
                result = await _manager.InstallExtension(id, requestInfo.Version, requestInfo.FeedUrl, requestInfo.Type, tracer, requestInfo.InstallationArgs);

                if (string.Equals(Constants.SiteExtensionProvisioningStateFailed, result.ProvisioningState, StringComparison.OrdinalIgnoreCase))
                {
                    SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, id, tracer);
                    throw new HttpResponseException(Request.CreateErrorResponse(armSettings.Status, result.Comment));
                }

                var response = Request.CreateResponse(HttpStatusCode.OK, result);
                LogEndEvent(id, (DateTime.UtcNow - startTime), tracer);
                return(response);
            }
        }