public override TryHandleRecordResult Execute( StandardTryHandleRecordOp operation) { operation.MustForArg(nameof(operation)).NotBeNull(); var sqlServerLocator = this.TryGetLocator(operation); var convertedRecordFilter = this.ConvertRecordFilter(operation.RecordFilter, sqlServerLocator); var tagIdsForEntryCsv = this.GetIdsAddIfNecessaryTag( sqlServerLocator, operation.Tags ?? new List <NamedValue <string> >()) .Select(_ => _.ToStringInvariantPreferred()) .ToCsv(); var storedProcOp = StreamSchema.Sprocs.TryHandleRecord.BuildExecuteStoredProcedureOp( this.Name, operation.Concern, operation.Details ?? Invariant($"Created by {nameof(StandardTryHandleRecordOp)}."), convertedRecordFilter, tagIdsForEntryCsv, operation.OrderRecordsBy, operation.MinimumInternalRecordId, operation.InheritRecordTags, operation.StreamRecordItemsToInclude); var sqlProtocol = this.BuildSqlOperationsProtocol(sqlServerLocator); var sprocResult = sqlProtocol.Execute(storedProcOp); int shouldHandle = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.ShouldHandle)].GetValueOfType <int>(); int isBlocked = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.IsBlocked)].GetValueOfType <int>(); if (shouldHandle != 1) { return(new TryHandleRecordResult(null, isBlocked == 1)); } long internalRecordId = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.InternalRecordId)].GetValueOfType <long>(); int serializerRepresentationId = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.SerializerRepresentationId)].GetValueOfType <int>(); int identifierTypeWithVersionId = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.IdentifierTypeWithVersionId)].GetValueOfType <int>(); int objectTypeWithVersionId = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.ObjectTypeWithVersionId)].GetValueOfType <int>(); string stringSerializedId = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.StringSerializedId)].GetValueOfType <string>(); string stringSerializedObject = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.StringSerializedObject)].GetValueOfType <string>(); byte[] binarySerializedObject = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.BinarySerializedObject)].GetValueOfType <byte[]>(); DateTime recordTimestampRaw = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.RecordDateTime)].GetValueOfType <DateTime>(); DateTime?objectTimestampRaw = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.ObjectDateTime)].GetValueOfType <DateTime?>(); string recordTagIdsCsv = sprocResult.OutputParameters[nameof(StreamSchema.Sprocs.TryHandleRecord.OutputParamName.TagIdsCsv)].GetValueOfType <string>(); var identifiedSerializerRepresentation = this.GetSerializerRepresentationFromId(sqlServerLocator, serializerRepresentationId); var identifierType = this.GetTypeById(sqlServerLocator, identifierTypeWithVersionId, true); var objectType = this.GetTypeById(sqlServerLocator, objectTypeWithVersionId, true); var tagIds = recordTagIdsCsv?.FromCsv().Select(_ => long.Parse(_, CultureInfo.InvariantCulture)).ToList(); var tags = tagIds == null ? null : this.GetTagsByIds(sqlServerLocator, tagIds); var recordTimestamp = recordTimestampRaw.ToUtc(); var objectTimestamp = objectTimestampRaw == null ? (DateTime?)null : objectTimestampRaw.ToUtc(); var metadata = new StreamRecordMetadata( stringSerializedId, identifiedSerializerRepresentation.SerializerRepresentation, identifierType, objectType, tags, recordTimestamp, objectTimestamp); DescribedSerializationBase payload; if (operation.StreamRecordItemsToInclude == StreamRecordItemsToInclude.MetadataAndPayload) { switch (identifiedSerializerRepresentation.SerializationFormat) { case SerializationFormat.Binary: payload = new BinaryDescribedSerialization( objectType.WithVersion, identifiedSerializerRepresentation.SerializerRepresentation, binarySerializedObject); break; case SerializationFormat.String: payload = new StringDescribedSerialization( objectType.WithVersion, identifiedSerializerRepresentation.SerializerRepresentation, stringSerializedObject); break; default: throw new NotSupportedException( Invariant($"{nameof(SerializationFormat)} {identifiedSerializerRepresentation.SerializationFormat} is not supported.")); } } else { payload = new NullDescribedSerialization(metadata.TypeRepresentationOfObject.WithVersion, metadata.SerializerRepresentation); } var record = new StreamRecord(internalRecordId, metadata, payload); var result = new TryHandleRecordResult(record); return(result); }
public override EvaluateReactionRegistrationResult Execute( EvaluateReactionRegistrationOp operation) { if (operation.ReactionRegistration.Dependencies.Count != 1) { throw new NotSupportedException(Invariant($"Only 1 single {typeof(RecordFilterReactorDependency)} is supported, {operation.ReactionRegistration.Dependencies.Count} were supplied.")); } var dependency = operation.ReactionRegistration.Dependencies.Single(); var recordFilterDependency = dependency as RecordFilterReactorDependency; if (recordFilterDependency == null) { throw new NotSupportedException(Invariant($"Only {typeof(RecordFilterReactorDependency)} is supported, {dependency?.GetType().ToStringReadable()}.")); } var reactionId = Invariant($"{operation.ReactionRegistration.Id}___{DateTime.UtcNow.ToStringInvariantPreferred()}"); var streamRepToHandledDependencyRecordIdToBeIncludedMap = new Dictionary <IStreamRepresentation, HashSet <long> >(); var handledRecordMementos = new List <RecordSetHandlingMemento>(); var allRequiredSeen = true; foreach (var recordFilterEntry in recordFilterDependency.Entries) { try { var stream = this.streamFactory.Execute(new GetStreamFromRepresentationOp(recordFilterEntry.StreamRepresentation)); stream.MustForOp(nameof(stream)).BeAssignableToType <ISyncReturningProtocol <StandardTryHandleRecordOp, TryHandleRecordResult> >(); var streamProtocol = (ISyncReturningProtocol <StandardTryHandleRecordOp, TryHandleRecordResult>)stream; var tryHandleConcern = EvaluateReactionRegistrationOp.BuildHandlingConcern(operation.ReactionRegistration, recordFilterEntry); var handledIds = new HashSet <long>(); // this is because we could get duplicates... StreamRecord currentRecord = null; do { var tryHandleRecordOp = new StandardTryHandleRecordOp( tryHandleConcern, recordFilterEntry.RecordFilter, streamRecordItemsToInclude: StreamRecordItemsToInclude.MetadataOnly, tags: new[] { new NamedValue <string>(TagNames.PotentialReactionId, reactionId), }); var tryHandleRecordResult = streamProtocol.Execute(tryHandleRecordOp); currentRecord = tryHandleRecordResult?.RecordToHandle; if (currentRecord != null) { handledIds.Add(currentRecord.InternalRecordId); } }while (currentRecord != null); if (handledIds.Any()) { var streamProtocolFactoryForActions = (IStreamRecordHandlingProtocolFactory)stream; var streamHandlingProtocolForActions = streamProtocolFactoryForActions.GetStreamRecordHandlingProtocols(); void CompleteAction() { foreach (var handledInternalRecordId in handledIds) { var completeHandlingOp = new CompleteRunningHandleRecordOp( handledInternalRecordId, tryHandleConcern); streamHandlingProtocolForActions.Execute( completeHandlingOp); } } void CancelAction() { foreach (var handledInternalRecordId in handledIds) { var cancelHandlingOp = new CancelRunningHandleRecordOp( handledInternalRecordId, tryHandleConcern, "Not all required dependencies present."); streamHandlingProtocolForActions.Execute( cancelHandlingOp); } } var actionableSetForTracking = new RecordSetHandlingMemento(CompleteAction, CancelAction); handledRecordMementos.Add(actionableSetForTracking); if (recordFilterEntry.IncludeInReaction) { if (streamRepToHandledDependencyRecordIdToBeIncludedMap.ContainsKey(recordFilterEntry.StreamRepresentation)) { streamRepToHandledDependencyRecordIdToBeIncludedMap[recordFilterEntry.StreamRepresentation].AddRange(handledIds); } else { streamRepToHandledDependencyRecordIdToBeIncludedMap.Add(recordFilterEntry.StreamRepresentation, handledIds); } } } else { if (recordFilterEntry.RequiredForReaction && !operation.OverrideRequired) { allRequiredSeen = false; break; } } } catch (Exception ex) { throw new ReactorException(Invariant($"Failed to process entry: {recordFilterEntry}."), ex, operation); } } EvaluateReactionRegistrationResult result; if (!allRequiredSeen) { foreach (var recordSetHandlingMemento in handledRecordMementos) { recordSetHandlingMemento.CancelSet(); } // no reaction created since not all requirement met. result = new EvaluateReactionRegistrationResult(null, new List <RecordSetHandlingMemento>()); } else if (!handledRecordMementos.Any()) { // no reaction created since there wasn't anything to react to. result = new EvaluateReactionRegistrationResult(null, new List <RecordSetHandlingMemento>()); } else { var streamRepresentationToInternalRecordIdsMap = streamRepToHandledDependencyRecordIdToBeIncludedMap.ToDictionary( k => k.Key, v => (IReadOnlyList <long>)v.Value.ToList()); var reactionTags = (operation.ReactionRegistration.Tags ?? new List <NamedValue <string> >()) .Union( new[] { new NamedValue <string>( TagNames.ReactionRegistrationId, operation.ReactionRegistration.Id), }) .ToList(); var reactionEvent = new ReactionEvent( reactionId, operation.ReactionRegistration.Id, operation.ReactionRegistration.ReactionContext, streamRepresentationToInternalRecordIdsMap, DateTime.UtcNow, reactionTags); result = new EvaluateReactionRegistrationResult(reactionEvent, handledRecordMementos); } return(result); }