Designing ServiceStack and ServiceStack.Redis with a message exchange - multithreading

I have reviewed and implemented / tested all the messaging options with ServiceStack that I know of (and I've searched on and off for a long time). The two are Pub/Sub and RedisMQ. Both of these have limitations that I needed to go beyond. I have already done this and have a solution that works perfectly for my system. The purpose of this posting / question is to see if I missed a better way, and a check on if my solution is really thread-safe. So far it is working well and I think it is good.
What I did was create an "exchange" class, and then a "pub" class and a "sub" class. My need was to have an arbitrary number of publishers, in any number of threads, publish to an arbitrary number of subscribers, in any number of threads. The only restriction is that my publisher and my subscriber can not be in the same thread, as this causes deadlock. This is by design, so for me not a limitation, as I want blocking subscribers (this could actually be changed with one line of code, but is not my application need and would actually be a negative). Also note that the subscribers can be to unique publishers or any number of subscribers to the same publisher (fan-out). This was the MQ limitation I needed to resolve. The Pub/Sub limitations were even greater, but let's not digress into why they did not solve my needs.
The usage construct for what I call RedisMEnQ (En = Enqueue because it uses Redis.EnqueueItemOnList) is to instantiate the pub class for each publisher, and a sub class for each subscriber. The pub and sub classes both own an instance of the exchange class, thus sharing the same exchange code. There is no direct interaction between pub and sub classes except through Redis. The exchange code implements locks so that the various threads are thread safe during exchange transactions, and of course the redis connections are unique for each thread and thus thread safe.
The Exchange code is the most interesting, and quite short, so I thought I'd post it:
public class Subscriber
{
public int id { get; set; }
public string key { get; set; }
public bool active { get; set; }
}
public class RedisQueueExchange
{
private IRedisList<Subscriber> RedisSubscribers;
IRedisClient Redis;
public string Key { get; set; }
public const string SubscriberListKey = "exchange:subscribers";
private int id;
public int ID { get { return id; } private set { id = value; } }
private Object thisLock = new Object(); // Mutuall exclusion lock
public RedisQueueExchange(IRedisClient _redis, string _key)
{
Key = _key;
Redis = _redis;
RedisSubscribers = Redis.As<Subscriber>().Lists[SubscriberListKey];
}
private int addSubscriber(string _key){
Subscriber sub = new Subscriber { id = 0, active = true, key = _key };
List<Subscriber> subscribers = RedisSubscribers.GetAll();
int idx = subscribers.FindIndex(x => !x.active);
if (idx < 0)
{
sub.id = idx = subscribers.Count;
RedisSubscribers.Add(sub);
}
else
{
sub.id = idx;
RedisSubscribers[idx] = sub;
}
return idx;
}
private List<Subscriber> findSubscribers(string key)
{
List<Subscriber> subscribers = RedisSubscribers.GetAll();
return subscribers.FindAll(x => x.key.Equals(key));
}
public int Subscribe(){
lock (thisLock)
{
ID = addSubscriber(Key);
return ID;
}
}
public string getSubscribeKey(int id)
{
return "sub:" + id.ToString() + ":" + Key;
}
public void UnSubscribe(int id)
{
lock (thisLock)
{
List<Subscriber> subscribers = RedisSubscribers.GetAll();
int idx = subscribers.FindIndex(x => x.id == id);
RedisSubscribers[idx].active = false;
}
}
public int pubMsg(string msg)
{
lock (thisLock)
{
List<Subscriber> subList = findSubscribers(Key);
int retVal = subList.Count;
foreach (Subscriber sub in subList)
{
string subkey = "sub:" + sub.id.ToString() + ":" + Key;
Redis.EnqueueItemOnList(subkey, msg);
}
return retVal;
}
}
public void clearExchange(){
if(RedisSubscribers != null )
RedisSubscribers.Clear();
}
}
There are lots of ways to approach the problem, but to understand the code one thing should be clarified. I am reusing subscriber ids. That makes it slightly more complex than it would be otherwise. I didn't want to have unnecessary gaps in subscriber ids, so if a subscriber unsubscribes, the next subscriber will pick up the unused id. I put the locks in so that a subscriber does not partly subscribe while a publisher is publishing. Either the subscriber is fully subscribed or not at all.

Related

DDD entity with complex creation process

How entities with complex creation process should be created in DDD? Example:
Entity
- Property 1
- Property 2: value depends on what was provided in Property 1
- Property 3: value depends on what was provided in Property 1
- Property 4: value depends on what was provided in Property 1, 2 and 3
I have two ideas but both looks terrible:
Create entity with invalid state
Move creation process to service
We are using REST API so in first scenario we will have to persist entity with invalid state and in second scenario we move logic outside of the entity.
You can use the Builder Pattern to solve this problem.
You can make a Builder that has the logic for the dependencies between properties and raise Exceptions, return errors or has a mechanism to tell the client which are the next valid steps.
If you are using an object orienterd language, the builder can also return different concrete classes based on the combination of these properties.
Here's a very simplified example. We will store a configuration for EventNotifications that can either listen on some Endpoint (IP, port) or poll.
enum Mode { None, Poll, ListenOnEndpoint }
public class EventListenerNotification {
public Mode Mode { get; set; }
public Interval PollInterval { get; set; }
public Endpoint Endpoint { get; set; }
}
public class Builder {
private Mode mMode = Mode.None;
private Interenal mInterval;
private Endpoint mEndpoint;
public Builder WithMode(Mode mode) {
this.mMode = mode;
return this;
}
public Builder WithInterval(Interval interval) {
VerifyModeIsSet();
verifyModeIsPoll();
this.mInterval = interval;
return this;
}
public Builder WithEndpoint(Endpoint endpoint) {
VerifyModeIsSet();
verifyModeIsListenOnEndpoint();
this.mInterval = interval;
return this;
}
public EventListenerNotification Build() {
VerifyState();
var entity = new EventListenerNotification();
entity.Mode = this.mMode;
entity.Interval = this.mInterval;
entity.Endpoint = this.mEndpoint;
return entity;
}
private void VerifyModeIsSet() {
if(this.mMode == Mode.None) {
throw new InvalidModeException("Set mode first");
}
}
private void VerifyModeIsPoll() {
if(this.mMode != Mode.Poll) {
throw new InvalidModeException("Mode should be poll");
}
}
private void VerifyModeIsListenForEvents() {
if(this.mMode != Mode.ListenForEvents) {
throw new InvalidModeException("Mode should be ListenForEvents");
}
}
private void VerifyState() {
// validate properties based on Mode
if(this.mMode == Mode.Poll) {
// validate interval
}
if(this.mMode == Mode.ListenForEvents) {
// validate Endpoint
}
}
}
enum BuildStatus { NotStarted, InProgress, Errored, Finished }
public class BuilderWithStatus {
private readonly List<Error> mErrors = new List<Error>();
public BuildStatus Status { get; private set; }
public IReadOnlyList<Error> Errors { get { return mErrors; } }
public BuilderWithStatus WithInterval(Interval inerval) {
if(this.mMode != Mode.Poll) {
this.mErrors.add(new Error("Mode should be poll");
this.Status = BuildStatus.Errored;
}
else {
this.mInterval = interval;
}
return this;
}
// rest is same as above, but instead of throwing errors you can record the error
// and set a status
}
Here are some resources with more information and other machisms that you can use:
https://martinfowler.com/articles/replaceThrowWithNotification.html
https://martinfowler.com/eaaDev/Notification.html
https://martinfowler.com/bliki/ContextualValidation.html
Take a look at chapter 6 of the Evans book, which specifically talks about the life cycle of entities in the domain model
Creation is usually handled with a factory, which is to say a function that accepts data as input and returns a reference to an entity.
in second scenario we move logic outside of the entity.
The simplest answer is for the "factory" to be some method associate with the entity's class - ie, the constructor, or some other static method that is still part of the definition of the entity in the domain model.
But problem is that creation of the entity requires several steps.
OK, so what you have is a protocol, which is to say a state machine, where you collect information from the outside world, and eventually emit a new entity.
The instance of the state machine, with the data that it has collected, is also an entity.
For example, creating an actionable order might require a list of items, and shipping addresses, and billing information. But we don't necessarily need to collect all of that information at the same time - we can get a little bit now, and remember it, and then later when we have all of the information, we emit the submitted order.
It may take some care with the domain language to distinguish the tracking entity from the finished entity (which itself is probably an input to another state machine....)

Spring-Integration: external routing slip

I would like to allow callers to pass an external routing slip, e.g. by posting:
POST http://localhost:8080/transform?routing-slip=capitalize&routing-slip=lowercase
Content-Type: text/plain
camelCase
It should be possible to use the given routing-slip array as external routing slip from a pojo:
#Bean
public IntegrationFlow transformerChain(RoutingSlipRouteStrategy routeStrategy) {
return IntegrationFlows.from(
Http.inboundGateway("/transform")
.headerExpression("routingSlipParam",
"#requestParams['routing-slip']")
.requestPayloadType(String.class))
.enrichHeaders(spec -> spec.header(
IntegrationMessageHeaderAccessor.ROUTING_SLIP,
new RoutingSlipHeaderValueMessageProcessor(
"#routePojo.get(request, reply)")
)
)
.logAndReply();
}
The pojo can access the routingSlipParam header and you would think it can then hold the slip as internal state, or at least that is what TestRoutingSlipRoutePojo lead me to believe, so I built this (with a slight doubt, given that there is only one instance of the pojo):
public class ExternalRoutingSlipRoutePojo {
private List<String> routingSlip;
private int i = 0;
public String get(Message<?> requestMessage, Object reply) {
if (routingSlip == null) {
routingSlip = (LinkedList)requestMessage.getHeaders()
.get("routingSlipParam");
}
try {
return this.routingSlip.get(i++);
} catch (Exception e) {
return null;
}
}
}
It turns out that this only works exactly once, which is not surprising after all - the index is incremented for every incoming message and the routing slip is never updated.
So I thought, sure, I have to hold the internal status for all incoming messages and came up with this RouteStrategy:
public class ExternalRoutingSlipRouteStrategy implements RoutingSlipRouteStrategy {
private Map<UUID, LinkedList<String>> routingSlips = new WeakHashMap<>();
private static final LinkedList EMPTY_ROUTINGSLIP = new LinkedList<>();
#Override
public Object getNextPath(Message<?> requestMessage,Object reply) {
MessageHeaders headers = requestMessage.getHeaders();
UUID id = headers.getId();
if (!routingSlips.containsKey(id)) {
#SuppressWarnings("unchecked")
List<String> routingSlipParam =
headers.get("routingSlipParam", List.class);
if (routingSlipParam != null) {
routingSlips.put(id,
new LinkedList<>(routingSlipParam));
}
}
LinkedList<String> routingSlip = routingSlips.getOrDefault(id,
EMPTY_ROUTINGSLIP);
String nextPath = routingSlip.poll();
if (nextPath == null) {
routingSlips.remove(id);
}
return nextPath;
}
}
That does not work either because the strategy is not only called for the incoming message but also for all the new messages which are created by the dynamic routing, which of course have different IDs.
But it is only called twice for the original message, so the routing slip never gets exhausted and the application runs in an endless loop.
How can I make spring-integration use an external routing slip?
UPDATE:
As suggested by Gary Russel, neither the external routing slip index nor the external routing slip itself should be stored in the Spring bean, rather one can use message headers to maintain them separately for each request:
Http.inboundGateway("/transform")
.headerExpression("routingSlipParam",
"#requestParams['routing-slip']")
.requestPayloadType(String.class))
.enrichHeaders(spec -> spec
.headerFunction("counter",h -> new AtomicInteger())
.header(IntegrationMessageHeaderAccessor.ROUTING_SLIP,
new RoutingSlipHeaderValueMessageProcessor(externalRouteStrategy)
)
)
The externalRouteStrategy is an instance of the following class:
public class ExternalRoutingSlipRouteStrategy implements
RoutingSlipRouteStrategy {
#Override
public Object getNextPath(Message<?> requestMessage, Object reply) {
List<String> routingSlip = (List<String>)
requestMessage.getHeaders().get("routingSlipParam");
int routingSlipIndex = requestMessage.getHeaders()
.get("counter", AtomicInteger.class)
.getAndIncrement();
String routingSlipEntry;
if (routingSlip != null
&& routingSlipIndex < routingSlip.size()) {
routingSlipEntry = routingSlip.get(routingSlipIndex);
} else {
routingSlipEntry = null;
}
return routingSlipEntry;
}
}
For reference, I have published the example in Github.
Go back to your first version and store i in a message header (AtomicInteger) in the header enricher.
.headerExpression("counter", "new java.util.concurrent.atomic.AtomicInteger()")
then
int i = requestMessage.getHeaders().get("counter", AtomicInteger.class).getAndIncrement();

Whats wrong in this Parallel.For Code?

this is the code that i want to run.
Parallel.For(1, itemCount, 1, () =>
{
return new ThreadLocalStateCache()
{
//assigning values to local variables
Receipient = serMailObj.ReceipientList.Dequeue(), //get a single recepeint for the email
mail = serMailObj.Email, //Object of type MailMessage
client = client //object of type SmtpClient
};
}
, (i, loopState) =>
{
doWork(i, loopState.ThreadLocalState);
});
}
//class to store local vairables for each thread
public class ThreadLocalStateCache
{
public KeyValuePair<string, string> Receipient { get; set; }
public MailMessage mail { get; set; }
public SmtpClient client { get; set; }
}
private static void doWork(int instance, ThreadLocalStateCache threadInstance)
{
//send mail
}
and it keeps on saying
The type arguments for method 'System.Threading.Tasks.Parallel.For(long, long, System.Func, System.Func, System.Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I could not find any resource on the internet that explains clearly how to use parallel.for with thread local variables. I am trying to process long list of email recipients and send mails to them. Please tell how can i use parallel.for.
EDIT 1: I am trying this code after reading this article http://www.lovethedot.net/2009/02/parallelfor-deeper-dive-parallel.html
The Parallel.For overloads that take step as the third argument were removed from .NET 4; see comments to http://blogs.msdn.com/b/pfxteam/archive/2009/05/26/9641563.aspx.
Due to that, your call with 5 arguments is resolved to this overload:
For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32, ParallelLoopState, TLocal, TLocal>, Action<TLocal>)
And obviously the compiler cannot match types of the arguments.
Since the step is 1 anyway, just remove it.
Then you will need to fix the body delegate which must have three parameters (since thread local variable is now separate from loop state object), and add another delegate that will be applied to thread local variables for final computation. At the end, it should be something like this:
Parallel.For( 1, itemCount,
() =>
{ return new ThreadLocalStateCache()
{
Receipient = serMailObj.ReceipientList.Dequeue(),
mail = serMailObj.Email,
client = client
};
},
(i, loopState, threadLocal ) =>
{
doWork(i, threadLocal);
return threadLocal;
},
(threadLocal) => {}
);

Retrieving values of ReadOnly fields from DynamicData DetailsView in Edit Mode on Updating using LinqDataSource

I have several tables in my database that have read-only fields that get set on Inserting and Updating, namely: AddDate (DateTime), AddUserName (string), LastModDate (DateTime), LastModUserName (string).
All of the tables that have these values have been set to inherit from the following interface:
public interface IUserTrackTable
{
string AddUserName { get; set; }
DateTime AddDate { get; set; }
string LastModUserName { get; set; }
DateTime LastModDate { get; set; }
}
As such, I have the following method on the Edit.aspx page:
protected void DetailsDataSource_Updating(object sender, LinqDataSourceUpdateEventArgs e)
{
IUserTrackTable newObject = e.NewObject as IUserTrackTable;
if (newObject != null)
{
newObject.LastModUserName = User.Identity.Name;
newObject.LastModDate = DateTime.Now;
}
}
However, by the time it hits this method, the e.OriginalObject has already lost the values for all four fields, so a ChangeConflictException gets thrown during the actual Update. I have tried adding the four column names to the DetailsView1.DataKeyNames array in the Init event handler:
protected void Page_Init(object sender, EventArgs e)
{
// other things happen before this
var readOnlyColumns = table.Columns.Where(c => c.Attributes.SingleOrDefaultOfType<ReadOnlyAttribute>(ReadOnlyAttribute.Default).IsReadOnly).Select(c => c.Name);
DetailsView1.DataKeyNames = DetailsView1.DataKeyNames.Union<string>(readOnlyColumns).ToArray<string>();
DetailsView1.RowsGenerator = new CustomFieldGenerator(table, PageTemplates.Edit, false);
// other things happen after this
}
I've tried making that code only happen on PostBack, and still nothing. I'm at a lose for how to get the values for all of the columns to make the round-trip.
The only thing the CustomFieldGenerator is handling the ReadOnlyAttribute, following the details on C# Bits.
UPDATE: After further investigation, the values make the round trip to the DetailsView_ItemUpdating event. All of the values are present in the e.OldValues dictionary. However, they are lost by the time it gets to the LinqDataSource_Updating event.
Obviously, there are the "solutions" of making those columns not participate in Concurrency Checks or other ways that involve hard-coding, but the ideal solution would dynamically add the appropriate information where needed so that this stays as a Dynamic solution.
i Drovani, I assume you want data auditing (see Steve Sheldon's A Method to Handle Audit Fields in LINQ to SQL), I would do this in the model in EF4 you can do it like this:
partial void OnContextCreated()
{
// Register the handler for the SavingChanges event.
this.SavingChanges += new EventHandler(context_SavingChanges);
}
private static void context_SavingChanges(object sender, EventArgs e)
{
// handle auditing
AuditingHelperUtility.ProcessAuditFields(objects.GetObjectStateEntries(EntityState.Added));
AuditingHelperUtility.ProcessAuditFields(objects.GetObjectStateEntries(EntityState.Modified), InsertMode: false);
}
internal static class AuditingHelperUtility
{
internal static void ProcessAuditFields(IEnumerable<Object> list, bool InsertMode = true)
{
foreach (var item in list)
{
IAuditable entity = item as IAuditable;
if (entity != null)
{
if (InsertMode)
{
entity.InsertedBy = GetUserId();
entity.InsertedOn = DateTime.Now;
}
entity.UpdatedBy = GetUserId();
entity.UpdatedOn = DateTime.Now;
}
}
}
}
Sadly this is not possible with EF v1

Can Prism EventAggregator be used for threading needs?

I was looking at Prism EventAggregator and its' great. I part i was most concerned was its capability to marshal thread correctly to UI thread.
I was wondering if i can use this capability to provide module developers a class which could be used to create threads in a similar way as BackgroundWorker. Interface of class can be somewhat similar to
public interface IMyTask
{
event DoWorkEventHandler DoWork;
event RunWorkerCompletedEventHandler RunWorkerCompleted;
void RunTaskAsync(object obj);
}
I have kept types similar to backgroundworker for better understanding. In implementation i am registering taskstart and taskcomplete events
public class TaskStartEventPayload
{
public SubscriptionToken token { get; set; }
public object Argument { get; set; }
}
public class TaskStartEvent : CompositePresentationEvent<TaskStartEventPayload>
{
}
public class TaskCompleteEventPayload
{
public SubscriptionToken token { get; set; }
public object Argument { get; set; }
public object Result { get; set; }
}
public class TaskCompleteEvent : CompositePresentationEvent<TaskCompleteEventPayload>
{
}
In the constructor for the MyTask class i take which thread the completion is required on as
public MyTask(IEventAggregator eventAggregator, bool isUICompletion)
{
if (eventAggregator == null)
{
throw new ArgumentNullException("eventAggregator");
}
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<TaskStartEvent>().Subscribe(TaskStartHandler, ThreadOption.BackgroundThread, false, new Predicate<TaskStartEventPayload>(StartTokenFilter));
if(isUICompletion)
_token = _eventAggregator.GetEvent<TaskCompleteEvent>().Subscribe(TaskCompleteHandler, ThreadOption.UIThread,true,new Predicate<TaskCompleteEventPayload>(CompleteTokenFilter));
else
_token = _eventAggregator.GetEvent<TaskCompleteEvent>().Subscribe(TaskCompleteHandler, ThreadOption.BackgroundThread, true, new Predicate<TaskCompleteEventPayload>(CompleteTokenFilter));
}
here i am registering with filters where filter function returns the event only if it has Payload has same token as while got while subscribing.
further I use
public void RunTaskAsync(object obj)
{
//create payload
_eventAggregator.GetEvent<TaskStartEvent>().Publish(payload);
}
public void TaskStartHandler(TaskStartEventPayload t)
{
//fire dowork and create payload
DoWork(this, args);
_eventAggregator.GetEvent<TaskCompleteEvent>().Publish(tc);
}
public void TaskCompleteHandler(TaskCompleteEventPayload t)
{
RunWorkerCompleted(this, args);
}
This class can be used as
MyTask et = new MyTaskagg, true);
et.DoWork += new System.ComponentModel.DoWorkEventHandler(et_DoWork);
et.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(et_RunWorkerCompleted);
et.RunTaskAsync("Test");
Benefit I see in this approach is
1. It uses threadpool so no overhead of creating threads as in backgroundWorker.
2. Proper thread marshalling in case RunWorkerCompleted to be executed on UI thread.
Please advice if this would be correct to use eventaggregator as Threader.
This will work, although it's code you have to debug for very little performance gain. Micro-optimizing is rarely worth the effort and support costs in my opinion.
EventAggregator is meant to be a message bus for your application and I typically prefer to use things for their original intention, lest I have to debug a lot of code, but that's my personal preference.
Event Aggregator is going to have to work a little harder than it is meant to cleaning up all of those subscriptions, which will likely exceed any performance gain you get from the thread pooling, but that is just a guess.

Resources