public UniqueProperty(ISagaEntity saga, string name, object value) { _type = saga.GetType(); Name = name; Value = value; SagaId = saga.Id; }
void ISagaPersister.Save(ISagaEntity saga) { lock (syncRoot) { data[saga.Id] = saga; } }
public void Update(ISagaEntity saga) { var p = UniqueAttribute.GetUniqueProperty(saga); if (!p.HasValue) { return; } var uniqueProperty = p.Value; var metadata = Session.Advanced.GetMetadataFor(saga); //if the user just added the unique property to a saga with existing data we need to set it if (!metadata.ContainsKey(UniqueValueMetadataKey)) { StoreUniqueProperty(saga); return; } var storedvalue = metadata[UniqueValueMetadataKey].ToString(); var currentValue = uniqueProperty.Value.ToString(); if (currentValue == storedvalue) { return; } DeleteUniqueProperty(saga, new KeyValuePair <string, object>(uniqueProperty.Key, storedvalue)); StoreUniqueProperty(saga); }
private void ValidateUniqueProperties(ISagaEntity saga) { var uniqueProperties = UniqueAttribute.GetUniqueProperties(saga.GetType()); if (!uniqueProperties.Any()) { return; } var sagasFromSameType = from s in data where ((s.Value as ISagaEntity).GetType() == saga.GetType() && (s.Key != saga.Id)) select s.Value; foreach (var storedSaga in sagasFromSameType) { foreach (var uniqueProperty in uniqueProperties) { if (uniqueProperty.CanRead) { var inComingSagaPropertyValue = uniqueProperty.GetValue(saga, null); var storedSagaPropertyValue = uniqueProperty.GetValue(storedSaga, null); if (inComingSagaPropertyValue.Equals(storedSagaPropertyValue)) { throw new InvalidOperationException( string.Format("Cannot store a saga. The saga with id '{0}' already has property '{1}' with value '{2}'.", storedSaga.Id, uniqueProperty.ToString(), storedSagaPropertyValue)); } } } } }
public void Complete(ISagaEntity saga) { var ctx = _sessionFactory.GetSession(); ctx.DeleteObject(saga as T); ctx.SaveChanges(); }
public void Update(ISagaEntity saga) { long currentVersion = GetSagaVersion(saga); var sagaKey = GetSagaKey(saga); var sagaVersionKey = GetSagaVersionKey(saga); using (var client = GetClient()) { var versionString = client.Get <string>(sagaVersionKey); if (versionString != null) { long storageVersion = long.Parse(versionString); if (storageVersion != currentVersion) { throw new ConcurrencyException("The saga " + saga.Id + " has changed since it was last loaded"); } } else { throw new ConcurrencyException("The saga " + saga.Id + " has been deleted since it was last loaded"); } } Save(saga); }
public void Save(ISagaEntity saga) { var ctx = _sessionFactory.GetSession(); ctx.AddObject(typeof(T).Name, saga as T); ctx.SaveChanges(); }
public void Complete(ISagaEntity saga) { using (var session = Store.OpenSession()) { session.Delete(saga); } }
void ISagaPersister.Complete(ISagaEntity saga) { lock (syncRoot) { data.Remove(saga.Id); } }
public void Save(Guid sagaId, ISagaEntity saga) { _data[sagaId] = new ProfileSagaEntity { SagaEntity = BlobSerializer.Serialize(saga), ProfileName = _pluginContext.ProfileName }; }
protected string GetSagaKey(ISagaEntity saga) { if (saga == null) { throw new ArgumentNullException("saga"); } return(KeyPrefix + "saga:" + saga.GetType().FullName + ":" + saga.Id.ToString("N")); }
/// <summary> /// Gets a single property that is marked with the UniqueAttribute for a saga entity /// </summary> /// <param name="entity">A saga entity</param> /// <returns>A PropertyInfo of the property marked with a UniqAttribute or null if not used</returns> public static KeyValuePair <string, object>?GetUniqueProperty(ISagaEntity entity) { var prop = GetUniqueProperty(entity.GetType()); return(prop != null ? new KeyValuePair <string, object>(prop.Name, prop.GetValue(entity, null)) : (KeyValuePair <string, object>?)null); }
public void SetUp() { _sagaEntityA = new SagaEntityA { Id = Guid.NewGuid(), SomeIdentifier = IDENTIFIER }; SagaPersister.Save(_sagaEntityA); SagaPersister.DocumentSessionFactory.Current.SaveChanges(); }
public void Complete(ISagaEntity saga) { using (var session = OpenSession()) { session.Advanced.DatabaseCommands.Delete(Store.Conventions.FindTypeTagName(saga.GetType()) + "/" + saga.Id, null); session.SaveChanges(); } }
private string GetXmlForSaga(ISagaEntity saga) { var serializer = new XmlSerializer(saga.GetType()); var stringWriter = new StringWriter(); serializer.Serialize(stringWriter, saga); return(stringWriter.ToString()); }
public void Save(ISagaEntity saga) { using (var session = Store.OpenSession()) { session.Store(saga); session.SaveChanges(); } }
/// <summary> /// Gets a single property that is marked with the UniqueAttribute for a saga entity /// </summary> /// <param name="entity">A saga entity</param> /// <returns>A PropertyInfo of the property marked with a UniqAttribute or null if not used</returns> public static KeyValuePair<string, object>? GetUniqueProperty(ISagaEntity entity) { var prop = GetUniqueProperty(entity.GetType()); return prop != null ? new KeyValuePair<string, object>(prop.Name, prop.GetValue(entity, null)) : (KeyValuePair<string, object>?) null; }
void ISagaPersister.Save(ISagaEntity saga) { lock (syncRoot) { ValidateUniqueProperties(saga); data[saga.Id] = saga; } }
public void Save(ISagaEntity saga) { Action saveSagaAction = () => { var stringId = saga.Id.ToString("N"); var sagaKey = GetSagaKey(saga); var sagaPropertyMapKey = GetSagaPropertyMapKey(saga); var sagaVersionKey = GetSagaVersionKey(saga); var uniqueProperties = UniqueAttribute.GetUniqueProperties(saga); using (var client = GetClient()) { using (var rlock = client.AcquireLock(stringId, TimeSpan.FromSeconds(30))) { long version = client.Increment(sagaVersionKey, 1); SetSagaVersion(saga, version); var sagaString = Serialize(saga); //Check that unique properties don't already exist for a different saga foreach (var prop in uniqueProperties) { var propertyKey = GetPropertyKey(saga.GetType(), prop.Key, prop.Value); var sagaId = client.Get <string>(propertyKey); if (sagaId != null) { if (saga.Id != Guid.Parse(sagaId)) { throw new UniquePropertyException("Unique property " + prop.Key + " already exists with value " + prop.Value); } } } using (var tran = client.CreateTransaction()) { tran.QueueCommand(c => c.Set(sagaKey, sagaString)); foreach (var prop in uniqueProperties) { var propertyKey = GetPropertyKey(saga.GetType(), prop.Key, prop.Value); tran.QueueCommand(c => c.Lists[sagaPropertyMapKey].Add(propertyKey)); //Link from saga ID to property key tran.QueueCommand(c => client.Set(propertyKey, stringId)); //Link from property key to saga } tran.Commit(); } } } }; if (Transaction.Current != null) { Transaction.Current.EnlistVolatile(new ActionResourceManager(saveSagaAction, null), EnlistmentOptions.None); } else { saveSagaAction(); } }
private void StoreUniqueProperty(ISagaEntity saga) { var uniqueProperty = GetUniqueProperty(saga); if (uniqueProperty != null) { DocumentSessionFactory.Current.Store(uniqueProperty); } }
private static UniqueProperty GetUniqueProperty(ISagaEntity saga) { return((from propertyInfo in saga.GetType().GetProperties() let customAttributes = propertyInfo.GetCustomAttributes(typeof(UniqueAttribute), false) where customAttributes.Length > 0 where propertyInfo.CanRead select new UniqueProperty(saga, propertyInfo.Name, propertyInfo.GetValue(saga, null)) ).FirstOrDefault()); }
public void SetUp() { _sagaEntityA = new SagaEntityA { Id = Guid.NewGuid(), SomeIdentifier = IDENTIFIER }; _sagaEntityB = new SagaEntityB { Id = Guid.NewGuid(), SomeIdentifier = IDENTIFIER }; SagaPersister.Save(_sagaEntityA); SagaPersister.Save(_sagaEntityB); SagaPersister.DocumentSessionFactory.Current.SaveChanges(); }
public void Complete(ISagaEntity saga) { var sagaData = Context.SagaData.FirstOrDefault(s => s.Id == saga.Id); if (sagaData == null) { return; } Context.SagaData.Remove(sagaData); }
protected void SetSagaVersion(ISagaEntity saga, long version) { var versionProp = saga.GetType().GetProperties().FirstOrDefault(o => o.Name == "Version"); if (versionProp == null) { throw new MissingMemberException("'Version' property must be defined"); } versionProp.SetValue(saga, version, null); }
protected long GetSagaVersion(ISagaEntity saga) { //TODO: Use an attribute instead of fixed property name? var versionProp = saga.GetType().GetProperties().FirstOrDefault(o => o.Name == "Version"); if (versionProp == null) { throw new MissingMemberException("'Version' property must be defined on saga data"); } return(Convert.ToInt64(versionProp.GetValue(saga, null))); }
public void Update(ISagaEntity saga) { var sagaData = Context.SagaData.FirstOrDefault(s => s.Id == saga.Id); if (sagaData == null) { return; } sagaData.Data = GetXmlForSaga(saga); sagaData.Version++; UpdateUniquePropertyForSaga(saga, sagaData); }
public void Complete(ISagaEntity saga) { Session.Delete(saga); var uniqueProperty = UniqueAttribute.GetUniqueProperty(saga); if (!uniqueProperty.HasValue) { return; } DeleteUniqueProperty(saga, uniqueProperty.Value); }
public void Save(ISagaEntity saga) { var sagaData = new SagaData { Id = saga.Id, Data = GetXmlForSaga(saga), Version = 1 }; UpdateUniquePropertyForSaga(saga, sagaData); Context.SagaData.Add(sagaData); }
void StoreUniqueProperty(ISagaEntity saga) { var uniqueProperty = UniqueAttribute.GetUniqueProperty(saga); if (!uniqueProperty.HasValue) { return; } var id = SagaUniqueIdentity.FormatId(saga.GetType(), uniqueProperty.Value); Session.Store(new SagaUniqueIdentity { Id = id, SagaId = saga.Id, UniqueValue = uniqueProperty.Value.Value }); SetUniqueValueMetadata(saga, uniqueProperty.Value); }
private void DeleteUniquePropertyEntityIfExists(ISagaEntity saga) { var session = DocumentSessionFactory.Current; var uniqueProperty = GetUniqueProperty(saga); if (uniqueProperty == null) { return; } var persistedUniqueProperty = session.Query <UniqueProperty>() .Customize(x => x.WaitForNonStaleResults()) .Where(p => p.SagaId == saga.Id) .SingleOrDefault(); if (persistedUniqueProperty != null) { session.Delete(persistedUniqueProperty); } }
void StoreUniqueProperty(ISagaEntity saga) { var uniqueProperty = UniqueAttribute.GetUniqueProperty(saga); if (!uniqueProperty.HasValue) { return; } var id = SagaUniqueIdentity.FormatId(saga.GetType(), uniqueProperty.Value); var sagaDocId = sessionFactory.Store.Conventions.FindFullDocumentKeyFromNonStringIdentifier(saga.Id, saga.GetType(), false); Session.Store(new SagaUniqueIdentity { Id = id, SagaId = saga.Id, UniqueValue = uniqueProperty.Value.Value, SagaDocId = sagaDocId }); SetUniqueValueMetadata(saga, uniqueProperty.Value); }
protected void DeleteSaga(ISagaEntity saga) { var stringId = saga.Id.ToString("N"); var sagaKey = GetSagaKey(saga); var sagaPropertyMapKey = GetSagaPropertyMapKey(saga); var sagaVersionKey = GetSagaVersionKey(saga); Action deleteSagaAction = () => { using (var client = GetClient()) { var propertyKeys = client.Lists[sagaPropertyMapKey].GetAll(); using (var tran = client.CreateTransaction()) { if (propertyKeys != null) { tran.QueueCommand(c => c.RemoveAll(propertyKeys.ToArray())); } tran.QueueCommand(c => c.Remove(sagaKey)); tran.QueueCommand(c => c.Remove(sagaPropertyMapKey)); tran.QueueCommand(c => c.Remove(sagaVersionKey)); tran.Commit(); } } }; if (Transaction.Current != null) { Transaction.Current.EnlistVolatile(new ActionResourceManager(deleteSagaAction, null), EnlistmentOptions.None); } else { deleteSagaAction(); } }
/// <summary> /// Indicate a timeout at the expiration time for the given saga maintaining the given state. /// </summary> /// <param name="expiration"></param> /// <param name="saga"></param> /// <param name="state"></param> public TimeoutMessage(DateTime expiration, ISagaEntity saga, object state) { expires = DateTime.SpecifyKind(expiration, DateTimeKind.Utc); SagaId = saga.Id; State = state; }
/// <summary> /// Indicate a timeout within the given time for the given saga maintaing the given state. /// </summary> /// <param name="expireIn"></param> /// <param name="saga"></param> /// <param name="state"></param> public TimeoutMessage(TimeSpan expireIn, ISagaEntity saga, object state) : this(DateTime.Now + expireIn, saga, state) { }
/// <summary> /// Signal to the timeout manager that all other <see cref="TimeoutMessage"/> /// objects can be cleared for the given <see cref="Saga"/>. /// </summary> /// <param name="saga"></param> /// <param name="clear"></param> public TimeoutMessage(ISagaEntity saga, bool clear) { SagaId = saga.Id; ClearTimeout = clear; }
/// <summary> /// Gets all the properties that are marked with the UniqueAttribute for a saga entity /// </summary> /// <param name="entity">A saga entity</param> /// <returns>A dictionary of property names and their values</returns> public static IDictionary<string, object> GetUniqueProperties(ISagaEntity entity) { return GetUniqueProperties(entity.GetType()).ToDictionary(p => p.Name, p => p.GetValue(entity, null)); }