コード例 #1
0
        public async Task <IEnumerable <IEventContext> > GetEventsWithContext(int StartingSequenceNumber = 0, DateTime?effectiveDateTime = null)
        {
            if (null != EventStreamBlob)
            {
                if (await EventStreamBlob.ExistsAsync())
                {
                    using (System.IO.Stream rawStream = await GetUnderlyingStream())
                    {
                        if (!(rawStream.Position >= rawStream.Length))
                        {
                            List <IEventContext> ret = new List <IEventContext>();
                            foreach (BlobBlockJsonWrappedEvent record in BlobBlockJsonWrappedEvent.FromBinaryStream(rawStream))
                            {
                                if (null != record)
                                {
                                    if (record.SequenceNumber >= StartingSequenceNumber)
                                    {
                                        if ((!effectiveDateTime.HasValue) || (record.WriteTime <= effectiveDateTime.Value))
                                        {
                                            ret.Add(record);
                                        }
                                    }
                                }
                            }

                            return(ret);
                        }
                    }
                }
            }

            return(Enumerable.Empty <IEventContext>());
        }
        /// <summary>
        /// Create a wrapper for this JSON event
        /// </summary>
        /// <param name="eventTypeName">
        /// The type of event in this wrapper
        /// </param>
        /// <param name="sequenceNumber">
        /// The ordinal sequence of the event in the event stream
        /// </param>
        /// <param name="VersionNumber">
        /// The version number of the event schema
        /// </param>
        /// <param name="writeTime">
        /// The date/time the event was written to the event stream
        /// </param>
        /// <param name="eventInstance">
        /// Th eunderlying data for this event instance
        /// </param>
        /// <param name="context">
        /// Extra context information to be written in with the event
        /// </param>
        public static BlobBlockJsonWrappedEvent Create(string eventTypeName,
                                                       int sequenceNumber,
                                                       int versionNumber,
                                                       DateTime?writeTime,
                                                       IEvent eventInstance,
                                                       IWriteContext context)
        {
            if (string.IsNullOrWhiteSpace(eventTypeName))
            {
                if (null != eventInstance)
                {
                    // Use the type name if no explicit name is passed in
                    eventTypeName = eventInstance.GetType().FullName;
                }
                else
                {
                    // Mark this as being just a place holder - used when we need to copy an event stream but "wipe out" some events
                    eventTypeName = "Placeholder event";
                }
            }

            if (!writeTime.HasValue)
            {
                writeTime = DateTime.UtcNow;
            }

            BlobBlockJsonWrappedEvent ret = new BlobBlockJsonWrappedEvent()
            {
                EventTypeName  = eventTypeName,
                SequenceNumber = sequenceNumber,
                VersionNumber  = versionNumber
            };

            ret.WriteTime = writeTime.Value;

            if (null != eventInstance)
            {
                ret.EventInstanceAsJson = JObject.FromObject(eventInstance);
            }

            if (null != context)
            {
                ret.CorrelationIdentifier = context.CorrelationIdentifier;
                ret.Commentary            = context.Commentary;
            }

            return(ret);
        }
        /// <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);
            }
        }