Channels ▼

Arnon Rotem-Gal-Oz

Dr. Dobb's Bloggers

Twitterjecting

May 07, 2009

Apropos the Blogjecting  Watchdog pattern,  In addition to blogging I recently added to our system the ability to twitter. I am using Tweet# from DimeBrain (thanks Mark Nijhof for the tip via twitter).

Tweet# makes using tweeter really simple (I included the code below in case you find it useful).

The tweeter sender is part of a PostOffice service (I thought that it would be problematic to present it as SpamServer which was its original name :) ) . A few points about our design in general that are interesting in this regards are

  • The PostOffice is a “Server” type service – we have 3 types of services: server which has one instance per node, channel which has multiple instances per node and algorithmic which has one instance per core
  • The PostOffice implements a pattern I call “Legacy Bridge” – which is basically an SOA version of an adapter+facade in OO terms. The post office supports the events (over WCF) mechanism we have in our system from one side  and connects to external systems (SMS, coupons and twitter) on the other. The PostOffice, basically contains an Edge Component which accepts the requests and funnels them to *Sender classes that interact with the external systems.
  • from contract design perspective – The events I added into the system are StatusEvent and AdminStatusEvent (and not TwitterEvent and DirectMessageEvent). this is better, in my opinion, as it carries the intent of what I want to achieve. It also means that if I choose to change technology or use multiple destinations the events will stay meaningful. For instance, the AdminStatusEvent will be used by our monitoring system to send a notification if the system crashes. I’ll probably want that as an SMS, maybe even a phone call as well as a twit (so the AdminStatusEvent will have a severity to designate how it should be handled)
<span style="color: #606060">   1:</span> <span style="color: #0000ff">using</span> System;
<span style="color: #606060">   2:</span> <span style="color: #0000ff">using</span> System.Collections.Generic;
<span style="color: #606060">   3:</span> <span style="color: #0000ff">using</span> System.Linq;
<span style="color: #606060">   4:</span> <span style="color: #0000ff">using</span> System.Text;
<span style="color: #606060">   5:</span> <span style="color: #0000ff">using</span> Dimebrain.TweetSharp.Fluent;
<span style="color: #606060">   6:</span>  
<span style="color: #606060">   7:</span> <span style="color: #0000ff">namespace</span> xsights.Apps.PostOffice.Server.Twitter
<span style="color: #606060">   8:</span> {
<span style="color: #606060">   9:</span>     <span style="color: #0000ff">class</span> TwitterSender
<span style="color: #606060">  10:</span>     {
<span style="color: #606060">  11:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">string</span> account;
<span style="color: #606060">  12:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">string</span> password;
<span style="color: #606060">  13:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">string</span> admin;
<span style="color: #606060">  14:</span>  
<span style="color: #606060">  15:</span>         <span style="color: #0000ff">public</span> TwitterSender(<span style="color: #0000ff">string</span> tweetAccount, <span style="color: #0000ff">string</span> twitterPassword,<span style="color: #0000ff">string</span> adminAccount)
<span style="color: #606060">  16:</span>         {
<span style="color: #606060">  17:</span>             account = tweetAccount;
<span style="color: #606060">  18:</span>             password = twitterPassword;
<span style="color: #606060">  19:</span>             admin = adminAccount;
<span style="color: #606060">  20:</span>         }
<span style="color: #606060">  21:</span>         <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Update(<span style="color: #0000ff">string</span> msg)
<span style="color: #606060">  22:</span>         {
<span style="color: #606060">  23:</span>              <span style="color: #0000ff">foreach</span> (var tweet <span style="color: #0000ff">in</span> BreakToTwitts(msg))
<span style="color: #606060">  24:</span>             {
<span style="color: #606060">  25:</span>                 var update =
<span style="color: #606060">  26:</span>                     FluentTwitter.CreateRequest().AuthenticateAs(account, password).Statuses().Update(tweet).AsJson();
<span style="color: #606060">  27:</span>  
<span style="color: #606060">  28:</span>                 update.Request();
<span style="color: #606060">  29:</span>             }
<span style="color: #606060">  30:</span>         }
<span style="color: #606060">  31:</span>  
<span style="color: #606060">  32:</span>         <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> SendAdminMessage(<span style="color: #0000ff">string</span> msg)
<span style="color: #606060">  33:</span>         {
<span style="color: #606060">  34:</span>             <span style="color: #0000ff">foreach</span> (var twit  <span style="color: #0000ff">in</span> BreakToTwitts(msg))
<span style="color: #606060">  35:</span>             {
<span style="color: #606060">  36:</span>                 var dm =
<span style="color: #606060">  37:</span>                 FluentTwitter.CreateRequest().AuthenticateAs(account, password).DirectMessages().Send(admin, twit).AsJson();
<span style="color: #606060">  38:</span>  
<span style="color: #606060">  39:</span>                 Retry(2,dm.Request,<span style="color: #0000ff">false</span>);
<span style="color: #606060">  40:</span>             }   
<span style="color: #606060">  41:</span>             
<span style="color: #606060">  42:</span>         }
<span style="color: #606060">  43:</span>  
<span style="color: #606060">  44:</span>         <span style="color: #0000ff">private</span> IList<<span style="color: #0000ff">string</span>> BreakToTwitts(<span style="color: #0000ff">string</span> originalString)
<span style="color: #606060">  45:</span>         {
<span style="color: #606060">  46:</span>             var list = <span style="color: #0000ff">new</span> List<<span style="color: #0000ff">string</span>>();
<span style="color: #606060">  47:</span>             <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i < originalString.Length; i += 140)
<span style="color: #606060">  48:</span>             {
<span style="color: #606060">  49:</span>                 var len = 140;
<span style="color: #606060">  50:</span>                 <span style="color: #0000ff">if</span> (originalString.Length - i < 140) len = originalString.Length - i;
<span style="color: #606060">  51:</span>                 list.Add(originalString.Substring(i, len));
<span style="color: #606060">  52:</span>             }
<span style="color: #606060">  53:</span>             <span style="color: #0000ff">return</span> list;
<span style="color: #606060">  54:</span>         }
<span style="color: #606060">  55:</span>  
<span style="color: #606060">  56:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> Retry(<span style="color: #0000ff">int</span> retries, Func<<span style="color: #0000ff">string</span>> call,<span style="color: #0000ff">bool</span> shouldThrow)
<span style="color: #606060">  57:</span>         {
<span style="color: #606060">  58:</span>            
<span style="color: #606060">  59:</span>             <span style="color: #0000ff">try</span>
<span style="color: #606060">  60:</span>             {
<span style="color: #606060">  61:</span>                 call();
<span style="color: #606060">  62:</span>             }
<span style="color: #606060">  63:</span>             <span style="color: #0000ff">catch</span> (Exception ex)
<span style="color: #606060">  64:</span>             {
<span style="color: #606060">  65:</span>  
<span style="color: #606060">  66:</span>                 <span style="color: #0000ff">if</span> (retries > 0)
<span style="color: #606060">  67:</span>                     Retry(--retries, call,shouldThrow);
<span style="color: #606060">  68:</span>                 <span style="color: #0000ff">else</span>
<span style="color: #606060">  69:</span>                 {
<span style="color: #606060">  70:</span>                     <span style="color: #0000ff">if</span> (shouldThrow)
<span style="color: #606060">  71:</span>                         <span style="color: #0000ff">throw</span>;
<span style="color: #606060">  72:</span>                 }
<span style="color: #606060">  73:</span>             }
<span style="color: #606060">  74:</span>           }
<span style="color: #606060">  75:</span>           
<span style="color: #606060">  76:</span>         }
<span style="color: #606060">  77:</span>     }
<span style="color: #606060">  78:</span>  
<span style="color: #606060">  79:</span> }

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video