Ejemplo n.º 1
0
        private InterfaceToUpdatesMap GenerateMemberUpdates(IndexUpdateReason updateReason,
                                                            bool onlyUpdateActiveIndexes, out bool updateIndexesEagerly,
                                                            ref bool onlyUniqueIndexesWereUpdated, out int numberOfUniqueIndexesUpdated)
        {
            (string prevIndexName, var prevIndexIsEager) = (null, false);

            var numUniqueIndexes  = 0;      // Local vars due to restrictions on local functions accessing ref/out params
            var onlyUniqueIndexes = true;

            IEnumerable <(string indexName, IMemberUpdate mu)> generateNamedMemberUpdates(Type interfaceType, InterfaceIndexes indexes)
            {
                var befImgs = indexes.BeforeImages.Value;

                foreach ((var indexName, var indexInfo) in indexes.NamedIndexes
                         .Where(kvp => !onlyUpdateActiveIndexes || !kvp.Value.IndexInterface.IsTotalIndex())
                         .Select(kvp => (kvp.Key, kvp.Value)))
                {
                    var mu = updateReason == IndexUpdateReason.OnActivate
                                            ? indexInfo.UpdateGenerator.CreateMemberUpdate(befImgs[indexName])
                                            : indexInfo.UpdateGenerator.CreateMemberUpdate(
                        updateReason == IndexUpdateReason.OnDeactivate ? null : indexes.Properties, befImgs[indexName]);
                    if (mu.OperationType != IndexOperationType.None)
                    {
                        if (prevIndexName != null && prevIndexIsEager != indexInfo.MetaData.IsEager)
                        {
                            throw new InvalidOperationException($"Inconsistent index eagerness specification on grain implementation {this.GetType().Name}," +
                                                                $" interface {interfaceType.Name}, properties {indexes.PropertiesType.FullName}." +
                                                                $" Prior indexes (most recently {prevIndexName}) specified {prevIndexIsEager} while" +
                                                                $" index {indexName} specified {indexInfo.MetaData.IsEager}. This misconfiguration should have been detected on silo startup.");
                        }
                        (prevIndexName, prevIndexIsEager) = (indexName, indexInfo.MetaData.IsEager);

                        if (indexInfo.MetaData.IsUniqueIndex)
                        {
                            // An update is a delete plus insert, so count it as two.
                            numUniqueIndexes += (mu.OperationType == IndexOperationType.Update) ? 2 : 1;
                        }
                        else
                        {
                            onlyUniqueIndexes = false;
                        }
                        yield return(indexName, mu);
                    }
                }
            }

            var interfaceToUpdatesMap = new InterfaceToUpdatesMap(updateReason, this.getWorkflowIdFunc,
                                                                  this._grainIndexes.Select(kvp => (kvp.Key, generateNamedMemberUpdates(kvp.Key, kvp.Value))));

            updateIndexesEagerly         = prevIndexName != null ? prevIndexIsEager : false;
            numberOfUniqueIndexesUpdated = numUniqueIndexes;
            onlyUniqueIndexesWereUpdated = onlyUniqueIndexes;
            return(interfaceToUpdatesMap);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// After some changes were made to the grain, and the grain is in a consistent state, this method is called to update the
        /// indexes defined on this grain type.
        /// </summary>
        /// <remarks>
        /// A call to this method first creates the member updates, and then sends them to ApplyIndexUpdates of the index handler.
        ///
        /// The only reason that this method can receive a negative result from a call to ApplyIndexUpdates is that the list of indexes
        /// might have changed. In this case, it updates the list of member update and tries again. In the case of a positive result
        /// from ApplyIndexUpdates, the list of before-images is replaced by the list of after-images.
        /// </remarks>
        /// <param name="updateReason">Determines whether this method is called upon activation, deactivation, or still-active state of this grain</param>
        /// <param name="onlyUpdateActiveIndexes">whether only active indexes should be updated</param>
        /// <param name="writeStateIfConstraintsAreNotViolated">whether to write back the state to the storage if no constraint is violated</param>
        private protected Task UpdateIndexes(IndexUpdateReason updateReason, bool onlyUpdateActiveIndexes, bool writeStateIfConstraintsAreNotViolated)
        {
            // A flag to determine whether only unique indexes were updated
            var onlyUniqueIndexesWereUpdated = this._hasAnyUniqueIndex;

            // Gather the dictionary of indexes to their corresponding updates, grouped by interface
            var interfaceToUpdatesMap = this.GenerateMemberUpdates(updateReason, onlyUpdateActiveIndexes,
                                                                   out var updateIndexesEagerly, ref onlyUniqueIndexesWereUpdated, out var numberOfUniqueIndexesUpdated);

            // Apply the updates to the indexes defined on this grain
            return(this.ApplyIndexUpdates(interfaceToUpdatesMap, updateIndexesEagerly,
                                          onlyUniqueIndexesWereUpdated, numberOfUniqueIndexesUpdated, writeStateIfConstraintsAreNotViolated));
        }
Ejemplo n.º 3
0
 internal InterfaceToUpdatesMap(IndexUpdateReason updateReason, Func <Guid> getWorkflowIdFunc,
                                IEnumerable <(Type interfaceType, IEnumerable <(string indexName, IMemberUpdate mu)> namedUpdates)> updateEnumerator)