|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Foo</title> |
|
<meta charset="utf-8" /> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> |
|
<style type='text/css'> |
|
body { |
|
font-family: 'Helvetica Neue'; |
|
background:#000; |
|
background-size:100%; |
|
color:#fff; |
|
margin:0; |
|
padding:.5em; |
|
} |
|
|
|
h1, h2, h3, p { |
|
margin:0; |
|
font-weight:200; |
|
} |
|
|
|
p, li { |
|
margin-bottom: .5em; |
|
} |
|
|
|
code { |
|
font-family: "Menlo", monospace; |
|
letter-spacing: 0; |
|
} |
|
|
|
em, i { |
|
font-weight: 200; |
|
} |
|
|
|
strong, b { |
|
font-weight: 400; |
|
} |
|
|
|
mark { |
|
color: orange; |
|
} |
|
|
|
a { |
|
background: orange; |
|
color:#000; |
|
text-decoration:none; |
|
} |
|
|
|
img { |
|
width:100%; |
|
} |
|
|
|
div { |
|
cursor:pointer; |
|
cursor:hand; |
|
position:absolute; |
|
top:0; |
|
left:0; |
|
} |
|
|
|
ol, ul { |
|
list-style-type: none; |
|
margin: 0.5em 0; |
|
padding: 0; |
|
} |
|
|
|
ul ul, ul ol, ol ol, ol ul { |
|
margin-left: .5em; |
|
} |
|
|
|
ol li:before, ul li:before { |
|
color: orange; |
|
} |
|
|
|
ol { |
|
counter-reset: list -1; |
|
} |
|
|
|
ol li { |
|
list-style-type: none; |
|
counter-increment: list; |
|
} |
|
|
|
ol li:before { |
|
content: counter(list, binary) " "; |
|
} |
|
|
|
ul li:before { |
|
content: "- "; |
|
} |
|
|
|
/* |
|
|
|
Sunburst-like style (c) Vasily Polovnyov <[email protected]> |
|
|
|
*/ |
|
|
|
pre code { |
|
display: block; padding: 0.5em; |
|
background: #000; color: #f8f8f8; |
|
} |
|
|
|
pre .comment, |
|
pre .template_comment, |
|
pre .javadoc { |
|
color: #aeaeae; |
|
font-style: italic; |
|
} |
|
|
|
pre .keyword, |
|
pre .ruby .function .keyword, |
|
pre .request, |
|
pre .status, |
|
pre .nginx .title { |
|
color: #E28964; |
|
} |
|
|
|
pre .function .keyword, |
|
pre .sub .keyword, |
|
pre .method, |
|
pre .list .title { |
|
color: #99CF50; |
|
} |
|
|
|
pre .string, |
|
pre .tag .value, |
|
pre .cdata, |
|
pre .filter .argument, |
|
pre .attr_selector, |
|
pre .apache .cbracket, |
|
pre .date, |
|
pre .tex .command { |
|
color: #65B042; |
|
} |
|
|
|
pre .subst { |
|
color: #DAEFA3; |
|
} |
|
|
|
pre .regexp { |
|
color: #E9C062; |
|
} |
|
|
|
pre .title, |
|
pre .sub .identifier, |
|
pre .pi, |
|
pre .tag, |
|
pre .tag .keyword, |
|
pre .decorator, |
|
pre .shebang, |
|
pre .prompt { |
|
color: #89BDFF; |
|
} |
|
|
|
pre .class .title, |
|
pre .haskell .type, |
|
pre .smalltalk .class, |
|
pre .javadoctag, |
|
pre .yardoctag, |
|
pre .phpdoc { |
|
text-decoration: underline; |
|
} |
|
|
|
pre .symbol, |
|
pre .ruby .symbol .string, |
|
pre .number { |
|
color: #3387CC; |
|
} |
|
|
|
pre .params, |
|
pre .variable, |
|
pre .clojure .attribute { |
|
color: #3E87E3; |
|
} |
|
|
|
pre .css .tag, |
|
pre .rules .property, |
|
pre .pseudo, |
|
pre .tex .special { |
|
color: #CDA869; |
|
} |
|
|
|
pre .css .class { |
|
color: #9B703F; |
|
} |
|
|
|
pre .rules .keyword { |
|
color: #C5AF75; |
|
} |
|
|
|
pre .rules .value { |
|
color: #CF6A4C; |
|
} |
|
|
|
pre .css .id { |
|
color: #8B98AB; |
|
} |
|
|
|
pre .annotation, |
|
pre .apache .sqbracket, |
|
pre .nginx .built_in { |
|
color: #9B859D; |
|
} |
|
|
|
pre .preprocessor { |
|
color: #8996A8; |
|
} |
|
|
|
pre .hexcolor, |
|
pre .css .value .number { |
|
color: #DD7B3B; |
|
} |
|
|
|
pre .css .function { |
|
color: #DAD085; |
|
} |
|
|
|
pre .diff .header, |
|
pre .chunk, |
|
pre .tex .formula { |
|
background-color: #0E2231; |
|
color: #F8F8F8; |
|
font-style: italic; |
|
} |
|
|
|
pre .diff .change { |
|
background-color: #4A410D; |
|
color: #F8F8F8; |
|
} |
|
|
|
pre .addition { |
|
background-color: #253B22; |
|
color: #F8F8F8; |
|
} |
|
|
|
pre .deletion { |
|
background-color: #420E09; |
|
color: #F8F8F8; |
|
} |
|
|
|
pre .coffeescript .javascript, |
|
pre .javascript .xml, |
|
pre .tex .formula, |
|
pre .xml .javascript, |
|
pre .xml .vbscript, |
|
pre .xml .css, |
|
pre .xml .cdata { |
|
opacity: 0.5; |
|
} |
|
|
|
</style> |
|
<script type='text/javascript'> |
|
window.onload = function() { |
|
var s = document.getElementsByTagName('div'), cur = 0; |
|
if (!s) return; |
|
function go(n) { |
|
cur = n; |
|
var i = 1e3, e = s[n]; |
|
for (var k = 0; k < s.length; k++) s[k].style.display = 'none'; |
|
e.style.display = 'inline-block'; |
|
e.style.fontSize = i + 'px'; |
|
if (e.firstChild.nodeName === 'IMG') { |
|
document.body.style.backgroundImage = 'url(' + e.firstChild.src + ')'; |
|
e.firstChild.style.display = 'none'; |
|
} else { |
|
document.body.style.backgroundImage = ''; |
|
document.body.style.backgroundColor = e.style.backgroundColor; |
|
} |
|
while ( |
|
e.offsetWidth > window.innerWidth || |
|
e.offsetHeight > window.innerHeight) { |
|
e.style.fontSize = (i -= 10) + 'px'; |
|
if (i < 0) break; |
|
} |
|
e.style.marginTop = ((window.innerHeight - e.offsetHeight) / 2) + 'px'; |
|
if (window.location.hash !== n) window.location.hash = n; |
|
document.title = e.textContent || e.innerText; |
|
} |
|
document.onclick = function() { |
|
go(++cur % (s.length)); |
|
}; |
|
document.onkeydown = function(e) { |
|
(e.which === 39) && go(Math.min(s.length - 1, ++cur)); |
|
(e.which === 37) && go(Math.max(0, --cur)); |
|
}; |
|
function parse_hash() { |
|
return Math.max(Math.min( |
|
s.length - 1, |
|
parseInt(window.location.hash.substring(1), 10)), 0); |
|
} |
|
if (window.location.hash) cur = parse_hash() || cur; |
|
window.onhashchange = function() { |
|
var c = parse_hash(); |
|
if (c !== cur) go(c); |
|
}; |
|
|
|
go(cur); |
|
}; |
|
</script></head><body> |
|
<div><h1>Azure Service Bus Correlation</h1> |
|
</div> |
|
<div><p>Correlation? WTF?</p> |
|
</div> |
|
<div><blockquote> |
|
<p>"I haz many fings to do that must work togeva."</p> |
|
</blockquote> |
|
</div> |
|
<div><h2>It's all about <code>SessionId</code></h2> |
|
<pre><code class="lang-javascript">var msg = new BrokeredMessage()<span class="comment">;</span> |
|
msg<span class="preprocessor">.SessionId</span> = <span class="string">"kitteh!"</span><span class="comment">;</span></code></pre> |
|
</div> |
|
<div><h1>So what does that mean?</h1> |
|
</div> |
|
<div><p>Azure promises:</p> |
|
<ul> |
|
<li>FIFO.</li> |
|
<li>Consistent session state</li> |
|
<li>Receivers can still die.</li> |
|
</ul> |
|
</div> |
|
<div><p>What this means for us:</p> |
|
<ul> |
|
<li>"Jobs" (e.g. <em>"scrape"</em>) tracked as whole.</li> |
|
<li>Easier reporting & management.</li> |
|
<li>Developer sanity.</li> |
|
</ul> |
|
</div> |
|
<div><h2>Key points</h2> |
|
<ul> |
|
<li>Queues <em>must</em> require Sessions.</li> |
|
<li><code>msg.SessionId</code> <em>must</em> be set on Session Queues.</li> |
|
<li>Don't do either and world ends.</li> |
|
<li>Do none and no sessions :)</li> |
|
</ul> |
|
</div> |
|
<div><pre><code class="lang-csharp"><span class="keyword">var</span> qd = <span class="keyword">new</span> QueueDescription(name) |
|
{ |
|
<span class="comment">/* Create Session Queue */</span> |
|
RequiresSession = <span class="keyword">true</span> |
|
};</code></pre> |
|
</div> |
|
<div><p>Morph handles transparently in <a href="https://github.com/MoBank/MoPowered.Morph/blob/add-sessions-api/src/MoPowered.Morph/Processing/ProcessingService.cs">ProcessingService</a>:</p> |
|
<pre><code class="lang-csharp">var message = <span class="built_in">x</span><span class="preprocessor">.ToMessage</span>()<span class="comment">;</span> |
|
message<span class="preprocessor">.SessionId</span> = sessionId<span class="comment">;</span> |
|
return Client<span class="preprocessor">.SendAsync</span>(message)<span class="comment">;</span></code></pre> |
|
</div> |
|
<div><p>Any <code>Job</code>'s queued or spawned will have their Session ID set for you.</p> |
|
</div> |
|
<div><p>Questions?</p> |
|
</div> |
|
<div><p><img src="http://static.fjcdn.com/gifs/Dancing_452c8b_395735.gif" alt="Kitteh"></p> |
|
</div> |