<?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/"
	>

<channel>
	<title>Here comes the Sun &#187; project</title>
	<atom:link href="http://sunng.info/blog/tag/project/feed/" rel="self" type="application/rss+xml" />
	<link>http://sunng.info/blog</link>
	<description>Homemade Clojure Geek</description>
	<lastBuildDate>Fri, 11 May 2012 02:24:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Slacker 0.8.0</title>
		<link>http://sunng.info/blog/2012/04/slacker-0-8-0/</link>
		<comments>http://sunng.info/blog/2012/04/slacker-0-8-0/#comments</comments>
		<pubDate>Sun, 22 Apr 2012 06:05:01 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[slacker]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1227</guid>
		<description><![CDATA[A new release 0.8.0 of slacker has been pushed to clojars. Let&#8217;s go through the changes in this version. Clojure 1.3 compatible Slacker finally landed on clojure 1.3. It takes advantages of performance in 1.3. Also, you can use 1.3 &#8230; <a href="http://sunng.info/blog/2012/04/slacker-0-8-0/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A new release 0.8.0 of <a href="https://github.com/sunng87/slacker">slacker</a> has been pushed to clojars. Let&#8217;s go through the changes in this version.</p>
<h3>Clojure 1.3 compatible</h3>
<p>Slacker finally landed on clojure 1.3. It takes advantages of performance in 1.3. Also, you can use 1.3 API in slacker. For example, a timeout argument is supported in deref, which is useful when dealing with promise returned by slacker&#8217;s asynchronous call.</p>
<h3>Performance Boost</h3>
<p>The performance enhancement is on the highest priority in this release.  I have migrated the NIO infrastructure to a new library called <a href="https://github.com/sunng87/link">link</a>. Now slacker 0.8.0 is at least <strong>8x</strong> faster than previous release. There is significant improvement both on per-request latency and overall throughput. And the server thread model is optimized for data-intensive tasks. Heavy IO tasks in hosted functions won&#8217;t block the whole server. </p>
<h3>slacker as a ring app</h3>
<p>Instead of running default transportation, slacker now can be configured as a ring app and deployed on any ring adapter.</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>use 'slacker<span style="color: #66cc66;">.</span>server<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>use 'ring<span style="color: #66cc66;">.</span>adapter<span style="color: #66cc66;">.</span>jetty<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #66cc66;">&#40;</span>run<span style="color: #66cc66;">-</span>jetty <span style="color: #66cc66;">&#40;</span>slacker<span style="color: #66cc66;">-</span>ring<span style="color: #66cc66;">-</span>app <span style="color: #66cc66;">&#40;</span>the<span style="color: #66cc66;">-</span><span style="color: #b1b100;">ns</span> 'slacker<span style="color: #66cc66;">.</span>example<span style="color: #66cc66;">.</span>api<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>:<span style="color: #555;">port</span> <span style="color: #cc66cc;">8080</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>This will expose the name space <em>slacker.example.api</em> with HTTP. Functions could be called with following URL pattern:</p>
<p>http://localhost:8080/&lt;namespace&gt;/&lt;function&gt;.&lt;content-type&gt;</p>
<p>For instance: http://localhost:8080/slacker.example.api/timestamp.json</p>
<h3>defn-remote</h3>
<p>There is a minor update for the defn-remote macro. </p>
<p>In 0.7.0, you have to specify remote namespace with an option:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>defn<span style="color: #66cc66;">-</span>remote sc timestamp :<span style="color: #555;">remote</span><span style="color: #66cc66;">-</span><span style="color: #b1b100;">ns</span> <span style="color: #ff0000;">&quot;slacker.example.api&quot;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>In 0.8.0, it&#8217;s more convenience:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>defn<span style="color: #66cc66;">-</span>remote sc slacker<span style="color: #66cc66;">.</span>example<span style="color: #66cc66;">.</span>api<span style="color: #66cc66;">/</span>timestamp<span style="color: #66cc66;">&#41;</span></div></div>
<p>To keep the core library compact, in 0.8.0, the cluster support has been moved to a standalone project <a href="https://github.com/sunng87/slacker-cluster">slacker-cluster</a>. </p>
<p>All above summarized my recent work in the slacker project. If you have any question with this library, feel free to drop me an email sunng@about.me .</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/04/slacker-0-8-0/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Slacker performance enhanced</title>
		<link>http://sunng.info/blog/2012/04/slacker-performance-enhanced/</link>
		<comments>http://sunng.info/blog/2012/04/slacker-performance-enhanced/#comments</comments>
		<pubDate>Mon, 02 Apr 2012 07:04:21 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[手艺]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[netty]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[slacker]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1216</guid>
		<description><![CDATA[In the slacker framework, performance issue becomes more and more critical as the basic features are almost completed. As mentioned in cnclojure meetup, I will focus on the performance enhancement in next release. Now I have worked out a testable &#8230; <a href="http://sunng.info/blog/2012/04/slacker-performance-enhanced/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the slacker framework, performance issue becomes more and more critical as the basic features are almost completed. As mentioned in cnclojure meetup, I will focus on the performance enhancement in next release. </p>
<p>Now I have worked out a testable version. The new slacker core has been moved to a new NIO library, <a href="https://github.com/sunng87/link" target="_blank">link</a>. Compared with aleph, link is a thin wrapper of Netty. It takes some nice features from aleph (gloss codec dsl, elegant API), and drops the heavy abstraction, lamina. The new slacker client runs on a real nonblocking connection. Connection pooling is no longer needed.</p>
<p>I have some performance benchmark to visualize the improvement. The test was made on my laptop (Intel(R) Core(TM)2 Duo CPU     T5870  @ 2.00GHz). It ran 400,000 calls with 40 threads on a local slacker server.</p>
<p>slacker 0.7.0 (clojure 1.2, aleph 0.2.0): <strong>614005.059259msecs</strong><br />
slacker 0.7.1-SNAPSHOT (clojure 1.3, aleph 0.2.1-beta2): <strong>409110.909142msecs</strong><br />
slacker 0.8.0-SNAPSHOT (clojure 1.3, link 0.2.0-SNAPSHOT): <strong>42468.401522msecs</strong></p>
<p><img src="http://i.imgur.com/gMtdo.jpg" alt="tps chart" /></p>
<p>Check out the new slacker on the <a href="https://github.com/sunng87/slacker/tree/0.8-dev" target="_blank">0.8-dev</a> branch. </p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/04/slacker-performance-enhanced/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Python&#8217;s Valentines Day Gift to Clojure</title>
		<link>http://sunng.info/blog/2012/02/pythons-valentines-day-gift-to-clojure/</link>
		<comments>http://sunng.info/blog/2012/02/pythons-valentines-day-gift-to-clojure/#comments</comments>
		<pubDate>Tue, 14 Feb 2012 12:49:41 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1173</guid>
		<description><![CDATA[Inspired by meh&#8217;s Ruby-Clj module, I created the python equivalent &#8220;pyclj&#8221; last weekend. Pyclj is a clojure literal reader/writer for python. It enables data exchange between python and clojure, in a clojure-native way. It&#8217;s Valentines Day today, I&#8217;d like to &#8230; <a href="http://sunng.info/blog/2012/02/pythons-valentines-day-gift-to-clojure/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Inspired by meh&#8217;s <a href="https://github.com/meh/ruby-clj" target="_blank">Ruby-Clj</a> module, I created the python equivalent &#8220;pyclj&#8221; last weekend. Pyclj is a clojure literal reader/writer for python. It enables data exchange between python and clojure, in a clojure-native way. It&#8217;s Valentines Day today, I&#8217;d like to release it as the gift of python to clojure <img src='http://sunng.info/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The API is very simple. It&#8217;s all like python&#8217;s data modules (json, pickle)</p>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> clj<br />
<br />
clj.<span style="color: black;">loads</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;[1 2 3]&quot;</span><span style="color: black;">&#41;</span><br />
clj.<span style="color: black;">dumps</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;a&quot;</span>:<span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;b&quot;</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></div></div>
<p>Clojure types are mapping to python data structures :</p>
<table border="1">
<tbody>
<tr>
<th>Clojure</th>
<th>Python</th>
</tr>
<tr>
<td>list</td>
<td>list</td>
</tr>
<tr>
<td>vector</td>
<td>list</td>
</tr>
<tr>
<td>set</td>
<td>set</td>
</tr>
<tr>
<td>map</td>
<td>dict</td>
</tr>
<tr>
<td>nil</td>
<td>None</td>
</tr>
<tr>
<td>string</td>
<td>string</td>
</tr>
<tr>
<td>int</td>
<td>int</td>
</tr>
<tr>
<td>float</td>
<td>float</td>
</tr>
<tr>
<td>boolean</td>
<td>boolean</td>
</tr>
<tr>
<td>char</td>
<td>string</td>
</tr>
<tr>
<td>keyword</td>
<td>string</td>
</tr>
</tbody>
</table>
<p>But how we win clojure&#8217;s heart from ruby? </p>
<p>We are faster.</p>
<p>Considering clojure literal below:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">2</span> <span style="color: #cc66cc;">3</span> true false nil <span style="color: #66cc66;">&#123;</span>:<span style="color: #555;">a</span> <span style="color: #cc66cc;">21.3</span> :<span style="color: #555;">b</span> <span style="color: #cc66cc;">43.2</span><span style="color: #66cc66;">&#125;</span> <span style="color: #ff0000;">&quot;Hello&quot;</span><span style="color: #66cc66;">&#93;</span></div></div>
<p>Comparing ruby-clj(0.0.4.5, ruby 1.9.3p0) and pyclj(0.1.3 python 2.7.2):</p>
<div class="codecolorer-container ruby twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'clj'</span><br />
<br />
s = <span style="color:#996600;">&quot;[1 2 3 true false nil {:a 21.3 :b 43.2} <span style="color:#000099;">\&quot;</span>Hello<span style="color:#000099;">\&quot;</span>]&quot;</span><br />
<br />
t1 = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<span style="color:#9966CC; font-weight:bold;">for</span> i <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#006666;">0</span>...<span style="color:#006666;">10000</span><br />
&nbsp; Clojure.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>s<span style="color:#006600; font-weight:bold;">&#41;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">-</span>t1</div></div>
<div class="codecolorer-container python twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> clj<br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span><br />
<br />
s <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;[1 2 3 true false nil {:a 21.3 :b 43.2} <span style="color: #000099; font-weight: bold;">\&quot;</span>Hello<span style="color: #000099; font-weight: bold;">\&quot;</span>]&quot;</span><br />
<br />
t1 <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10000</span><span style="color: black;">&#41;</span>:<br />
&nbsp; clj.<span style="color: black;">loads</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>-t1</div></div>
<p>The result:<br />
ruby: <del datetime="2012-02-16T05:30:18+00:00"><strong>13.451157809</strong></del><br />
python: <del datetime="2012-02-16T05:30:18+00:00"><strong>0.712423086166</strong></del><br />
Edit 20120216 13:30<br />
ruby-clj 0.0.5.3 has resolved the performance issue <img src='http://sunng.info/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
The new result ruby-clj/0.0.5.4 Vs pyclj0.1.4 (on my laptop):<br />
ruby-clj: 2.044872364<br />
pyclj: 1.19659209251</p>
<p>The project is hosted on <a href="https://github.com/sunng87/pyclj" target="_blank">github</a>. Feel free to join the development and enhance it.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/02/pythons-valentines-day-gift-to-clojure/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>HeatCanvas performance enhanced</title>
		<link>http://sunng.info/blog/2012/02/heatcanvas-performance-enhanced/</link>
		<comments>http://sunng.info/blog/2012/02/heatcanvas-performance-enhanced/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 14:11:29 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[heatcanvas]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1169</guid>
		<description><![CDATA[时隔半年日日沉浸在clojure世界里的时候，多亏了github上Daniel Azuma的提示，现在HeatCanvas通过Image Data数组来绘制图像。过去由于不太熟悉Canvas API，我用的是fillRect来填充1像素大小的区域，模拟像素的渲染。但是这种方式导致浏览器渲染的效率非常低。 ImageDataArray允许用户开辟一个固定大小的buffer，并设置每一像素的像素值，然后一次性地渲染到canvas上。详情可以参考这里：Pixel manipulation with canvas 这次性能的提升基本没有影响API，唯一的区别是如果原先自定义了value-color的映射函数的话，现在不再接受hsl的css字符串了，新的API需要你返回一个四个元素的数组，分别代表h, s, l, a，值域[0-1]。 感谢关注HeatCanvas的朋友。]]></description>
			<content:encoded><![CDATA[<p><img src="http://i.imgur.com/6vkpo.png" alt="heatcanvas" /></p>
<p>时隔半年日日沉浸在clojure世界里的时候，多亏了github上<a href="https://github.com/dazuma">Daniel Azuma</a>的提示，现在HeatCanvas通过Image Data数组来绘制图像。过去由于不太熟悉Canvas API，我用的是fillRect来填充1像素大小的区域，模拟像素的渲染。但是这种方式导致浏览器渲染的效率非常低。</p>
<p>ImageDataArray允许用户开辟一个固定大小的buffer，并设置每一像素的像素值，然后一次性地渲染到canvas上。详情可以参考这里：<a href="https://developer.mozilla.org/En/HTML/Canvas/Pixel_manipulation_with_canvas" target="_blank">Pixel manipulation with canvas</a></p>
<p>这次性能的提升基本没有影响API，唯一的区别是如果原先自定义了value-color的映射函数的话，现在不再接受hsl的css字符串了，新的API需要你返回一个四个元素的数组，分别代表h, s, l, a，值域[0-1]。</p>
<p>感谢关注HeatCanvas的朋友。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/02/heatcanvas-performance-enhanced/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Slacker Cluster</title>
		<link>http://sunng.info/blog/2012/02/slacker-cluster/</link>
		<comments>http://sunng.info/blog/2012/02/slacker-cluster/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 13:08:19 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[slacker]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1161</guid>
		<description><![CDATA[Cluster support is one of the big thing in slacker 0.6.x. Cluster enables high-availability and load balancing on slacker client and server. Slacker cluster has a centralized registry, a zookeeper node, stores information of all the namespaces and servers instances &#8230; <a href="http://sunng.info/blog/2012/02/slacker-cluster/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Cluster support is one of the big thing in slacker 0.6.x. Cluster enables high-availability and load balancing on slacker client and server. </p>
<p>Slacker cluster has a centralized registry, a zookeeper node, stores information of all the namespaces and servers instances in the cluster. Once a client declared remote functions, by calling `defn-remote` or `use-remote`, it reads all available servers offering that namespace from the registry and create connection to each of them. We the user issues a request, the client randomly pick up a connection from them. So the load is eventually distributed to every instance of slacker servers. And thanks to zookeeper&#8217;s notification feature, the client watches certain znode. It will be notified when 1. a connected server goes offline 2. a new server serving required namespace added into the cluster. Thus you don&#8217;t have to change client code or restart client when server changes. </p>
<p>To start a slacker server and add it to a cluster, you have to provide cluster information using the new <strong>:cluster</strong> option:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>start<span style="color: #66cc66;">-</span>slacker<span style="color: #66cc66;">-</span>server <span style="color: #66cc66;">&#40;</span>the<span style="color: #66cc66;">-</span><span style="color: #b1b100;">ns</span> 'slacker<span style="color: #66cc66;">.</span>example<span style="color: #66cc66;">.</span>api<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;">2104</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :<span style="color: #555;">cluster</span> <span style="color: #66cc66;">&#123;</span>:<span style="color: #555;">zk</span> <span style="color: #ff0000;">&quot;127.0.0.1:2181&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :<span style="color: #555;">name</span> <span style="color: #ff0000;">&quot;example-cluster&quot;</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span></div></div>
<ul>
<li>:zk is the address of zookeeper node</li>
<li>:name is a znode qualified string, to identify the cluster</li>
</ul>
<p>On the client side, it&#8217;s important to use APIs from `slacker.client.cluster` instead of `slacker.client`:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>use 'slacker<span style="color: #66cc66;">.</span>client<span style="color: #66cc66;">.</span>cluster<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #808080; font-style: italic;">;; arguments: cluster-name, zookeeper address</span><br />
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">def</span> sc <span style="color: #66cc66;">&#40;</span>clustered<span style="color: #66cc66;">-</span>slackerc <span style="color: #ff0000;">&quot;example-cluster&quot;</span> <span style="color: #ff0000;">&quot;127.0.0.1:2181&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>use<span style="color: #66cc66;">-</span>remote 'sc 'slacker<span style="color: #66cc66;">.</span>example<span style="color: #66cc66;">.</span>api<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">;; call the function from a random server</span><br />
<span style="color: #66cc66;">&#40;</span>timestamp<span style="color: #66cc66;">&#41;</span></div></div>
<p>If all servers provide &#8216;slacker.example.api go offline, slacker client will raise a &#8220;not-found&#8221; exception.</p>
<p>Slacker cluster is also designed with simple and clean in mind. You don&#8217;t have to change you business code to make it remote or cluster. Everything is transparent and non-invasive. Enjoy it.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/02/slacker-cluster/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Slacker 0.6: Exposing multiple namespaces</title>
		<link>http://sunng.info/blog/2012/02/slacker-0-6-exposing-multiple-namespaces/</link>
		<comments>http://sunng.info/blog/2012/02/slacker-0-6-exposing-multiple-namespaces/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 14:14:34 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[slacker]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1154</guid>
		<description><![CDATA[After 98 commits in about one month, I&#8217;m glad to announce [slacker "0.6.1"]. One thing in slacker 0.6.x is you can expose multiple namespaces from a single server. Suppose you have two namespaces `redday.stats` and `redday.api`, both contains functions you &#8230; <a href="http://sunng.info/blog/2012/02/slacker-0-6-exposing-multiple-namespaces/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After <a href="https://github.com/sunng87/slacker/compare/8b4abdb62a...3e41e035b9" title="Changes">98 commits</a> in about one month, I&#8217;m glad to announce [slacker "0.6.1"].</p>
<p>One thing in slacker 0.6.x is you can expose multiple namespaces from a single server.</p>
<p>Suppose you have two namespaces `redday.stats` and `redday.api`, both contains functions you want to expose.</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #66cc66;">&#40;</span>start<span style="color: #66cc66;">-</span>slacker<span style="color: #66cc66;">-</span>server <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#40;</span>the<span style="color: #66cc66;">-</span><span style="color: #b1b100;">ns</span> 'redday<span style="color: #66cc66;">.</span>stats<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>the<span style="color: #66cc66;">-</span><span style="color: #b1b100;">ns</span> 'redday<span style="color: #66cc66;">.</span>api<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;">6565</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>This will expose `redday.stats` and `redday.api` on port 6565.</p>
<p>On the client side, we have a new `use-remote` behaviors like clojure&#8217;s use. Instead of local one, it imports functions from a remote namespace to your current namespace.</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>use 'slacker<span style="color: #66cc66;">.</span>client<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #808080; font-style: italic;">;; create a slacker client</span><br />
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">def</span> scp <span style="color: #66cc66;">&#40;</span>slackerc <span style="color: #ff0000;">&quot;127.0.0.1:6565&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <br />
<br />
<span style="color: #66cc66;">&#40;</span>use<span style="color: #66cc66;">-</span>remote 'scp 'redday<span style="color: #66cc66;">.</span>api<span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">;; caution, use the symbol of 'scp here </span><br />
<span style="color: #66cc66;">&#40;</span>use<span style="color: #66cc66;">-</span>remote 'scp 'redday<span style="color: #66cc66;">.</span>stats<span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">;;top-titles is a function in redday.api</span><br />
<span style="color: #808080; font-style: italic;">;;now you can use the remote function transparently</span><br />
<span style="color: #66cc66;">&#40;</span>top<span style="color: #66cc66;">-</span>titles <span style="color: #ff0000;">&quot;programming&quot;</span><span style="color: #66cc66;">&#41;</span> <br />
<br />
<span style="color: #808080; font-style: italic;">;;check function metadata you can find more slacker properties</span><br />
<span style="color: #66cc66;">&#40;</span>meta top<span style="color: #66cc66;">-</span>titles<span style="color: #66cc66;">&#41;</span></div></div>
<p>If you need to configure callback to a particular function, you can still use `defn-remote` to specify the callback function. In slacker 0.6.0, a `:remote-ns` is required when you define such a remote function.</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>defn<span style="color: #66cc66;">-</span>remote top<span style="color: #66cc66;">-</span>titles :<span style="color: #555;">remote</span><span style="color: #66cc66;">-</span><span style="color: #b1b100;">ns</span> <span style="color: #ff0000;">&quot;redday.api&quot;</span> :<span style="color: #555;">callback</span> #<span style="color: #66cc66;">&#40;</span>println <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>The complete code example (both server and client) can be found <a href="https://bitbucket.org/sunng/slacker-demo/overview">here</a>. </p>
<p>In next post, I will explain another big new feature of 0.6.x, cluster support.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/02/slacker-0-6-exposing-multiple-namespaces/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ClojureDocs Android App</title>
		<link>http://sunng.info/blog/2012/01/clojuredocs-android-app/</link>
		<comments>http://sunng.info/blog/2012/01/clojuredocs-android-app/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 08:34:56 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[project]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1145</guid>
		<description><![CDATA[利用春节的假期写了一个Android应用，可以在ClojureDocs.org上搜索clojure API，浏览文档、源代码和社区贡献的代码实例。ClojureDocs在我学习Clojure的过程中起了很大的作用，所以我想这个网站应该对很多人有用。 无暇去学习Android平台上繁琐的知识，不过好在有Phonegap这样的框架，可以把网页应用转化为本地应用，并且提供访问本地设备的API。通过Phonegap开发的程序还可以直接移植到iphone平台上。ClojureDocs Android就是运行在Phonegap中。 首页： 搜索界面 API函数界面 你可以从github获得代码和签名过的apk：https://github.com/sunng87/clojuredocs-android Known Issue，phonegap程序在屏幕旋转时会崩溃，已经在2.3和3.2上重现，目前还不清楚具体的原因。(Edit 20120127: Fixed in 1.0.4) 欢迎任何的pull request。]]></description>
			<content:encoded><![CDATA[<p>利用春节的假期写了一个Android应用，可以在<a href="http://clojuredocs.org" target="_blank">ClojureDocs.org</a>上搜索clojure API，浏览文档、源代码和社区贡献的代码实例。ClojureDocs在我学习Clojure的过程中起了很大的作用，所以我想这个网站应该对很多人有用。</p>
<p>无暇去学习Android平台上繁琐的知识，不过好在有Phonegap这样的框架，可以把网页应用转化为本地应用，并且提供访问本地设备的API。通过Phonegap开发的程序还可以直接移植到iphone平台上。ClojureDocs Android就是运行在Phonegap中。</p>
<p>首页：<br />
<img src="http://i.imgur.com/zdMCt.png" alt="" /></p>
<p>搜索界面<br />
<img src="http://i.imgur.com/MVCz4.png" alt="" /></p>
<p>API函数界面<br />
<img src="http://i.imgur.com/M0fEI.png" alt="" /></p>
<p>你可以从github获得代码和签名过的apk：<a href="https://github.com/sunng87/clojuredocs-android" target="_blank">https://github.com/sunng87/clojuredocs-android</a></p>
<p>Known Issue，phonegap程序在屏幕旋转时会崩溃，已经在2.3和3.2上重现，目前还不清楚具体的原因。(Edit 20120127: Fixed in 1.0.4)</p>
<p>欢迎任何的pull request。</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/01/clojuredocs-android-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Weekend Project: LazyPress</title>
		<link>http://sunng.info/blog/2012/01/weekend-project-lazypress/</link>
		<comments>http://sunng.info/blog/2012/01/weekend-project-lazypress/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 07:40:01 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[cloudfoundry]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1134</guid>
		<description><![CDATA[发布一个典型的weekend project, 名字叫做LazyPress.顾名思义,这是一个在线的写作系统. 取名Lazy, 除了因为它用Clojure写成,更因为他的简单: 没有繁琐的注册,没有繁琐的分类tag,没有繁琐的格式化,无论是使用还是开发都力求做到最简单. LazyPress采用Mozilla刚刚发布的BrowserID. 技术作为账号系统, 用户只需要在首次登录后提供一个ID即可(原本这一步也可以省略, 但是为了保护您的邮箱隐私, 现在需要一个LazyPress专用的ID). 这样LazyPress本身不存储用户的密码,也简化了用户账号管理的代价. BrowserID的登录流程非常简单, 速度也比传统的OpenID和OAuth要快, 用户体验要比多次跳转好很多. LazyPress使用Markdown进行文本格式化, 简单的编辑器可以支持绝大多数格式的要求. 另外,在浏览器后台LazyPress使用HTML5 LocalStorage技术自动保存用户的文本草稿, 如果用户没有成功发布, 可以在下次浏览器打开时进行恢复. LazyPress后台存储采用mongodb. 正是mongodb的schema free特性降低了项目功能重构的成本, 促进了人们更快更频繁地优化产品的模型. 这应该是文档型数据库之于传统关系型数据库最大的优势. (犹如git之于svn, 开分支的成本要低得多, 看似是一个普通的功能改进, 实则鼓励促进了开发人员通过开分支实现自己的修改) LazyPress运行在最近发布的compojure 1.0.0和ring 1.0.0上, 打包为标准的Java web应用直接部署在cloudfoundry上. 前端继续使用的是我偏爱的Mootools库, 因为使用了很多新的浏览器技术, 所以目前只能保证在最新的Firefox和Chromium/Chrome上正常使用. Fork me &#8230; <a href="http://sunng.info/blog/2012/01/weekend-project-lazypress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>发布一个典型的weekend project, 名字叫做<a href="http://lazypress.cloundfoundry.com">LazyPress</a>.顾名思义,这是一个在线的写作系统. 取名Lazy, 除了因为它用Clojure写成,更因为他的简单: 没有繁琐的注册,没有繁琐的分类tag,没有繁琐的格式化,无论是使用还是开发都力求做到最简单.<br />
LazyPress采用Mozilla刚刚发布的<a href="http://browserid.org/">BrowserID</a>. 技术作为账号系统, 用户只需要在首次登录后提供一个ID即可(原本这一步也可以省略, 但是为了保护您的邮箱隐私, 现在需要一个LazyPress专用的ID). 这样LazyPress本身不存储用户的密码,也简化了用户账号管理的代价. BrowserID的登录流程非常简单, 速度也比传统的OpenID和OAuth要快, 用户体验要比多次跳转好很多.<br />
LazyPress使用Markdown进行文本格式化, 简单的编辑器可以支持绝大多数格式的要求. 另外,在浏览器后台LazyPress使用HTML5 LocalStorage技术自动保存用户的文本草稿, 如果用户没有成功发布, 可以在下次浏览器打开时进行恢复.</p>
<p>LazyPress后台存储采用mongodb. 正是mongodb的schema free特性降低了项目功能重构的成本, 促进了人们更快更频繁地优化产品的模型. 这应该是文档型数据库之于传统关系型数据库最大的优势. (犹如git之于svn, 开分支的成本要低得多, 看似是一个普通的功能改进, 实则鼓励促进了开发人员通过开分支实现自己的修改)<br />
LazyPress运行在最近发布的compojure 1.0.0和ring 1.0.0上, 打包为标准的Java web应用直接部署在cloudfoundry上. 前端继续使用的是我偏爱的Mootools库, 因为使用了很多新的浏览器技术, 所以目前只能保证在最新的Firefox和Chromium/Chrome上正常使用.</p>
<p>Fork me on github: <a href="http://github.com/sunng87/lazypress">http://github.com/sunng87/lazypress</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/01/weekend-project-lazypress/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>slacker 0.4.0 released</title>
		<link>http://sunng.info/blog/2012/01/slacker-0-4-0-released/</link>
		<comments>http://sunng.info/blog/2012/01/slacker-0-4-0-released/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 12:49:04 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[ANN]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[slacker]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1132</guid>
		<description><![CDATA[Slacker 0.4.0 has been released to clojars.org . There are new features and breaking changes in this release. Breaking Changes New maven coordinator: [slacker "0.4.0"] (groupId renamed to slakcer) defremote renamed to defn-remote SlackerException removed. slacker now uses slingshot for &#8230; <a href="http://sunng.info/blog/2012/01/slacker-0-4-0-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Slacker 0.4.0 has been released to clojars.org . There are new features and breaking changes in this release.</p>
<h3>Breaking Changes</h3>
<ul>
<li>New maven coordinator: [slacker "0.4.0"] (groupId renamed to slakcer)</li>
<li>defremote renamed to <strong>defn-remote</strong></li>
<li>SlackerException removed. slacker now uses slingshot for exception handling</li>
<li>Rename :async option of defn-remote to <strong>:async?</strong></li>
</ul>
<h3>What&#8217;s new in 0.4.0</h3>
<ul>
<li>Add new serialization type <strong>:clj</strong></li>
<li>New interceptors: execution time stats, args logger, slow watch dog</li>
<li>New HTTP interface</li>
<li>Server inspect commands	</li>
<li> utility functions/macros <strong>defn-remote-all</strong>, <strong>defn-remote-batch</strong> and <strong>meta-remote</strong></li>
</ul>
<p>Get more information on <a href="https://github.com/sunng87/slacker" target="_blank">github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2012/01/slacker-0-4-0-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extend slacker server with interceptors</title>
		<link>http://sunng.info/blog/2011/12/extend-slacker-server-with-interceptors/</link>
		<comments>http://sunng.info/blog/2011/12/extend-slacker-server-with-interceptors/#comments</comments>
		<pubDate>Sun, 18 Dec 2011 10:08:42 +0000</pubDate>
		<dc:creator>sunng</dc:creator>
				<category><![CDATA[装备]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[slacker]]></category>

		<guid isPermaLink="false">http://sunng.info/blog/?p=1106</guid>
		<description><![CDATA[An interceptor framework was introduced in slacker 0.3.0. It&#8217;s designed to allow user to add custom functionality without hacking into the internal of slacker. Like many server frameworks, slacker abstracts the request processing as a pipeline. The request object is &#8230; <a href="http://sunng.info/blog/2011/12/extend-slacker-server-with-interceptors/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>An interceptor framework was introduced in slacker 0.3.0. It&#8217;s designed to allow user to add custom functionality without hacking into the internal of slacker.</p>
<p>Like many server frameworks, slacker abstracts the request processing as a pipeline. The request object is modified by adding or updating attributes through each node of the pipeline. So it&#8217;s easy to add your interceptor into the pipeline, with which you can get the data before and after function executed.</p>
<p>To create such an interceptor, you should use the <em>slacker.interceptor/definterceptor</em> macro and <em>slacker.interceptor/definterceptor+</em> macro:</p>
<blockquote><p>(definterceptor name<br />
  :before interceptor-function<br />
  :after interceptor-function)</p></blockquote>
<blockquote><p>(definterceptor+ name [arguments]<br />
  :before interceptor-function<br />
  :after interceptor-function)</p></blockquote>
<p>definterceptor+ can accept arguments so you can configure the interceptor when you use it.</p>
<p>See a simple example:</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>definterceptor log<span style="color: #66cc66;">-</span>function<span style="color: #66cc66;">-</span>call<br />
&nbsp; :<span style="color: #555;">before</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">fn</span> <span style="color: #66cc66;">&#91;</span>req<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>println <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">str</span> <span style="color: #ff0000;">&quot;calling &quot;</span> <span style="color: #66cc66;">&#40;</span>:<span style="color: #555;">fname</span> req<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> req<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
<span style="color: #66cc66;">&#40;</span>definterceptor<span style="color: #66cc66;">+</span> log<span style="color: #66cc66;">-</span>function<span style="color: #66cc66;">-</span>call<span style="color: #66cc66;">-</span>prefixed <span style="color: #66cc66;">&#91;</span>prefix<span style="color: #66cc66;">&#93;</span><br />
&nbsp; :<span style="color: #555;">before</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">fn</span> <span style="color: #66cc66;">&#91;</span>req<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span>println <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">str</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">fn</span>? prefix<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>prefix<span style="color: #66cc66;">&#41;</span> prefix<span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot; calling &quot;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>:<span style="color: #555;">fname</span> req<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; req<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Then, add it to your slacker server by</p>
<div class="codecolorer-container clojure twitlight" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="clojure codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>use '<span style="color: #66cc66;">&#91;</span>slacker<span style="color: #66cc66;">.</span>interceptor<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">import</span> '<span style="color: #66cc66;">&#91;</span>java<span style="color: #66cc66;">.</span>util Date<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#40;</span>start<span style="color: #66cc66;">-</span>slacker <span style="color: #66cc66;">&#40;</span>the<span style="color: #66cc66;">-</span><span style="color: #b1b100;">ns</span> 'slapi<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">2104</span><br />
&nbsp; :<span style="color: #555;">interceptors</span> <span style="color: #66cc66;">&#40;</span>interceptors log<span style="color: #66cc66;">-</span>function<span style="color: #66cc66;">-</span>call<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span>log<span style="color: #66cc66;">-</span>function<span style="color: #66cc66;">-</span>call<span style="color: #66cc66;">-</span>prefixed <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">fn</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">.</span>toString <span style="color: #66cc66;">&#40;</span>Date<span style="color: #66cc66;">.</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></div>
<p>Now you can log every function call of your slacker server.</p>
<p>For more detail about the interceptor framework, especially the request data, please check the <a href="https://github.com/sunng87/slacker/wiki/Interceptors" target="_blank">wiki page</a>.</p>
<p>In slacker 0.3.0, there is a built-in interceptor to stats function calls. You can find it at <em>slacker.interceptors.stats</em>. The stats data is expose via JMX. You can also write monitoring application to retrieve the data.<br />
<a href="http://imgur.com/vtOoL"><img src="http://i.imgur.com/vtOoL.png" alt="" title="Hosted by imgur.com" /></a></p>
<p>And there will be more built-in interceptors in 0.4.0, includes function call time stats and logging.</p>
]]></content:encoded>
			<wfw:commentRss>http://sunng.info/blog/2011/12/extend-slacker-server-with-interceptors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

