public bool UpdateOrCreateIfLatest(string id, HostSnapshot snapshot) { if (snapshot == null) { throw new ArgumentNullException("snapshot"); } if (!_store.ContainsKey(id)) { _store.Add(id, snapshot); return true; } else { HostSnapshot existing = _store[id]; if (snapshot.HostVersion > existing.HostVersion) { _store[id] = snapshot; return true; } else { // Tell callers when they have the latest version, even if it was already present. return snapshot.HostVersion == existing.HostVersion; } } }
public bool UpdateOrCreateIfLatest(string id, HostSnapshot snapshot) { if (snapshot == null) { throw new ArgumentNullException("snapshot"); } return _store.UpdateOrCreateIfLatest(id, snapshot.HostVersion, otherMetadata: null, document: snapshot); }
public bool UpdateOrCreateIfLatest(string id, HostSnapshot snapshot) { if (snapshot == null) { throw new ArgumentNullException("snapshot"); } return(_store.UpdateOrCreateIfLatest(id, snapshot.HostVersion, otherMetadata: null, document: snapshot)); }
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); }
private static IHostIndexManager CreateStubHostIndexManager(HostSnapshot existingSnapshot, bool persistSucceeds) { Mock<IHostIndexManager> mock = new Mock<IHostIndexManager>(MockBehavior.Strict); mock.Setup(m => m.Read(It.IsAny<string>())) .Returns(existingSnapshot); mock.Setup(m => m.UpdateOrCreateIfLatest(It.IsAny<string>(), It.IsAny<HostSnapshot>())) .Returns(persistSucceeds); return mock.Object; }
public bool UpdateOrCreateIfLatest(string id, HostSnapshot snapshot) { return(_store.UpdateOrCreateIfLatest(id, snapshot.HostVersion, otherMetadata: null, document: snapshot)); }