I only have a single starting message type so I guess I don't have to upgrade immediately?
On the other hand, even with a single starting message type I still think there can be a concurrency problem:
In our IoT solution the user can configure rules that inform him by email of certain status changes on the monitored devices. He can also configure the rules to get reminder emails while the device remains in that state. I use saga's to orchestrate the rules. Separate saga instances are started per device/rule combination. There can be multiple triggers for the same rule (e.g. send email when temperature1 > 50 OR temperature2 > 45. For the same device, both temperatures can reach their theshold at the same time (concurrently). As I have my endpoint concurrency = 5, I think the same saga instance could be started concurrently resulting in 2 saga instances.
Or am I safe because I have a rowversion field in my saga data? (see code below).
Please comment.
// Note about NHibernate concurrency settings
//
// - NHibernate will use the Version field attributed with [RowVersion] for optimistic concurrency checking
// - By default, starting from version 4.1.0 of the NHibernate saga persister, an additional pessimistic concurrency control was added.
// This however locks the saga status row till the end of the transaction. To disable this pessimistic concurrency control we added
// [LockMode(LockModes.Read)], resulting in a pure optimistic concurrency strategy (with retries).
//
[LockMode(LockModes.Read)]
public class RuleActionManagerStatus : IContainSagaData
{
#region IContainSagaData implementation
public virtual Guid Id { get; set; }
public virtual string OriginalMessageId { get; set; }
public virtual string Originator { get; set; }
#endregion
[RowVersion]
public virtual byte[] Version { get; set; }
private string _sagaKey;
[Unique]
public virtual string SagaKey
{
get
{
_sagaKey = CreateSagaKey(RuleId, DeviceId);
return _sagaKey;
}
set
{
_sagaKey = value;
}
}
public static string CreateSagaKey(string ruleId, string assetId)
{
return string.Format("{0}/{1}", ruleId, assetId);
}
public virtual string RuleId { get; set; }
public virtual string DeviceId { get; set; }
public virtual string RuleName { get; set; } // Only purpose = make debugging easier...
// Note:
// By default, NHibernate would create database columns of type nvarchar(255).
// However, the lenght of these strings can be more than 255 characters.
// To force NHibernate to create these database columns as nvarchar(max) a hbm.xml file
// has to be created for this type with Build action = "embedded resource".
// Also, in that file, don't forget to make the SagaKey field unique=true!!!
public virtual string InvokingTriggerAsString { get; set; }
public virtual string InvokingDataExpressionAsString { get; set; }
public virtual bool InProgress { get; set; }
public virtual int DelayInSeconds { get; set; }
public virtual int RepetitionIntervalInSeconds { get; set; }
public virtual int MaximumNumberOfRepetitions { get; set; }
public virtual int ExecutionCounter { get; set; }
}