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)); }
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); } }
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); }
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)); }
internal static bool?HostHasHeartbeat(IHeartbeatValidityMonitor heartbeatMonitor, FunctionSnapshot snapshot) { return(HostHasHeartbeat(heartbeatMonitor, snapshot.HeartbeatExpirationInSeconds, snapshot.HeartbeatSharedContainerName, snapshot.HeartbeatSharedDirectoryName)); }
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); }