New Posts New Posts RSS Feed: Application Architecture
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Application Architecture

 Post Reply Post Reply
Author
smi-mark View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
Post Options Post Options   Quote smi-mark Quote  Post ReplyReply Direct Link To This Post Topic: Application Architecture
    Posted: 25-Jul-2011 at 8:39pm

I am looking at designing a Point of Sale system and I had a few questions regarding architecture. The below diagram is how I have envisioned it so far.

http://img189.imageshack.us/img189/3523/diagrams.png

I am planning on using DevForce with NServiceBus. In case of outages the tills absolutely have to have the latest products at all times. I have a couple options for how to implement this.

When the tills startup they will do a complete refresh of the Product and lookup tables.

Option 1:

The interface will be responsible for updating prices and product changes. Rather than having the tills poll for item updates, the Frontend Server (BOS) will then retrieve the updated items and push them (Either with NServiceBus or DevForce) to the tills.

Option 2:

Another option is having the interface push the product changes to the Frontend Server, making it responsible for the actual updates and then pushing the changes to the tills.

When an order has been completed the tills will send a message to the Frontend Server which will push a message to the Interface telling it to export the order to the backend.

Does either of these seem like reasonable options?

As it stands right now the tills will not actually use DevForce to query, other than perhaps the startup code.

Any thoughts?

Thanks,

Mark

 



Edited by smi-mark - 25-Jul-2011 at 8:40pm
Back to Top
ting View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 27-Mar-2009
Location: San Francisco
Posts: 427
Post Options Post Options   Quote ting Quote  Post ReplyReply Direct Link To This Post Posted: 26-Jul-2011 at 6:35pm
Hi Mark,

I'm still trying to educate myself on your diagram. As I understand it:

Till = Point of sale terminal (e.g. cash register)
Frontend Server = DevForce BOS
Backend = Purchase fulfillment system
Interface = Admin console and service that marshals purchases to the Backend?

With Option 1, we haven't specified how the Frontend Server will know which updated records to push to the Tills. You either need to tell it explicitly, or just notify it that something has changed at time X, and it will find everything that has has a modification timestamp after X.

There may be a hybrid architecture that makes sense. You have the Interface submit the changed entities to the Frontend Server as part of a typical save. In the EntityServerSaveInterceptor, you tell the DevForce Push service which entities have changed after the save is complete. The Push service then notifies all the Tills of the updates.

Back to Top
smi-mark View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
Post Options Post Options   Quote smi-mark Quote  Post ReplyReply Direct Link To This Post Posted: 26-Jul-2011 at 7:03pm
Hi Ting,

You are pretty much spot on.

The backend is where the product maintenance (Price changes, etc) are done and for storing sales history

The hybrid architecture is what I have come up with so far. The Interface submits the changes to the Frontend Server ( BOS) and I'm using the EntityServerSaveInterceptor to push the changes to the tills. Right now I'm using NServiceBus to push the changed entities to the clients.

What is the best way to integrate DevForce Push service with the EntityServerSaveInterceptor? Would I setup my server method  then access the static variables from the interceptor?  I'm not sure of the best practices of using the push service outside of a standard server method.
Back to Top
smi-mark View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
Post Options Post Options   Quote smi-mark Quote  Post ReplyReply Direct Link To This Post Posted: 26-Jul-2011 at 8:58pm
One of the downsides in the DevForce push is I have to keep the main method open, below is the code I have come up with, please feel free to critique and improve upon.


public class EntityServerSaveManager : EntityServerSaveInterceptor
{

        protected override bool ExecuteSave()
        {
            var em = EntityManager;
            var ok = base.ExecuteSave();

            if (ok)
            {
                var entityTypes = new[] { typeof(Product), typeof(ProductSpecial) };
                var entities = EntityManager
                    .FindEntities(EntityState.Added | EntityState.Deleted | EntityState.Modified)
                    .OfType<Entity>()
                    .Where(t => entityTypes.Contains(t.GetType()))
                    .ToList();

                EntityUpdateService.NotifyClients(entities);
            }

            return ok;
        }
}



    public class EntityUpdateService
    {
        private static Guid _serviceKey;
        private static INotificationManager _notificationManager;
        private static POSEntities _entityManager;
        private static bool _isInitialized;


        public static void Subscribe(Guid serviceKey,
            INotificationManager notificationManager,
            EntityManager entityManager)
        {
            _serviceKey = serviceKey;
            _notificationManager = notificationManager;
            _entityManager = new POSEntities(entityManager);
            _isInitialized = true;

            while (_notificationManager.GetSubscribers(_serviceKey).Count > 0)
            {
                System.Threading.Thread.Sleep(1000);
            }

            _isInitialized = false;
        }

        public static void NotifyClients(IEnumerable<Entity> entities)
        {
            if (!_isInitialized)
                return;

            if (entities.Count() == 0)
                return;

            var cacheState = _entityManager.CacheStateManager.GetCacheState(entities);

            var entitiesUpdatedInfo = new EntitiesUpdatedInfo
                                          {
                                              CacheState = cacheState
                                          };

            _notificationManager.Send(_serviceKey, entitiesUpdatedInfo);
        }
    }


Is there a better way to do this than having to keep calling sleep in the original method?
Back to Top
ting View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 27-Mar-2009
Location: San Francisco
Posts: 427
Post Options Post Options   Quote ting Quote  Post ReplyReply Direct Link To This Post Posted: 27-Jul-2011 at 7:26pm
The code you show seems to meet your needs.

I would put a lock inside NotifyClients to guard against multiple concurrent calls since it's not re-entrant. This is just in case you have multiple save requests pending. If that becomes common, then you'd want to look at placing the entitiesUpdatedInfo into a concurrent queue on one thread (in the EntityServerSaveInterceptor), and pulling it out of the queue in another thread (the while loop of the Subscribe method). This prevents blocking on the save which could cause timeouts with heavy traffic (your current use case wouldn't worry about this though).

Back to Top
smi-mark View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
Post Options Post Options   Quote smi-mark Quote  Post ReplyReply Direct Link To This Post Posted: 01-Aug-2011 at 11:31am
Thanks, Ting. That sounds like a good solution. 
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down