public void Apply(IEnumerable <IShard> shards, IShardOperation operation) { foreach (var shard in GetNextOrderingOfShards(shards)) { var shardOperation = operation.Prepare(shard); shardOperation(); } }
public T Apply <T>(IEnumerable <IShard> shards, IShardOperation <T> operation, IExitStrategy <T> exitStrategy) { foreach (var shard in GetNextOrderingOfShards(shards)) { var shardOperation = operation.Prepare(shard); var result = shardOperation(); if (result != null && exitStrategy.AddResult(result, shard)) { Log.Debug("Short-circuiting operation {0} after execution against shard {1}", operation.OperationName, shard); break; } } return(exitStrategy.CompileResults()); }
private void ExecuteForShard(object state) { var s = (IShard)state; try { Func <T> shardOperation; // Perform thread-safe preparation of the operation for a single shard. lock (this) { // Prevent execution if parallel operation has already been cancelled. if (_isCancelled) { if (--_activeCount <= 0) { Monitor.Pulse(this); } return; } shardOperation = _operation.Prepare(s); } // Perform operation execution on multiple shards in parallel. var result = shardOperation(); // Perform thread-safe aggregation of operation results. lock (this) { // Only add result if operation still has not been cancelled and result is not null. if (!_isCancelled && !Equals(result, null)) { _isCancelled = _exitStrategy.AddResult(result, s); } if (--_activeCount <= 0) { Monitor.Pulse(this); } } } catch (Exception e) { lock (this) { if (!_isCancelled) { _exception = e; _isCancelled = true; } if (--_activeCount <= 0) { Monitor.Pulse(this); } } Log.DebugFormat("Failed parallel operation '{0}' on shard '{1:X}'.", _operation.OperationName, s.ShardIds.First()); } }