private static bool TryResolveParameters(FunctionSnapshot function, FunctionInstanceSnapshot snapshot, out IEnumerable <FunctionParameterViewModel> resolvedParameters)
        {
            List <FunctionParameterViewModel> parameters = new List <FunctionParameterViewModel>();

            foreach (KeyValuePair <string, ParameterSnapshot> parameter in function.Parameters)
            {
                if (!snapshot.Arguments.ContainsKey(parameter.Key))
                {
                    resolvedParameters = null;
                    return(false);
                }

                FunctionParameterViewModel parameterModel = new FunctionParameterViewModel
                {
                    Name        = parameter.Key,
                    Description = parameter.Value.Prompt,
                    Value       = snapshot.Arguments[parameter.Key].Value
                };

                parameters.Add(parameterModel);
            }

            resolvedParameters = parameters;
            return(true);
        }
        public ActionResult Replay(string parentId, string queue, FormCollection form)
        {
            Guid             parent;
            FunctionSnapshot function = GetFunctionFromInstance(parentId, out parent);

            return(Invoke(queue, form, function, ExecutionReason.Dashboard, parent));
        }
示例#3
0
        public bool UpdateOrCreateIfLatest(FunctionSnapshot snapshot, string currentETag, DateTimeOffset currentVersion)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException("snapshot");
            }

            StoreItem existing = _store.Where(i => i.FunctionSnapshot.Id == snapshot.Id).FirstOrDefault();

            if (existing == null)
            {
                _store.Add(CreateStoreItem(snapshot));
                return(true);
            }
            else if (currentETag == existing.ETag && currentVersion < snapshot.HostVersion)
            {
                Debug.Assert(currentVersion == existing.FunctionSnapshot.HostVersion);
                _store.Remove(existing);
                _store.Add(CreateStoreItem(snapshot));
                return(true);
            }
            else
            {
                // Tell callers when they have the latest version, even if it was already present.
                return(existing.FunctionSnapshot.HostVersion == snapshot.HostVersion);
            }
        }
示例#4
0
        public Guid TriggerAndOverride(string queueName, FunctionSnapshot function,
                                       IDictionary <string, string> arguments, Guid?parentId, ExecutionReason reason)
        {
            if (function == null)
            {
                throw new ArgumentNullException("function");
            }

            Guid id = Guid.NewGuid();

            CallAndOverrideMessage message = new CallAndOverrideMessage
            {
                Id         = id,
                FunctionId = function.HostFunctionId,
                Arguments  = arguments,
                ParentId   = parentId,
                Reason     = reason
            };

            string functionId = new FunctionIdentifier(function.QueueName, function.HostFunctionId).ToString();
            FunctionInstanceSnapshot snapshot = CreateSnapshot(id, arguments, parentId, DateTimeOffset.UtcNow,
                                                               functionId, function.FullName, function.ShortName);

            _logger.LogFunctionQueued(snapshot);
            _sender.Enqueue(queueName, message);

            return(id);
        }
示例#5
0
 private static StoreItem CreateStoreItem(FunctionSnapshot snapshot)
 {
     return(new StoreItem
     {
         FunctionSnapshot = snapshot,
         ETag = Guid.NewGuid().ToString()
     });
 }
        private ActionResult Invoke(string queueName, FormCollection form, FunctionSnapshot function, ExecutionReason reason, Guid?parentId)
        {
            if (function == null)
            {
                return(HttpNotFound());
            }

            IDictionary <string, string> arguments = GetArguments(form);

            Guid id = _invoker.TriggerAndOverride(queueName, function, arguments, parentId, reason);

            return(Redirect("~/#/functions/invocations/" + id));
        }
 private RunFunctionViewModel CreateRunFunctionViewModel(FunctionSnapshot function, IEnumerable <FunctionParameterViewModel> parameters, string submitText, Guid?parentId)
 {
     return(new RunFunctionViewModel
     {
         QueueName = function.QueueName,
         FunctionId = function.Id,
         Parameters = parameters,
         ParentId = parentId,
         FunctionName = function.ShortName,
         FunctionFullName = function.FullName,
         HostIsNotRunning = !FunctionsController.HostHasHeartbeat(_heartbeatMonitor, function).GetValueOrDefault(true),
         SubmitText = submitText
     });
 }
        private static IEnumerable <FunctionParameterViewModel> CreateParameters(FunctionSnapshot function)
        {
            List <FunctionParameterViewModel> parameters = new List <FunctionParameterViewModel>();

            foreach (KeyValuePair <string, ParameterSnapshot> parameter in function.Parameters)
            {
                FunctionParameterViewModel parameterModel = new FunctionParameterViewModel
                {
                    Name        = parameter.Key,
                    Description = parameter.Value.Prompt,
                    Value       = parameter.Value.DefaultValue
                };
                parameters.Add(parameterModel);
            }

            return(parameters);
        }
        public ActionResult Run(string functionId)
        {
            if (functionId == null)
            {
                return(HttpNotFound());
            }

            FunctionSnapshot function = GetFunction(functionId);

            if (function == null)
            {
                return(HttpNotFound());
            }

            var model = CreateRunFunctionViewModel(function, CreateParameters(function), "Run", null);

            return(View(model));
        }
        public ActionResult Replay(string parentId)
        {
            if (parentId == null)
            {
                return(HttpNotFound());
            }

            Guid parent;
            FunctionInstanceSnapshot parentLog;
            FunctionSnapshot         function = GetFunctionFromInstance(parentId, out parent, out parentLog);

            if (function == null)
            {
                return(HttpNotFound());
            }

            IEnumerable <FunctionParameterViewModel> parameters;

            ViewBag.CanReplay = TryResolveParameters(function, parentLog, out parameters);
            var model = CreateRunFunctionViewModel(function, parameters, "Replay", parent);

            return(View(model));
        }
        public ActionResult Run(string queue, string functionId, FormCollection form)
        {
            FunctionSnapshot function = GetFunction(functionId);

            return(Invoke(queue, form, function, ExecutionReason.Dashboard, null));
        }
示例#12
0
 internal static bool?HostHasHeartbeat(IHeartbeatValidityMonitor heartbeatMonitor, FunctionSnapshot snapshot)
 {
     return(HostHasHeartbeat(heartbeatMonitor, snapshot.HeartbeatExpirationInSeconds,
                             snapshot.HeartbeatSharedContainerName, snapshot.HeartbeatSharedDirectoryName));
 }
示例#13
0
        public void ProcessHostStarted(HostStartedMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            string         hostId         = message.SharedQueueName;
            DateTimeOffset hostVersion    = message.EnqueuedOn;
            DateTime       hostVersionUtc = hostVersion.UtcDateTime;
            IEnumerable <FunctionDescriptor> messageFunctions = message.Functions ?? Enumerable.Empty <FunctionDescriptor>();

            HostSnapshot newSnapshot = new HostSnapshot
            {
                HostVersion = hostVersion,
                FunctionIds = CreateFunctionIds(messageFunctions)
            };

            if (_hostIndexManager.UpdateOrCreateIfLatest(hostId, newSnapshot))
            {
                IEnumerable <VersionedMetadata> existingFunctions = _functionIndexManager.List(hostId);

                IEnumerable <VersionedMetadata> removedFunctions = existingFunctions
                                                                   .Where((f) => !newSnapshot.FunctionIds.Any(i => f.Id == i));

                foreach (VersionedMetadata removedFunction in removedFunctions)
                {
                    // Remove all functions no longer in our list (unless they exist with a later host version than
                    // ours).
                    string fullId = new FunctionIdentifier(hostId, removedFunction.Id).ToString();
                    _functionIndexManager.DeleteIfLatest(fullId, hostVersion, removedFunction.ETag,
                                                         removedFunction.Version);
                }

                HeartbeatDescriptor heartbeat = message.Heartbeat;

                IEnumerable <FunctionDescriptor> addedFunctions = messageFunctions
                                                                  .Where((d) => !existingFunctions.Any(f => d.Id == f.Id));

                foreach (FunctionDescriptor addedFunction in addedFunctions)
                {
                    // Create any functions just appearing in our list (or update existing ones if they're earlier than
                    // ours).
                    FunctionSnapshot snapshot = CreateFunctionSnapshot(hostId, heartbeat, addedFunction, hostVersion);
                    _functionIndexManager.CreateOrUpdateIfLatest(snapshot);
                }

                // Update any functions appearing in both lists provided they're still earlier than ours (or create them
                // if they've since been deleted).
                var possiblyUpdatedFunctions = existingFunctions
                                               .Join(messageFunctions, (f) => f.Id, (d) => d.Id, (f, d) => new
                {
                    Descriptor  = d,
                    HostVersion = f.Version,
                    ETag        = f.ETag
                });

                foreach (var possiblyUpdatedFunction in possiblyUpdatedFunctions)
                {
                    FunctionSnapshot snapshot = CreateFunctionSnapshot(hostId, heartbeat,
                                                                       possiblyUpdatedFunction.Descriptor, hostVersion);
                    _functionIndexManager.UpdateOrCreateIfLatest(snapshot, possiblyUpdatedFunction.ETag,
                                                                 possiblyUpdatedFunction.HostVersion);
                }
            }

            // Delete any functions we may have added or updated that are no longer in the index.

            // The create and update calls above may have occured after another instance started processing a later
            // version of this host. If that instance had already read the existing function list before we added the
            // function, it would think the function had already been deleted. In the end, we can't leave a function
            // around unless it's still in the host index after we've added or updated it.

            HostSnapshot finalSnapshot = _hostIndexManager.Read(hostId);
            IEnumerable <FunctionDescriptor> functionsRemovedAfterThisHostVersion;

            if (finalSnapshot == null)
            {
                functionsRemovedAfterThisHostVersion = messageFunctions;
            }
            else if (finalSnapshot.HostVersion.UtcDateTime > hostVersionUtc)
            {
                // Note that we base the list of functions to delete on what's in the HostStartedMessage, not what's in
                // the addedFunctions and possibleUpdatedFunctions variables, as this instance could have been aborted
                // and resumed and could lose state like those local variables.
                functionsRemovedAfterThisHostVersion = messageFunctions.Where(
                    f => !finalSnapshot.FunctionIds.Any((i) => f.Id == i));
            }
            else
            {
                functionsRemovedAfterThisHostVersion = Enumerable.Empty <FunctionDescriptor>();
            }

            foreach (FunctionDescriptor functionNoLongerInSnapshot in functionsRemovedAfterThisHostVersion)
            {
                string fullId = new FunctionIdentifier(hostId, functionNoLongerInSnapshot.Id).ToString();
                _functionIndexManager.DeleteIfLatest(fullId, hostVersionUtc);
            }

            _functionIndexVersionManager.UpdateOrCreateIfLatest(newSnapshot.HostVersion);
        }