protected override OperationBase DeepCloneInternal()
        {
            var result = new WriteEventOnMatchingRecordFilterOp <TId>(
                this.CheckRecordExistsOps?.DeepClone(),
                this.EventToPutOnMatchChainOfResponsibility?.DeepClone(),
                this.WaitTimeBeforeRetry.DeepClone());

            return(result);
        }
        public WriteEventOnMatchingRecordFilterOp <TId> DeepCloneWithWaitTimeBeforeRetry(TimeSpan waitTimeBeforeRetry)
        {
            var result = new WriteEventOnMatchingRecordFilterOp <TId>(
                this.CheckRecordExistsOps?.DeepClone(),
                this.EventToPutOnMatchChainOfResponsibility?.DeepClone(),
                waitTimeBeforeRetry);

            return(result);
        }
        public WriteEventOnMatchingRecordFilterOp <TId> DeepCloneWithEventToPutOnMatchChainOfResponsibility(IReadOnlyList <EventToPutWithIdOnRecordFilterMatch <TId> > eventToPutOnMatchChainOfResponsibility)
        {
            var result = new WriteEventOnMatchingRecordFilterOp <TId>(
                this.CheckRecordExistsOps?.DeepClone(),
                eventToPutOnMatchChainOfResponsibility,
                this.WaitTimeBeforeRetry.DeepClone());

            return(result);
        }
        public WriteEventOnMatchingRecordFilterOp <TId> DeepCloneWithCheckRecordExistsOps(IReadOnlyCollection <CheckRecordExistsOp> checkRecordExistsOps)
        {
            var result = new WriteEventOnMatchingRecordFilterOp <TId>(
                checkRecordExistsOps,
                this.EventToPutOnMatchChainOfResponsibility?.DeepClone(),
                this.WaitTimeBeforeRetry.DeepClone());

            return(result);
        }
        /// <inheritdoc />
        public bool Equals(WriteEventOnMatchingRecordFilterOp <TId> other)
        {
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            if (ReferenceEquals(other, null))
            {
                return(false);
            }

            var result = this.CheckRecordExistsOps.IsEqualTo(other.CheckRecordExistsOps) &&
                         this.EventToPutOnMatchChainOfResponsibility.IsEqualTo(other.EventToPutOnMatchChainOfResponsibility) &&
                         this.WaitTimeBeforeRetry.IsEqualTo(other.WaitTimeBeforeRetry);

            return(result);
        }
        public override void Execute(
            WriteEventOnMatchingRecordFilterOp <TId> operation)
        {
            operation.MustForArg(nameof(operation)).NotBeNull();

            var results = new Dictionary <CheckRecordExistsOp, CheckRecordExistsResult>();

            foreach (var checkRecordExistsOp in operation.CheckRecordExistsOps)
            {
                var result = this.checkRecordExistsProtocol.Execute(checkRecordExistsOp);
                results.Add(checkRecordExistsOp, result);
            }

            if (results.Any())
            {
                var recordExistsSet = results.Select(_ => _.Value.RecordExists).ToList();

                foreach (var eventToPutWithIdOnMatch in operation.EventToPutOnMatchChainOfResponsibility)
                {
                    var matches =
                        recordExistsSet.MatchesAccordingToStrategy(
                            eventToPutWithIdOnMatch.RecordExistsMatchStrategy);

                    if (matches)
                    {
                        var eventToPutWithId = eventToPutWithIdOnMatch.EventToPut;
                        var targetStream     = this.streamFactory.Execute(new GetStreamFromRepresentationOp(eventToPutWithId.StreamRepresentation));
                        targetStream.MustForOp("targetStreamMustBeIWriteOnlyStream").BeAssignableToType <IWriteOnlyStream>();

                        IEvent eventToPut;
                        if (eventToPutWithId.UpdateTimestampOnPut)
                        {
                            var eventBase = eventToPutWithId.EventToPut as EventBase;
                            eventBase
                            .MustForOp(Invariant($"{nameof(eventToPutWithId)}.{nameof(eventToPutWithId.EventToPut)}"))
                            .NotBeNull(
                                Invariant(
                                    $"Only {nameof(EventBase)} is supported, this was {eventToPutWithId.EventToPut.GetType().ToStringReadable()}."));

                            // ReSharper disable once PossibleNullReferenceException - checked with Must above
                            eventToPut = eventBase.DeepCloneWithTimestampUtc(DateTime.UtcNow);
                        }
                        else
                        {
                            eventToPut = eventToPutWithId.EventToPut;
                        }

                        ((IWriteOnlyStream)targetStream).PutWithId(eventToPutWithId.Id, eventToPut, eventToPutWithId.Tags);

                        switch (eventToPutWithIdOnMatch.ChainOfResponsibilityLinkMatchStrategy)
                        {
                        case ChainOfResponsibilityLinkMatchStrategy.MatchHaltsEvaluationOfChainAndCompletes:
                            return;

                        case ChainOfResponsibilityLinkMatchStrategy.MatchHaltsEvaluationOfChainAndSelfCancels:
                            Thread.Sleep(operation.WaitTimeBeforeRetry);
                            throw new SelfCancelRunningExecutionException("Matched status and wrote record, terminating chain but not terminating execution.");

                        case ChainOfResponsibilityLinkMatchStrategy.Continue:
                            // Keep going through links...
                            break;

                        default:
                            throw new NotSupportedException(Invariant($"Unsupported {nameof(ChainOfResponsibilityLinkMatchStrategy)}: {eventToPutWithIdOnMatch.ChainOfResponsibilityLinkMatchStrategy}."));
                        }
                    }
                }

                Thread.Sleep(operation.WaitTimeBeforeRetry);
                throw new SelfCancelRunningExecutionException("No matches found or the matches did not terminate the chain or execution.");
            }
            else
            {
                Thread.Sleep(operation.WaitTimeBeforeRetry);
                throw new SelfCancelRunningExecutionException("No records found to test.");
            }
        }