<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Greg Young&#039;s Blog</title>
	<atom:link href="http://goodenoughsoftware.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://goodenoughsoftware.net</link>
	<description>Good Enough Software is By Definition Good Enough</description>
	<lastBuildDate>Thu, 18 Apr 2013 10:51:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='goodenoughsoftware.net' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Greg Young&#039;s Blog</title>
		<link>http://goodenoughsoftware.net</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://goodenoughsoftware.net/osd.xml" title="Greg Young&#039;s Blog" />
	<atom:link rel='hub' href='http://goodenoughsoftware.net/?pushpress=hub'/>
		<item>
		<title>Repeat from 2008</title>
		<link>http://goodenoughsoftware.net/2013/04/07/repeat-from-2008/</link>
		<comments>http://goodenoughsoftware.net/2013/04/07/repeat-from-2008/#comments</comments>
		<pubDate>Sun, 07 Apr 2013 09:22:43 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=624</guid>
		<description><![CDATA[Five years ago at alt.net Seattle I recorded this panel discussion about static vs dynamic languages with some heavy hitters over at Microsoft. The conversations are as meaningful today as they were then http://www.viddler.com/v/40aa9085 is a click through link!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=624&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Five years ago at alt.net Seattle I recorded this panel discussion about static vs dynamic languages with some heavy hitters over at Microsoft. The conversations are as meaningful today as they were then</p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="437" height="370" id="viddler_player_437"> <param name="movie" value="//www.viddler.com/player/40aa9085/"><param name="allowScriptAccess" value="always"/><param name="allowNetworking" value="all"/><param name="wmode" value=""/><param name="allowFullScreen"value="true"/><param name="flashVars" value="f=1&amp;player=full&amp;autoplay=f&amp;disablebranding=f&amp;liverailTags="/><embed src="//www.viddler.com/player/40aa9085/" width="437" height="370" type="application/x-shockwave-flash" wmode="" allowScriptAccess="always" allowFullScreen="true" allowNetworking="all" name="viddler_player_437" flashVars="f=1&amp;player=full&amp;autoplay=f&amp;disablebranding=f&amp;liverailTags="></embed></object>
<p><a href="http://www.viddler.com/v/40aa9085">http://www.viddler.com/v/40aa9085</a> is a click through link!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/624/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/624/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=624&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/04/07/repeat-from-2008/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Projections 8: Internal Indexing</title>
		<link>http://goodenoughsoftware.net/2013/03/09/projections-8-internal-indexing/</link>
		<comments>http://goodenoughsoftware.net/2013/03/09/projections-8-internal-indexing/#comments</comments>
		<pubDate>Sat, 09 Mar 2013 16:03:33 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=618</guid>
		<description><![CDATA[In the last post we introduced the new concept of fromStreams([]) that will join multiple streams into a single stream for your fold to be run against. We also introduced options and two options that can be used to control the re-ordering behaviour in a distributed environment. In this post we are going to look [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=618&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>In the <a href="http://geteventstore.com/blog/20130309/projections-7-multiple-streams/">last post</a> we introduced the new concept of fromStreams([]) that will join multiple streams into a single stream for your fold to be run against. We also introduced options and two options that can be used to control the re-ordering behaviour in a distributed environment. In this post we are going to look at how this concept is used internally in the Event Store in order to provide indexing of queries.</p>
<p>Let&#8217;s propose a scenario where you have 80,000,000 events in the Event Store. You wish to write a query that looks like:</p>
<pre class="brush: jscript; title: ; notranslate">
fromAll().
    when({
        Foo: function(s,e) { ... },
        Bar: function(s,e) { ... },
        Baz: function(s,e) { ... } 
    });
</pre>
<p>In the store there are a total of 500 Foo events, 100 Bar events, and 1000 Baz events. This query would be very very expensive to run as it would need to look through 80,000,000 events in order to run on the 1600 events that you are interested in (the equivalent of a table scan in sql). This query though can (and is) indexed internally!</p>
<p>If you look in options there is another option called &#8220;useEventIndexes&#8221; that defaults to true. If you enable this option, this query will only look at 1600 events and ignore the other 80,000,000! </p>
<p>This works using the same principles we have been learning in the blog post series. If you look there is a special projection in the Event Store called $by_event_type. This projection is at this point implemented internally but if it were written in javascript it would look something like:</p>
<pre class="brush: jscript; title: ; notranslate">
fromAll().
    when({
        $any : function(s,e) { linkTo(&quot;$et-&quot; + e.type, e); }
    });
</pre>
<p>In other words the projection will create a stream per event type named $et-{eventtype} that contains links to all events of that type. This standard projection can then be used in conjunction with other projections to provide indexing. Consider our original projection:</p>
<pre class="brush: jscript; title: ; notranslate">
fromAll().
    when({
        Foo: function(s,e) { ... },
        Bar: function(s,e) { ... },
        Baz: function(s,e) { ... } 
    });
</pre>
<p>This can now be converted into an indexed projection using fromStreams(). We can convert it into:</p>
<pre class="brush: jscript; title: ; notranslate">
fromStreams([&quot;$et-Foo&quot;, &quot;$et-Bar&quot;, &quot;$et-Baz&quot;]).
    when({
        Foo: function(s,e) { ... },
        Bar: function(s,e) { ... },
        Baz: function(s,e) { ... } 
    });
</pre>
<p>This is done by default. It will then read only from the three joined streams listed! not from all of the events in the system, in our example it will only see 1600 events, not the 80,000,000 that exist. This is how you can combine some of the ideas we have been looking at to provide indexing in various forms for your projections.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/618/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/618/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=618&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/03/09/projections-8-internal-indexing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Projections 7: Multiple Streams</title>
		<link>http://goodenoughsoftware.net/2013/03/09/projections-7-multiple-streams/</link>
		<comments>http://goodenoughsoftware.net/2013/03/09/projections-7-multiple-streams/#comments</comments>
		<pubDate>Sat, 09 Mar 2013 14:01:55 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=614</guid>
		<description><![CDATA[Up until this point we have only used two event selection methods for our projections. We have used fromStream(&#8216;stream&#8217;) which will select all of the events in a stream and we have used fromAll() which selects all events in the system. There is another quite useful selection that will move us from SEP (Simple Event [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=614&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Up until this point we have only used two event selection methods for our projections. We have used fromStream(&#8216;stream&#8217;) which will select all of the events in a stream and we have used fromAll() which selects all events in the system. There is another quite useful selection that will move us from SEP (Simple Event Processing) to CEP (Complex Event Processing). This is the ability to select between multiple streams.</p>
<p>To select from multiple streams we use fromStreams(['stream1', 'stream2', 'stream3']) what this will do is bring together the events from multiple streams. This can also be called a Join operation. fromStreams(['stream1', 'stream2', 'stream3']) will take the three streams (stream1, stream2, stream3) and produce a single output stream containing events from all three that the projection will be run against.</p>
<p>This operation while seemingly simple is actually quite difficult. Generally the partition point of the system is streams. If you are running in a single node group (not partitioned, either the replicated group or single node) then this projection will have assurances that the events will come in perfect order (even when being processed in real time). But what happens if this is distributed?</p>
<p>You can imagine stream1 lives on one machine and stream2 lives on another machine. This could cause problems with ordering due to situations where the machines are partitioned from each other. Luckily projections allows you to solve this problem with some options that you can set. In particular you can add options</p>
<p>options({<br />
reorderEvents: true,<br />
processingLag: 500 //time in ms<br />
});</p>
<p>This will tell projections to introduce a delay to allow for the reordering of events from different partitions. This allows a much better handling for fromStreams in a distributed scenario. A buffer of processingLag milliseconds will be introduced to allow for the reordering of events before they are run through the projection.</p>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/614/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=614&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/03/09/projections-7-multiple-streams/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Startups and TDD</title>
		<link>http://goodenoughsoftware.net/2013/03/06/startups-and-tdd/</link>
		<comments>http://goodenoughsoftware.net/2013/03/06/startups-and-tdd/#comments</comments>
		<pubDate>Wed, 06 Mar 2013 14:19:43 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=565</guid>
		<description><![CDATA[Yesterday Uncle Bob put up a post on using TDD in start up environments &#8220;The Startup Trap&#8221; its a good read. Check it out. Nate soon after posted: It&#039;s funny, you never see someone with the title &#34;Master Craftsman&#34; at a startup. I wonder why?&#8212; Nate Kohari (@nkohari) March 05, 2013 then I take it all [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=565&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Yesterday Uncle Bob put up a post on using TDD in start up environments <a href="http://t.co/DLE79YFpkc">&#8220;The Startup Trap&#8221;</a> its a good read. Check it out.</p>
<p>Nate soon after posted:</p>
<blockquote class='twitter-tweet'><p>It&#039;s funny, you never see someone with the title &quot;Master Craftsman&quot; at a startup. I wonder why?&mdash; <br />Nate Kohari (@nkohari) <a href='http://twitter.com/#!/nkohari/status/309001001761923072' data-datetime='2013-03-05T18:02:34+00:00'>March 05, 2013</a></p></blockquote>
<p>then</p>
<blockquote class='twitter-tweet'><p>I take it all back. I would strongly encourage startups to use TDD while developing any products that compete with ours. <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &mdash; <br />Nate Kohari (@nkohari) <a href='http://twitter.com/#!/nkohari/status/309005301766561792' data-datetime='2013-03-05T18:19:39+00:00'>March 05, 2013</a></p></blockquote>
<p>I wanted to write a few comments about TDD in startups. Good code is the least of the risks in a startup. Sorry but worrying about technical debt making us go slower when we have a two month runway and likely will pivot four times to quote Bob.</p>
<blockquote><p>Captain Sulu when the Klingon power moon of Praxis exploded and a young Lieutenant asked whether they should notify Star-Fleet: &#8220;Are you kidding?&#8221; ARE YOU KIDDING?</p></blockquote>
<p>One of the biggest mistakes in my career was building something appropriate&#8230;</p>
<p>It was just after Hurricane Katrina. I was living in a hotel. An acquaintance asked me if we could hack together this business idea they had for a trading system. He had the knowledge but not the know how. I said sure, hell I was living in a hotel!</p>
<p>In less than two weeks we had an algorithmic trading system. It was a monstrosity of a source base. It was literally a winforms app connected directly to the stock market. UI interactions happened off events directly from the feed! Everything was in code behinds (including the algos!) Due to the nature of the protocol if anything failed during the day and crashed the app (say bad parsing of a string?) the day for the trader was over as they could not restart.</p>
<p>But after two weeks we put it in front of a trader who started using it. We made about 70-80k$ the first month. We had blundered into the pit of success. A few months later I moved up with the company. We decided that we were going to &#8220;do things right&#8221;. While keeping the original version running and limping along as stable as we could keep it while adding just a few features.</p>
<p>We ended up with a redundant multi-user architecture nine months or so later, it was really quite a beautiful system. If a client/server crashed, no big deal just sign it back on, multiple clients? no problem. We moved from a third party provider to a direct exchange link (faster and more information!). We had &gt; 95% code coverage on our core stuff, integration suites including a fake stock exchange that actually sent packets over UDP so we could force various problems with retry reconnects etc/errors. We were very stable and had a proper clean architecture.</p>
<p>In fact you could say that we were dealing with what Bob describes in:</p>
<blockquote><p>As time passes your estimates will grow. You&#8217;ll find it harder and harder to add new features. You will find more and more bugs accumulating. You&#8217;ll start to parse the bugs into critical and acceptable (as if any bug is acceptable!) You&#8217;ll create modules that are so fragile you won&#8217;t trust yourself, or anyone else, to modify them; so you&#8217;ll work around them. You&#8217;ll build a festering pile of code that, with every passing week, requires more and more effort just to keep running. Forward progress will slow and falter. It may even reverse as each release becomes buggier and buggier, and less and less stable. Catastrophes will become more and more common as errors, that should never have happened, create corruptions and damage that take huge traunches of time to repair.</p></blockquote>
<p>We had built a production prototype and were suffering all the pain described by Bob. We were paying down our debt in an &#8220;intelligent&#8221; way much the way many companies that start with production prototypes do.</p>
<p>However this is still a naive viewpoint. What really mattered was that after our nine months of beautiful architecture and coding work we were making approximately 10k/month more than what our stupid production prototype made for all of its shortcomings.</p>
<p><strong>We would have been better off making 30 new production prototypes of different strategies and &#8220;throwing shit at the wall&#8221; to see what worked than spending any time beyond a bit of stabilization of the first. How many new business opportunities would we have found?</strong></p>
<p>There are some lessons here.</p>
<p>1) If we had started with a nine month project it never would have been done</p>
<p>2) A Production Prototype is common as a Minimum Viable Product. Yes testing, engineering, or properly architecting will likely slow you down on a production prototype.</p>
<p>3) Even if you succeed you are often better to stabilize your Production Prototype than to &#8220;build it right&#8221;. Be very careful about taking the &#8220;build it right&#8221; point of view.</p>
<p>4) Context is important!</p>
<p><strong>Never underestimate the value of working software.</strong></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/565/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/565/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=565&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/03/06/startups-and-tdd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Why not pluralsight</title>
		<link>http://goodenoughsoftware.net/2013/03/06/why-not-pluralsight/</link>
		<comments>http://goodenoughsoftware.net/2013/03/06/why-not-pluralsight/#comments</comments>
		<pubDate>Wed, 06 Mar 2013 08:32:31 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=562</guid>
		<description><![CDATA[I have had a lot of people ask me why I am not putting my online classes into PluralSight. The answer is quite simple, their business model does not align well with the type of content being discussed, I have had these discussions with them before. The pluralsight default royalty model is setup upon a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=562&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I have had a lot of people ask me why I am not putting my online classes into PluralSight. The answer is quite simple, their business model does not align well with the type of content being discussed, I have had these discussions with them before.</p>
<p>The pluralsight default royalty model is setup upon a fractional payment payment system based upon views % during a period. This works wonderful for commoditized trainings such as &#8220;learn C# quickly&#8221; especially if its primarily screencasts. It makes just next to no sense to put up 4 days worth of content.</p>
<p>Think about your viewing habits. Are you going to watch one episode at a time over the course of 12 months or are you going to spend a weekend/week during gym time etc and watch all of the content? So let&#8217;s just imagine that the way it worked was based upon viewing % during the month the royalties would end up being +- $10/viewer on average. Factor in 15k-20keu in order to film/edit 20-25 hours of content and you are saying that maybe you hope to break even at 2500 people viewing.</p>
<p>For a short commoditized class such as &#8220;Introduction to iOS programming&#8221; things would make total sense, wide audience and low production cost, high relevance. For something like a 3 day class + extra material it makes almost no sense.</p>
<p>That said they do now say that &#8220;things are open for negotiation&#8221; so maybe its worth talking to them.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/562/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/562/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=562&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/03/06/why-not-pluralsight/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Ensuring Writes &#8211; Multi-Node Replication</title>
		<link>http://goodenoughsoftware.net/2013/03/01/ensuring-writes-multi-node-replication/</link>
		<comments>http://goodenoughsoftware.net/2013/03/01/ensuring-writes-multi-node-replication/#comments</comments>
		<pubDate>Fri, 01 Mar 2013 16:08:12 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=558</guid>
		<description><![CDATA[We have gotten the question very often how the multi-node version works with replication. After typing it up about five times in email I figured it might be valuable to do a longer write-up that we can suck into our documentation (and a blog post). One could quite easily put the Event Store Open Source [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=558&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>We have gotten the question very often how the multi-node version works with replication. After typing it up about five times in email I figured it might be valuable to do a longer write-up that we can suck into our documentation (and a blog post).</p>
<p>One could quite easily put the Event Store Open Source version running on a virtual machine with data storage on a SAN. If the first machine goes wrong for some reason the VM is spun back up on a different host with connection to the same SAN. This is a perfectly valid way of handling a failover. There are some issues that come up with it however. The largest is the amount of downtime in the middle with a close second being a whole slew of byzantine problems that can occur (network reachability issues as an example)</p>
<p>This is not by any means a &#8220;bad&#8221; system. The Event Store however uses a different model for its replication that comes with its own strengths and weaknesses.</p>
<p>The Event Store uses a quorum based model for replication. As of now all replication is fully consistent though we have talked about other models in the future (more discussion further). When you use a quorum based model you almost always want to have an odd number of servers.</p>
<p>When a server is brought up it will use the dns given to it to find other nodes in its replication group. There is a config point for the predetermined quorum size of the group. It will begin gossiping with these other servers over http until it can get some information about the other nodes that are there.</p>
<p>If there is no quorum yet a Paxos Election will then occur to determine which of the nodes is to be the leader of the replication group (for right now). The Paxos Election basically says that all nodes will agree upon a leader, or none of them will think that they have agreed upon a leader. Once the leader is picked, the leader can begin accepting write transactions (other nodes forward writes to the leader, clients do not need to be aware of the leader).</p>
<p>Every write even in the Single Node open sourced version has a small manager that controls it&#8217;s lifecycle. It will write a prepare followed by a commit. This is done for various reasons not the least of which is transactional writes are supported. It is also used in replication.</p>
<p>The manager will first send out a Prepare of the write. This will go to its local storage writer which will reply with an ACK once the item has been fsynced to disk. The item is also asynchronously dispatched to the other nodes. The manager will not send its commit until a quorum of nodes has acknowledged the message as being fsynced to disk.</p>
<p>If a failure happens during the process of a prepare the commit will never happen, the client will be told that the transaction timed out (or perhaps the connection was lost if the leader was the one that died). The client&#8217;s responsibility in all cases is to retry, the Event Store is idempotent. The C# client will do this automatically for you. This client retrying also handles the case that the manager sent a commit and then died (not sending client a response). Again the client retries in this case. This also holds true in a multi-node scenario.</p>
<p>The interesting case that comes up here is when a commit has been written in the leader but it dies before distributing it to the other nodes and getting acks. The old leader will actually truncate in the process of coming back into the cluster (the client was never told the transaction was committed and thus will retry with the new leader who will know whether or not it was committed).</p>
<p>The key to the style of replication is the two quorums being used. Since a transaction is only considered written when a majority of nodes have it, when an election happens (also requires a quorum) you are assured that one node in the election will have the item or the election will to build a quorum. To illustrate let&#8217;s try an example. To illustrate the example let&#8217;s imagine that we are dealing with an incrementing sequence number.</p>
<p>Node A Leader -&gt; 5555<br />
Node B -&gt; 5553<br />
Node C -&gt; 5554</p>
<p>Node A sends commit on 5555 and moves to 5556<br />
Node C acks 5555</p>
<p>Node A Leader -&gt; 5556<br />
Node B -&gt; 5553<br />
Node C -&gt; 5555</p>
<p>Now the leader dies.</p>
<p>Node A dead -&gt; 5556<br />
Node B -&gt; 5553<br />
Node C -&gt; 5555</p>
<p>Nodes B/C have an election. They decide that C is the winner as it has more information than B, thus C is the new leader and sends B 5554 and 5555. The client on 5556 will receive a dropped connection and will retry 5556 with C. If both nodes A and B were dead. C would not be capable of creating a quorum. As such C would enter into read-only mode.</p>
<p>This replication model ensures consistency throughout the replica group and is a well known replication model. It has some strengths and weaknesses operationally over other models.</p>
<p>A main strength is that its fully consistent. There are not possibilities of conflicting data on different nodes (eg A accepted a write without seeing the write to C). For most business systems this is a huge gain as dealing with these rare problems often gets looked over when using models that allows them.</p>
<p>Another strength is that failovers happen very quickly with minimal impact on clients. This is especially true when you consider that the nodes internally route so the client does not need to in most cases know who the leader is. Along with this, for a group of three nodes, so long as any two are up and communicating the system is considered running and consistent.</p>
<p>The main weakness of the model is largely from the point of view that its consistent. If a quorum is unable to be built, the system will no longer accept writes and it will be readonly. This weakness also brings us to a strength of event sourcing. Keeping events locally in the application and synchronizing them later is actually a pretty easy process if you want to have eventuallly consistent behaviour with the Event Store.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/558/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/558/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=558&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/03/01/ensuring-writes-multi-node-replication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Projections 6: A use case of indexing</title>
		<link>http://goodenoughsoftware.net/2013/02/27/projections-6-a-use-case-of-indexing/</link>
		<comments>http://goodenoughsoftware.net/2013/02/27/projections-6-a-use-case-of-indexing/#comments</comments>
		<pubDate>Wed, 27 Feb 2013 14:19:18 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=553</guid>
		<description><![CDATA[As we went through in Projections 5 : Indexing. The linkTo() function is capable of emitting pointers to another stream. This can allow you to break apart streams in order to change their partitioning and to allow fast indexing. In this post we will look at a use case of how you can use this [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=553&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>As we went through in <a href="http://geteventstore.com/blog/20130218/projections-5-indexing/">Projections 5 : Indexing</a>. The linkTo() function is capable of emitting pointers to another stream. This can allow you to break apart streams in order to change their partitioning and to allow fast indexing. In this post we will look at a use case of how you can use this functionality.</p>
<p>I have seen no less than 10 custom auditing systems for nservicebus. Everyone seems to want to build out their own custom auditing system. Most involve writing out the messages to a database table then querying off the database table to show results for say a given correlationid or a certain user. Projections and the Event Store can handle this workload quite easily with two small indexing projections.</p>
<p>Let&#8217;s assume we have hooked the audit queue in nservicebus and we are writing into the Event Store all the messages. When writing we write metadata containing the correlationId and the username.</p>
<p>{<br />
correlationId : &#8220;guid&#8221;,<br />
username : &#8220;greg&#8221;<br />
}</p>
<p>We would then write our two indexing projections (correlationid and username).</p>
<p>fromAll().when({$any : function(s,e) { linkTo(e.metadata.correlationId, e); }}})</p>
<p>fromAll().when({$any : function(s,e) { linkTo(e.metadata.username, e); }}})</p>
<p>This will create a stream for every correlationId and a stream for every username. Once those are run you would then just go to <a href="http://node:port/streams/greg" rel="nofollow">http://node:port/streams/greg</a> and you would see all the messages I am doing in the system (the ui even updates on its own as I am watching it). This is a very common and simple usage. It should also be noted that while here I am basically promoting a piece of metadata, the code is in javascript and you could do pretty much anything there (maybe the modulus of the combined string of four properties of the to 42?)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/553/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/553/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=553&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/02/27/projections-6-a-use-case-of-indexing/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Projections vs rxjs vs etc</title>
		<link>http://goodenoughsoftware.net/2013/02/18/projections-vs-rxjs-vs-etc/</link>
		<comments>http://goodenoughsoftware.net/2013/02/18/projections-vs-rxjs-vs-etc/#comments</comments>
		<pubDate>Mon, 18 Feb 2013 14:17:24 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Projections]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=528</guid>
		<description><![CDATA[There was a pretty good question this morning when I checked comments on posts. &#8220;What is the difference between projections and say rxjs&#8221;. We could as easily include any of the functional reactive libraries out there (bacon.js, flapjax, elm, rx, etc). We can also start going way back and looking at predecessors like CLM Let&#8217;s [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=528&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>There was a pretty good question this morning when I checked comments on posts.</p>
<p>&#8220;What is the difference between projections and say rxjs&#8221;. <em>We could as easily include any of the functional reactive libraries out there (bacon.js, flapjax, elm, rx, etc). We can also start going way back and looking at predecessors like CLM</em></p>
<p>Let&#8217;s start with the similarities both are JavaScript. Both are functional reactive APIs (this is why they look rather similar). They if you go way back trace their lineages to the same places. All have concepts like &#8220;streams&#8221;, &#8220;events&#8221;, and &#8220;behaviours&#8221; as these are underlying concepts. There are however some differences as well.</p>
<p><em>In particular the tools are handling CEP</em></p>
<p>The largest difference is most of those tools listed are only capable of being run from now forward (for some you could write persistent adapters, we had experimented with one for rx). They are small libraries for dealing with things like events in a javascript UI. You could build up everything around something like rxjs as well (eg we could switch out our definitions for ones matching theirs).</p>
<p>When we talk about projections, the streams are persistent (and distributed). We host v8 internally and use this API as our query language over persistent streams of events. A projection is not just for running from this point forward but for running against previous history as well. This is a very powerful idea (and not a new one).</p>
<p>Projections are the query language of the Event Store. When you write a projection you can specify that you want it to run for history and stop or you want it to run for the history and continue. The Event Store will also handle you doing this in a durable, consistent, and distributed way (over terrabytes of indexed data). A projection will survive a power outage as example if configured to do so.</p>
<p>I hope this helps to clear up some of the similarities and differences between the options.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/528/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=528&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/02/18/projections-vs-rxjs-vs-etc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Projections 5: Indexing</title>
		<link>http://goodenoughsoftware.net/2013/02/18/projections-5-indexing/</link>
		<comments>http://goodenoughsoftware.net/2013/02/18/projections-5-indexing/#comments</comments>
		<pubDate>Mon, 18 Feb 2013 10:03:21 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=519</guid>
		<description><![CDATA[Now we can start getting to some of the interesting things in Projections. It was quite odd, as I was leading up to this post last night we got into a very long discussion about indexing inside the Event Store on twitter. Mike Brown noted that it would be really useful if we built lucene [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=519&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Now we can start getting to some of the interesting things in Projections. It was quite odd, as I was leading up to this post last night we got into a <strong>very long</strong> discussion about indexing inside the Event Store on twitter. Mike Brown noted that it would be really useful if we built lucene like indexing into the system so he could use the Event Store as an Audit Log that was easily searchable by things like correlationId and username. While the indexing is very different than something like lucene it is still quite possible.</p>
<p>In order to get into indexing we will need to introduce a new basic operation linkTo. linkTo works very similarly to emit except when you linkTo(&#8220;stream&#8221;, event) it does not actually write the event to the stream. It instead emits a pointer to the event to the stream. When you resolve &#8220;stream&#8221; you will see the event as if it was part of that stream but that is due to the resolution of the pointer (with the TCP API you can say whether or not you want to resolve links). Let&#8217;s try an example.</p>
<pre class="brush: jscript; title: ; notranslate">

fromAll().when({$any : function(s,e) { linkTo(e.metadata.username, e); });

</pre>
<p>What this code does is it listens to All events in the system. As they happen it will produce links into streams based upon the user (providing username is in metadata). If we were to have:</p>
<p>Chat1 -&gt; Greg Says hi<br />
Chat2 -&gt; John Says yo<br />
Chat1 -&gt; John Says Hey Greg<br />
Chat2 -&gt; Jill Says donuts!<br />
Chat3 -&gt; Jill Says anyone there?<br />
Chat3 -&gt; Greg Says sure</p>
<p>With this projection running we would be creating indexes. To start with there are three streams here (Chat1,Chat2, and Chat3) They look like: </p>
<p>Stream Chat1<br />
&#8212;&#8212;&#8212;<br />
Chat1 -&gt; Greg Says hi<br />
Chat1 -&gt; John Says Hey Greg</p>
<p>Stream Chat2<br />
&#8212;&#8212;&#8212;<br />
Chat2 -&gt; John Says yo<br />
Chat2 -&gt; Jill Says donuts!</p>
<p>Stream Chat3<br />
&#8212;&#8212;&#8212;<br />
Chat3 -&gt; Jill Says anyone there?<br />
Chat3 -&gt; Greg Says sure</p>
<p>After our index is built we will have six streams (you can build an index at anytime). It will create three additional streams Greg, John, and Jill. They would look at follows.</p>
<p>Stream Greg<br />
&#8212;&#8212;&#8212;<br />
Chat1 -&gt; Greg Says hi<br />
Chat3 -&gt; Greg Says sure</p>
<p>Stream John<br />
&#8212;&#8212;&#8212;<br />
Chat1 -&gt; John Says Hey Greg<br />
Chat2 -&gt; John Says yo</p>
<p>Stream Jill<br />
&#8212;&#8212;&#8212;<br />
Chat2 -&gt; Jill Says donuts!<br />
Chat3 -&gt; Jill Says anyone there?</p>
<p>If I were to point my browser at mydomain.com/streams/jill I would see all of Jill&#8217;s chat messages. This is generally how indexes get built up using the Event Store. One nice thing about this methodology is that as the result is a stream, you can listen to that stream like any other stream in the system to get updates for when new things are happening.</p>
<p>You will also notice if you look at an ATOMfeed that the URI to the original event does not change. As such if you are working over ATOM you likely will not pull the event down twice (it will be in cache). In our next post we will look at a quick use case for applying linkTo.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/519/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/519/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=519&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/02/18/projections-5-indexing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
		<item>
		<title>Projections 4: Event Matching</title>
		<link>http://goodenoughsoftware.net/2013/02/18/projections-4-event-matching/</link>
		<comments>http://goodenoughsoftware.net/2013/02/18/projections-4-event-matching/#comments</comments>
		<pubDate>Mon, 18 Feb 2013 00:40:54 +0000</pubDate>
		<dc:creator>gregfyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://goodenoughsoftware.net/?p=514</guid>
		<description><![CDATA[In the &#8220;intermission&#8221; post we jumped ahead quite a bit in terms of the complexity of the projection we were building. Let&#8217;s jump back into our progression of learning bits. The projections we have used so far have used a method called when(). This method allows you to match functions back to types of events. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=514&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>In the <a href="http://geteventstore.com/blog/20130217/projections-intermission/">&#8220;intermission&#8221; post</a> we jumped ahead quite a bit in terms of the complexity of the projection we were building. Let&#8217;s jump back into our progression of learning bits.</p>
<p>The projections we have used so far have used a method called when(). This method allows you to match functions back to types of events. Up until now that has been a single match but you can also use more than one.</p>
<pre class="brush: jscript; title: ; notranslate">
fromStream('test').when({
                           Event1: f1,
                           Event2: f2
                        });
</pre>
<p>This defines that every time an event of type Event1 is seen the function f1 should be called with that event and function f2 for events of type Event2. This is a very useful construct when trying to build out projections that require the ability to handle many different types of events.</p>
<p>There are also some special matches defined.</p>
<p>$any: $any will match all events to your function. This is useful for example when you want to build an index for all events. We will get into how this works later but you can imagine if I wanted to build an index based upon the user that created the event (stream per user) then the function would want to look at all events in the system.</p>
<p><em>It is important to remember that as of now $any cannot be under in conjunction with other filters.</em></p>
<p>$init: $init gets called before any other handler. The job of $init is to return the initial state that will be passed to the rest of your functions. In the intermission post this handler was used to set up initial state so the other handlers did not have to. The usage can also be seen in looking at the post from the <a href="http://geteventstore.com/blog/20130215/projections-3-using-state/">Projections 3</a></p>
<pre class="brush: jscript; title: ; notranslate">
fromStream('$stats-127.0.0.1:2113').
    when({
        &quot;$stats-collected&quot; : function(s,e) {
              var currentCpu = e.body[&quot;sys-cpu&quot;];
              if(currentCpu &gt; 40) {
                   if(!s.count) s.count = 0;
                   s.count += 1;
                   if(s.count &gt;= 3)
                        emit(&quot;heavycpu&quot;, &quot;heavyCpuFound&quot;, {&quot;level&quot; : currentCpu,
                                                           &quot;count&quot; : s.count});
              }
              else
                   s.count = 0;
         }
    });
</pre>
<p>In this projection the line if(!s.count) s.count = 0 is being used to initialize the state if its the first time into the function. This could also be implemented as</p>
<pre class="brush: jscript; title: ; notranslate">
fromStream('$stats-127.0.0.1:2113').
    when({
        &quot;$init&quot; : function(s,e) { return {&quot;count&quot;:0},
        &quot;$stats-collected&quot; : function(s,e) {
              var currentCpu = e.body[&quot;sys-cpu&quot;];
              if(currentCpu &gt; 40) {
                   s.count += 1;
                   if(s.count &gt;= 3)
                        emit(&quot;heavycpu&quot;, &quot;heavyCpuFound&quot;, {&quot;level&quot; : currentCpu,
                                                           &quot;count&quot; : s.count});
              }
              else
                   s.count = 0;
         }
    });
</pre>
<p>The two will work in the same way. In our next post we will start looking at how indexing works in the event store.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gregfyoung.wordpress.com/514/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gregfyoung.wordpress.com/514/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=goodenoughsoftware.net&#038;blog=33093581&#038;post=514&#038;subd=gregfyoung&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://goodenoughsoftware.net/2013/02/18/projections-4-event-matching/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/087629750be44831ae3dce791daeedfc?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">gregfyoung</media:title>
		</media:content>
	</item>
	</channel>
</rss>
