private async Task PerformKvsOperation(Func <List <UpgradeServiceNodeState>, bool> operation, TimeSpan timeout, CancellationToken cancellationToken)
        {
            Trace.WriteNoise(TraceType, "PerformKvsOperation: Begin.");
            using (var tx = this.kvsStore.CreateTransaction())
            {
                bool shouldAdd = false;
                List <UpgradeServiceNodeState> upgradeServiceNodeStates = new List <UpgradeServiceNodeState>();

                var item = this.kvsStore.TryGet(tx, StoreKey);
                if (item == null)
                {
                    shouldAdd = true;
                }
                else
                {
                    Trace.WriteNoise(TraceType, "PerformKvsOperation: Invoking JsonSerializationHelper.DeserializeObject<List<UpgradeServiceNodeState>>");
                    upgradeServiceNodeStates = JsonSerializationHelper.DeserializeObject <List <UpgradeServiceNodeState> >(item.Value);
                    Trace.WriteNoise(TraceType, "PerformKvsOperation: Completed JsonSerializationHelper.DeserializeObject<List<UpgradeServiceNodeState>>");
                }

                bool shouldUpdate = operation(upgradeServiceNodeStates);

                if (shouldAdd || shouldUpdate)
                {
                    var serializedState = JsonSerializationHelper.SerializeObject(upgradeServiceNodeStates);

                    if (shouldAdd)
                    {
                        Trace.WriteNoise(TraceType, "PerformKvsOperation: Invoking this.kvsStore.Add");
                        this.kvsStore.Add(tx, StoreKey, serializedState);
                        Trace.WriteNoise(TraceType, "PerformKvsOperation: Completed this.kvsStore.Add");
                    }
                    else
                    {
                        Trace.WriteNoise(TraceType, "PerformKvsOperation: Invoking this.kvsStore.Update");
                        this.kvsStore.Update(tx, StoreKey, serializedState, item.Metadata.SequenceNumber);
                        Trace.WriteNoise(TraceType, "PerformKvsOperation: Completed this.kvsStore.Update");
                    }
                    Trace.WriteNoise(TraceType, "PerformKvsOperation: Invoking tx.CommitAsync");
                    await tx.CommitAsync(timeout);

                    Trace.WriteNoise(TraceType, "PerformKvsOperation: Completed tx.CommitAsync");
                }
            }
            Trace.WriteNoise(TraceType, "PerformKvsOperation: End.");
        }
        internal async Task FilterNodeTypesAsync(IEnumerable <string> primaryNodeTypes, TimeSpan timeout, CancellationToken cancellationToken)
        {
            using (var tx = this.kvsStore.CreateTransaction())
            {
                var item = this.kvsStore.TryGet(tx, StoreKey);
                if (item == null)
                {
                    return;
                }

                var nodeStates = JsonSerializationHelper.DeserializeObject <List <UpgradeServiceNodeState> >(item.Value);
                if (nodeStates == null || !nodeStates.Any())
                {
                    return;
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                var filtered = new List <UpgradeServiceNodeState>();
                foreach (var nodeState in nodeStates)
                {
                    if (primaryNodeTypes.Contains(nodeState.Node.NodeType))
                    {
                        filtered.Add(nodeState);
                    }
                }

                var serializedState = JsonSerializationHelper.SerializeObject(filtered);

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                this.kvsStore.Update(tx, StoreKey, serializedState);

                await tx.CommitAsync(timeout);
            }
        }