Projections Example

Last week in class a question regarding bugs over time in system. In specific let’s assume that I had a bug in my system, I want to know how many places were affected by that bug and possibly I need to issue some form of compensating action to places that were affected.

Let’s assume that I have a business rule that should be in my system. You can only deactivate inventory items that have a name starting with the first letter ‘p’. Unfortunately we realized that we have forgotten to put this rule in appropriately and it is a key business concept.

Using SQL we might issue a query:

SELECT * FROM INVENTORYITEMS WHERE ACTIVATED=FALSE AND NOT NAME LIKE “P%”

This however does not give us an appropriate answer to our question. This shows us all Inventory Items that are now deactivated with a name other than one that starts with P. What if someone deactivated an Inventory Item and then renamed it? The business rule states that it must start with the letter p at the time of deactivation not that it must be like this now.

Remember this is a very important rule within our business domain and things could be screwed up elsewhere because of it!

This is a perfect use case for writing a quick projections based query.

fromCategory('InventoryItem')
	.foreachStream()
		.when({
			InventoryItemCreated    : function(s,e) {
										return {
										   id : e.id,
										   name : e.name,
										   problem : false
										}
									  },
			InventoryItemRenamed     : function(s,e) {
										return {
										   id : s.id,
										   name : e.name,
										   problem : s.problem
										}
									   }
			InventoryItemDeactivated : function(s,e) {
										return {
										   id : s.id,
										   name : s.name,
										   problem : s.name.startWith('p')
										}
									   }
		})
		.transformedBy(function(s) {
		      if(!s.problem) return null;
		      return s;
		})

or the alternative (shorter)

fromCategory('InventoryItem')
	.foreachStream()
		.when({
			InventoryItemCreated    : function(s,e) {
										return {
										   id : e.id,
										   name : e.name,
										   problem : false
										}
									  },
			InventoryItemRenamed     : function(s,e) { s.name=e.name},
			InventoryItemDeactivated : function(s,e) {s.problem=s.name.startWith('p')}										
		})
		.transformedBy(function(s) {
		      if(!s.problem) return null;
		      return s;
		})

This quick query when run will produce a stream representing all inventory item streams where the problem occured in the form of:

{
    id : 12345,
    name : "foo",
    problem : true
}

You could then take the resulting stream and pipe to an operation to fix all of the items. As an example emiting an event to the stream to “Reactivate” the item marking the previous deactivation as being errorneous. And yes this query will be automatically parallelized to run across multiple nodes within a cluster if you happen to have say 200m Inventory Item events.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>