コード例 #1
0
        /// <summary>
        /// Append an event onto the event stream
        /// </summary>
        /// <param name="eventToAppend">
        /// The event we want to write to the event stream
        /// </param>
        /// <param name="expectedTopSequence">
        /// The sequence number we expect to be the last in the event stream - if events have been added since this then a
        /// concurrency error is thrown
        /// </param>
        public async Task AppendEvent(object eventToAppend,
                                      int?expectedTopSequence = null,
                                      EventStreamExistenceConstraint streamConstraint = EventStreamExistenceConstraint.Loose)
        {
            if (null != _writer)
            {
                // make an event instance of this event and append it to the event stream
                IAppendResult result = await _writer.AppendEvent(EventInstance.Wrap(eventToAppend),
                                                                 expectedTopSequence.GetValueOrDefault(0),
                                                                 streamConstraint : streamConstraint);

                if (null != result)
                {
                    if (null != this._notificationDispatcher)
                    {
                        if (result.NewEventStreamCreated)
                        {
                            await _notificationDispatcher.NewEntityCreated(this,
                                                                           commentary : _context?.Commentary,
                                                                           context : _context);
                        }
                        await _notificationDispatcher.NewEventAppended(this,
                                                                       EventNameAttribute.GetEventName(eventToAppend.GetType()),
                                                                       result.SequenceNumber,
                                                                       commentary : _context?.Commentary,
                                                                       eventPayload : eventToAppend,
                                                                       context : _context);
                    }
                }
            }
        }
コード例 #2
0
        public async Task <IAppendResult> AppendEvent(IEvent eventInstance,
                                                      int expectedTopSequenceNumber = 0,
                                                      int eventVersionNumber        = 1,
                                                      EventStreamExistenceConstraint streamConstraint = EventStreamExistenceConstraint.Loose)
        {
            int nextSequence = 0;

            // check stream constraints
            if (streamConstraint != EventStreamExistenceConstraint.Loose)
            {
                // find out if the stream exists
                bool exists = StreamAlreadyExists();
                if (streamConstraint == EventStreamExistenceConstraint.MustExist)
                {
                    if (!exists)
                    {
                        throw new EventStreamWriteException(this,
                                                            0,
                                                            message: $"Stream is constrained to MustExist but has not been created",
                                                            source: "Table Event Stream Writer");
                    }
                }
                if (streamConstraint == EventStreamExistenceConstraint.MustBeNew)
                {
                    if (exists)
                    {
                        throw new EventStreamWriteException(this,
                                                            0,
                                                            message: $"Stream is constrained to be new but has already been created",
                                                            source: "Table Event Stream Writer");
                    }
                }
            }

            // Read and update the [RECORDID_SEQUENCE] row in a transaction..
            nextSequence = await IncrementSequenceNumber();

            if (expectedTopSequenceNumber > 0)
            {
                if ((1 + expectedTopSequenceNumber) < nextSequence)
                {
                    //Concurrency error has occured
                    throw new EventStreamWriteException(this,
                                                        (nextSequence - 1),
                                                        message: $"Out of sequence write - expected seqeunce number {expectedTopSequenceNumber}, actual {nextSequence - 1}",
                                                        source: "Table Event Stream Writer");
                }
            }


            var dteEvent = MakeDynamicTableEntity(eventInstance, nextSequence);

            if (null != dteEvent)
            {
                await base.Table.ExecuteAsync(TableOperation.Insert(dteEvent));
            }


            return(new AppendResult((nextSequence == 1), nextSequence));
        }
        /// <summary>
        /// Append the event to the end of the event stream
        /// </summary>
        /// <param name="eventInstance">
        /// The event to append to the end of the event stream
        /// </param>
        /// <param name="expectedTopSequenceNumber">
        /// if this is set to > 0 and the event stream is further on then a consistency issue has arisen and the
        /// event should not be written but rather throw an error
        /// </param>
        /// <param name="eventVersionNumber">
        /// The version number to add to the event wrapper
        /// </param>
        /// <param name="streamConstraint">
        /// An additional constrain that must be satisfied by the event stream in order to persist the event
        /// </param>
        /// <returns></returns>
        public async Task <IAppendResult> AppendEvent(IEvent eventInstance,
                                                      int expectedTopSequenceNumber = 0,
                                                      int eventVersionNumber        = 1,
                                                      EventStreamExistenceConstraint streamConstraint = EventStreamExistenceConstraint.Loose)
        {
            if (base.EventStreamBlob != null)
            {
                // acquire a lease for the blob..
                string writeStreamLeaseId = null;
                if (await Exists())
                {
                    writeStreamLeaseId = await base.EventStreamBlob.AcquireLeaseAsync(TimeSpan.FromSeconds(15));
                }

                int nextSequence = await base.GetSequenceNumber() + 1;

                if (expectedTopSequenceNumber > 0)
                {
                    // check against actual top sequence number
                    if ((expectedTopSequenceNumber + 1) < nextSequence)
                    {
                        throw new EventStreamWriteException(this,
                                                            (nextSequence - 1),
                                                            message: $"Out of sequence write - expected seqeunce number {expectedTopSequenceNumber }",
                                                            source: "Blob Event Stream Writer");
                    }
                }

                string eventName = "";
                if (null != eventInstance)
                {
                    eventName = EventNameAttribute.GetEventName(eventInstance.GetType());
                }

                // create an access condition
                AccessCondition condition = AccessCondition.GenerateEmptyCondition();
                if (streamConstraint == EventStreamExistenceConstraint.MustBeNew)
                {
                    condition = AccessCondition.GenerateIfNotExistsCondition();
                }
                if (streamConstraint == EventStreamExistenceConstraint.MustExist)
                {
                    condition = AccessCondition.GenerateIfExistsCondition();
                }
                if (!string.IsNullOrWhiteSpace(writeStreamLeaseId))
                {
                    condition.LeaseId = writeStreamLeaseId;
                }

                // default the writer context if it is not already set
                if (null == _writerContext)
                {
                    _writerContext = WriteContext.DefaultWriterContext();
                }

                BlobBlockJsonWrappedEvent evtToWrite = BlobBlockJsonWrappedEvent.Create(eventName,
                                                                                        nextSequence,
                                                                                        eventVersionNumber,
                                                                                        null,
                                                                                        eventInstance,
                                                                                        _writerContext);

                try
                {
                    // Create it if it doesn't exist and initialsie the metadata
                    await base.Refresh();


                    Microsoft.Azure.Storage.OperationContext context = new Microsoft.Azure.Storage.OperationContext()
                    {
                    };

                    await EventStreamBlob.AppendBlockAsync(new System.IO.MemoryStream(Encoding.UTF8.GetBytes(evtToWrite.ToJSonText())),
                                                           "",
                                                           condition,
                                                           null, // use the default blob request options
                                                           context
                                                           );
                }
                catch (Microsoft.Azure.Storage.StorageException exBlob)
                {
                    throw new EventStreamWriteException(this,
                                                        (nextSequence - 1),
                                                        message: "Failed to save an event to the event stream",
                                                        source: "Blob Event Stream Writer",
                                                        innerException: exBlob);
                }

                await IncrementSequence(writeStreamLeaseId);

                if (!string.IsNullOrWhiteSpace(writeStreamLeaseId))
                {
                    // and release the lease
                    await base.EventStreamBlob.ReleaseLeaseAsync(condition);
                }

                int sequence = await base.GetSequenceNumber();

                return(new AppendResult((sequence == 0), sequence));
            }
            else
            {
                return(null);
            }
        }