Commits

Anonymous committed 90ae15c

Commands and Events are not executed Async. I was using Execute instead of bus.Send.
Added some ajax loading goodness just to demonstrate how to deal with "eventual consistency"

Comments (0)

Files changed (12)

CQRSDemo.Web/CQRSDemo.Web.csproj

     <Compile Include="ViewModels\NewTweetModel.cs" />
   </ItemGroup>
   <ItemGroup>
+    <Content Include="Content\ajax-loader.gif" />
     <Content Include="Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png" />
     <Content Include="Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png" />
     <Content Include="Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png" />
       <Generator>WCF Proxy Generator</Generator>
       <LastGenOutput>Reference.cs</LastGenOutput>
     </None>
+    <Content Include="Scripts\twitterfeed.js" />
     <Content Include="Web.config" />
     <Content Include="Web.Debug.config">
       <DependentUpon>Web.config</DependentUpon>

CQRSDemo.Web/Content/Site.css

     border-radius: 4px 0 0 0;
     -webkit-border-radius: 4px 0 0 0;
     -moz-border-radius: 4px 0 0 0;
+    position: relative;
 }
 
 footer, 
 li.tweet { padding: 10px; border-bottom: 1px solid #ececec; width: 500px; background-color: #F0F8FB;  }
 li.tweet:nth-child(odd) { background-color: #CEE8FF; }
 li.tweet span.tweeter { font-weight: bold; }
-li.tweet p.message { font-size: 1.2em; margin: 0 0 .25em 0; }
+li.tweet p.message { font-size: 1.2em; margin: 0 0 .25em 0; }
+
+.loader { display: none; width: 16px;  height: 16px; position: absolute; top: 5px; left : 5px; background: url('ajax-loader.gif') no-repeat;

CQRSDemo.Web/Content/ajax-loader.gif

Added
New image

CQRSDemo.Web/Controllers/TweetController.cs

         public ActionResult Index()
         {
             var model = new TweetReader("CQRSDemo").GetLatestTweets();
-            
+
+            if (Request.IsAjaxRequest())
+            {
+                return PartialView("_TweetList", model);
+            }
+
             return View(model);
         }
 

CQRSDemo.Web/Scripts/twitterfeed.js

+var twitterfeed = {
+    config: {
+        wrapper: '#myFeature',
+        feedUrl: '/tweet/index',
+        interval: 10000
+    },
+
+    start: function (config) {
+        $.extend(twitterfeed.config, config);
+        twitterfeed.startPolling();
+    },
+
+    startPolling: function () {
+        setInterval(twitterfeed.getTweets, twitterfeed.config.interval);
+    },
+
+    getTweets: function () {
+        $(twitterfeed.config.wrapper).load(twitterfeed.config.feedUrl);
+    }
+};
+
+$(function () {
+    $('div.loader')
+        .ajaxStart(function () {
+            $(this).show();
+        })
+        .ajaxStop(function () {
+            $(this).hide();
+        });
+});

CQRSDemo.Web/Views/Shared/_Layout.cshtml

     <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
     <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
     <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
+    <script src="@Url.Content("~/Scripts/twitterfeed.js")" type="text/javascript"></script>
 </head>
 <body>
     <div class="page">
             </nav>
         </header>
         <section id="main">
+            <div class="loader"></div>
             @RenderBody()
         </section>
         <footer>
     </div>
 </body>
 </html>
+

CQRSDemo.Web/Views/Tweet/Index.cshtml

 
 <h3>Latest Tweets</h3>
 
-@Html.Partial("_TweetList")
+<div id="twitter-feed">
+    @Html.Partial("_TweetList")
+</div>
+
+<script type="text/javascript">
+    $(function () {
+        twitterfeed.start({ wrapper: $("div#twitter-feed") });
+    });
+</script>

CQRSDemo.Web/Views/Tweet/Profile.cshtml

 
 <h3>Latest tweets by @Model.Username</h3>
 
-@Html.Partial("_TweetList", Model.LatestTweets)
+<div id="twitter-feed">
+    @Html.Partial("_TweetList", Model.LatestTweets)
+</div>
 
 <p>
     <a href="@Url.Action("index")">Back to all tweets</a>
-</p>
+</p>
+
+<script type="text/javascript">
+    $(function () {
+        twitterfeed.start({ wrapper: $("div#twitter-feed"), feedUrl: '@Url.Action("profile", "tweet", new { username = Model.Username })' });
+    });
+</script>

CQRSDemo.Web/Views/Tweet/_TweetList.cshtml

             </small>
         </li>
     }
-</ul>
+</ul>
+

SimpleCQRS/SimpleCQRSDemo.CommandHandlers/PostNewTweetCommandHandler.cs

         
         public override void Handle(PostNewTweetCommand command)
         {
-            System.Console.WriteLine("Received post new tweet command. Started processing");
-            System.Threading.Thread.Sleep(2000);
             var tweet = new Tweet(command.Message, command.Who);
             domainRepository.Save(tweet); // not required if using AggregateRootCommandHandler           
-            
-            System.Console.WriteLine("Post new tweet command. Finished processing");
         }
     }
 }

SimpleCQRS/SimpleCQRSDemo.CommandService/SimpleCQRSTwitterService.svc.cs

         
         public void Execute(PostNewTweetCommand command)
         {
-            commandBus.Execute(command);
+            //commandBus.Execute(command); // waits for a response = synchronous
+            commandBus.Send(command); // sends (A)sync
         }
     }
 }

SimpleCQRS/SimpleCQRSDemo.EventHandlers/TweetCountDenormalizer.cs

     {
         public void Handle(TweetPostedEvent domainEvent)
         {
-            System.Console.WriteLine("Recieved tweet posted event. Starting processing");
-            System.Threading.Thread.Sleep(5000);
             var repo = new TweetRepository();
             repo.UpdateTweetCount(domainEvent.Who);
-            System.Console.WriteLine("Tweet posted event. Completed processing");
         }
     }
 }