I intend to use this post to document some of the things that I’ve done in the Reactivity project, that I am proud of and that I think would be cool to share and reused in the future.
Reactivity is open source, at least for the part I wrote. Please refer to this frozen subversion repository for a clean check out of Reactivity source code: http://svn.ziyan.info/svn/reactivity, you can also browse it online here.
Object Model
Before I talk about anything else, object model of Reactivity is the base of everything. Basically there are three main tables in Reactivity’s SQL Server 2005 database: user, device, rule. And correspondingly, there are three main object types in Reactivity.Objects: User, Device, Rule. These objects are used to hold data retrieved from the database, except for a user’s password due to security reasons. In the current version of Reactivity, everything is cached on the server’s memory in the forms of objects. The database is merely a place to store a copy of all the data and changes in case the server goes down and needs to be restarted, in which case, all objects are reloaded from the database. This feature could be improved by partial caching instead of full caching, meaning to only cache the frequently used objects instead of everything.
Event Notification System
Reactivity uses Windows Communication Foundation, the latest service-oriented technology from .NET Framework 3.5, an upgrade of .NET XML Web Service. WCF has a dual HTTP binding that allows callback from the service. But I used basic HTTP binding because this binding fits in most situations and is even backward compatible with .NET XML Web Service.
In order to do callback or event in basic HTTP binding, on the server side (Reactivity.Server), I set up the web service to use multiple concurrency mode (Reactivity.Server.Clients.ClientService), then create a queue for each session (Reactivity.Server.Clients.ClientSession). In association with the queue are a mutex and an EventWaitHandler. On the client side, after a session is established, a thread is created to constantly call a method to get the events from the queue on the server. But the EventWaitHandler will wait some amount of time, say 10 seconds, before returning an empty result to the client if the queue is empty. Once an event is en-queued on the server, the EventWaitHandler will be woken. And if the client is in the progress of calling the get events method at this moment, all available events in the queue will be returned immediately. This system simulates a pretty fast and reliable event notification system, and is in the heart of Reactivity.
For example, in Reactivity.UI.Client, which is the enhanced version of Reactivity.Clients.Client, list of devices, users, rules are cached on the client side once they are retrieved from the server for the first time. The event notification system will tell all clients about an update to a particular device, user or rule. So, if you open two control panels on two different machines at the same time, change to one will affect the other immediately. The cached list are ObservableCollections which are bound directly into the WPF GUI. The code is clean and simple.
I reserved Reactivity.Clients.Client, which is a basic version of the client without any threading or caching, because it is used in Reactivity.Web. Reactivity.Web contains the code for all sort of Web Handlers that I’ve created to provide users with an application-like web experience using AJAX. The web that I’ve created for iPhone and iPod Safari implements a similar event notification system. In this case, the threading is done in JavaScript to constantly call a method to get events from the server. The similar technology enables the mobile client to receive real time sensor data and reflects real time changes to objects. For example, when a device goes offline, and the mobile user is watching the live data coming from this device, the web client will be notified about the event, will automatically unsubscribe the live data for the user and will update the page to reflect the change. Everything is done seamlessly through event notification system.
Live Data Subscription
Since I just mentioned live data in the event notification system, I would like to talk more about it. Live data is essentially done through event notification system. But I don’t push all available data to the clients, that would be overwhelming for some clients, like mobile users. Instead, the client needs to create a subscription, or in another word, subscribe to the particular device and service before it can get live data. Once the subscrption is created, every time live data is available, it will get en-queued to that client’s event queue as subscription notification. Subscription could be affected when the device’s status changes, say going offline. Reactivity.UI.Client has an enhanced subscription system that allows GUI to register callbacks when a particular subscription has new data.
Rule Chain
I’ve talked about rule chain in the previous post. But here is the details. First of all, rule chain is multi-threaded, this makes it really cool and efficient. When data comes into the server, it gets queued the same way an event gets queued, meaning there are a mutex and an EventWaitHandler. The EventWaitHandler will wake one of the waiting thread (meaning that thread is idle), and the thread will grab the data and get to work.
There are two types of rules. One that uses source code and one that uses assembled dll. Every change to rules will cause the rule chain to reload on server side. The reload process includes sending stop signal to all threads, join all threads to wait for a complete stop. Note that at this point all incoming data will not be lost but will be queued for later process. Since rules are essentially small programs, the next step is to update all the rule instances. If a rule is using source code, it’s hash value will be computed to check against cache. If the source has not be changed, it will not be compiled again. Otherwise, the rule is compiled into a temporary assembly. If the rule is using assembly file, this is skipped. After that, the assembly is loaded and an instance of the specified type is created. The type must be implementing Reactivity.API.IRule, which allows it to be initialized with some customizable settings, to accept incoming data for process, and to be uninitialized when the rule chain is about to be reloaded. After all the rules are updated, the threads are started again to catch up with all the accumulated data in the queue, and process new data.
When programming rules for Reactivity, the class that will be used needs to implement the interface Reactivity.API.IRule. An object that implements Reactivity.API.IAdapter will be provided to the rule to do special actions related to Reactivity, including send data to another device, add data to statistics, push data to subscribing clients, and log messages either to log file or to the control panel.
The control panel has the ability to change the rules and see the rule’s status. It can also receive information about the compilation of individual rules. And most importantly, debug message that rule programmers might need to see.
BROWSE / IN TIMELINE
« Reactivity – Introduction
» Bonjour Paris
BROWSE / IN SAME CATEGORY English
« Reactivity – Introduction
» Bonjour Paris




SPEAK / ADD YOUR COMMENT