<?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>Talk Unafraid &#187; rails</title>
	<atom:link href="http://www.talkunafraid.co.uk/tag/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.talkunafraid.co.uk</link>
	<description>EVE Online, Ruby on Rails and Security</description>
	<lastBuildDate>Wed, 01 Sep 2010 17:12:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>EVE Metrics 3</title>
		<link>http://www.talkunafraid.co.uk/2010/07/eve-metrics-3/</link>
		<comments>http://www.talkunafraid.co.uk/2010/07/eve-metrics-3/#comments</comments>
		<pubDate>Sat, 10 Jul 2010 02:56:42 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[EVE Metrics]]></category>
		<category><![CDATA[MMMetrics]]></category>
		<category><![CDATA[Servers and Software]]></category>
		<category><![CDATA[eve metrics]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[release]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=972</guid>
		<description><![CDATA[Okay, as someone who feels an obligation to post at least once a month I&#8217;m ashamed. 8th of May? Time to sort that out. So here&#8217;s a post about EVE Metrics 3. We&#8217;re getting close to having everything polished and ready for release. The main issue at hand thus far has been the homepage; I [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, as someone who feels an obligation to post at least once a month I&#8217;m ashamed. 8th of May? Time to sort that out.</p>
<p>So here&#8217;s a post about EVE Metrics 3.</p>
<p>We&#8217;re getting close to having everything polished and ready for release. The main issue at hand thus far has been the homepage; I say this like it&#8217;s a small thing but it&#8217;s required me to learn some new and interesting things about CSS, Makurid&#8217;s done some excellent work to produce some feed scrapers and elements for the lower portion of the page&#8230; there&#8217;s a lot to it.</p>
<p>I thought that it&#8217;d be good to list a few of the changes we&#8217;ve made for version 3.</p>
<ul>
<li>Complete redesign of the site thanks to Rettic</li>
<li>Market detail pages have been entirely renovated</li>
<li>Various pages which haven&#8217;t been improved in some time have now been tidied up</li>
<li>API key management has been improved</li>
<li>API key permissions management has been improved</li>
<li>Backend processors for API functions and upload processing have been improved and made more reliable</li>
<li>My Metrics has been entirely renovated, now with sparklines for wallets and a new layout</li>
<li>Orders and transactions have been moved from My Metrics into their own detail pages, with a summary on My Metrics</li>
<li>Journal information has been added and given it&#8217;s own detail page</li>
<li>Player Owned Structure integration has been added, though still in it&#8217;s infancy</li>
<li>Sensitive portions of the site now make use of SSL transport encryption (HTTPS) automatically</li>
<li>Wormhole pages have been updated</li>
<li>Improvements to the corporation pages through refactoring to share view code between character and corporation pages</li>
<li>Graph improvements</li>
<li>Complete test coverage of every line of code (Nah, just kidding, we&#8217;re still pretty thin on those test things for large chunks of UI code)</li>
<li>0.2% more cowbell</li>
<li>5% other features I&#8217;ve not listed above, plus 100% more polish overall</li>
</ul>
<p>Excited? We are! There&#8217;s a lot of work in the lines above and I think you&#8217;ll like the results. We&#8217;re not sticking to any firm release schedule because we&#8217;re terrible at sticking to them; we&#8217;re students, not full-time developers (incidentally, if anyone&#8217;s got any jobs available for temporary/contract work, SE UK preferred (or work-at-home), 6 weeks max, let me know!). That said, we hope to have a release before the end of July.</p>
<p>We&#8217;ve also been rewriting our uploader! That&#8217;s right- Linux, Mac and Windows support all in one neat package. The GUI&#8217;s not anything special but it works, and we&#8217;ll be polishing it and getting it release-ready before long. Huge thanks should be directed to TTimo, who has been the driving force behind this with some welcome Python experience, and Makurid for assisting him in developing the new client.</p>
<p>Once we&#8217;ve gotten that polished, packaged and rolled out, we&#8217;ll be running a 5 billion ISK contest to promote it- the three winners (each receiving a portion of the 5 billion pool) will be selected from the most active uploaders for the week or two after the competition is announced. We&#8217;ll finalize all the details and have it posted up when we&#8217;re ready to go ahead with that, of course. If you&#8217;d like to make that 5 billion figure larger, you can contribute ISK to the character MMMetrics Agent ingame! So far, thanks go out to Rilcon, Chribba and Entity for contributing to the current pool. The new uploader will be released after the new site &#8211; we&#8217;d like to change one thing at a time so we can iron out all the kinks. Once we&#8217;ve gotten it out and tested it thoroughly we&#8217;ll roll out the upgrade- your existing uploader will prompt you to update when you start it.</p>
<p>One last thing &#8211; I&#8217;ve personally submitted a proposal to the CSM regarding development efforts from CCP surrounding the API and EVE Gate. If you&#8217;ve not done so already, I strongly urge you to read my proposal and support it if you feel, like I do, that CCP have made some serious mistakes lately in this regard. The thread can be found <a href="http://www.eveonline.com/ingameboard.asp?a=topic&amp;threadID=1348624">here</a>. It has been picked up and supported by at least 3 CSM members so far, but the community support will help considerably to drive CCP to consider it seriously.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2010/07/eve-metrics-3/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Learning (a tale of memory)</title>
		<link>http://www.talkunafraid.co.uk/2010/02/learning-a-tale-of-memory/</link>
		<comments>http://www.talkunafraid.co.uk/2010/02/learning-a-tale-of-memory/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 00:19:40 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[EVE Metrics]]></category>
		<category><![CDATA[eve metrics]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[servers]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=653</guid>
		<description><![CDATA[We never really stop learning. Learning is perhaps the most important process to occur in our brains; ignore the past, and you are screwed. This post is a tale of how we&#8217;ve been running into issues with memory usage recently, how we&#8217;ve been solving and diagnosing it, and the design decisions that have lead to [...]]]></description>
			<content:encoded><![CDATA[<p>We never really stop learning. Learning is perhaps the most important process to occur in our brains; ignore the past, and you are <em>screwed</em>.</p>
<p>This post is a tale of how we&#8217;ve been running into issues with memory usage recently, how we&#8217;ve been solving and diagnosing it, and the design decisions that have lead to it.<span id="more-653"></span></p>
<p>In the past week or so we&#8217;ve been puzzling over some unusually high memory usage of our application servers (we use the Thin server for EVE Metrics and Passenger for everything else). Specifically, our thins were getting fat; chewing up memory, not responding to new requests and churning on locks.</p>
<p>On a hunch and some history, we pulled out RMagick, the Ruby interface to ImageMagick, which had been known to cause issues with memory usage by way of some leaks. We switched the code that we had to use ImageMagick for to use the mini_magick library, and where we could (notably the sparkline graphs on the statistics panel) we switched from server-side to client-side rendering. Those sparklines are now using the excellent jQuery Sparklines plugin. They look better, too!</p>
<p>That did solve our memory issues; we still had problems with sudden spikes in memory, and we pinned down the cause using the Oink diagnostics plugin. Someone (and if you&#8217;re reading this, let me know who you are, I&#8217;d like to talk, not to bite your head off, but to ask you why the CSVs didn&#8217;t leap out at you quite as they should have&#8230;) decided to make lots of history requests to the API, for all 59 regions at a time and for 25 items at a time. Admittedly only for one day, but there&#8217;s a kicker here.</p>
<p>Those 25 items across 59 regions is not a lot of <em>historical</em> data. But, those of you with EVE Metrics API experience should be shouting, &#8220;James, the history API <em>also includes the item API data!</em>&#8221; Which it does! This entails loading the market orders. Now, there is a problem here. Let&#8217;s say you request 25 items for 59 regions. That is a _lot_ of market orders, potentially. Remember we have 1.5 million orders over the whole market and the really active market is spread across a few thousand items. But there&#8217;s a few items with vast numbers of orders. That number of orders can rise quite easily into the tens or hundreds of thousands.</p>
<p>We have to load all those orders into memory to work with them, then allocate the raw data into Gnu Scientific Library vectors, then process that data (fast, thanks to C), and then render out the XML response. Because we have to have all these orders in RAM at once, Ruby&#8217;s VM allocates the process more and more memory, which is removed from the OS&#8217;s spare resources which are used for caching the filesystem in memory. This cache is the primary mechanism for PostgreSQL, our database engine, to keep data in RAM; subtract from this and you&#8217;re hurting DB performance and increasing disk IO. Everything slows down. Eventually, Ruby allocates enough that the OS itself is out of cache and has to start swapping to disk; we&#8217;ve not yet run into this since I&#8217;ve been monitoring this all closely with Munin, but it would eventually happen. Ruby (along with most other VM-based languages) has a pretty crap GC, and even once the request is over, this memory is not returned to the OS from the VM. This means that things can escalate pretty dramatically if left unchecked.</p>
<p>So, what can we do to fix this? Well, in time I want to remove the item API data from the history API. That&#8217;ll improve things greatly in our own application. I&#8217;ve also implemented a limit on the number of items and regions that can be checked at once to stop people generating huge memory spikes.</p>
<p>There&#8217;s a nasty side-effect here: While these thins are churning away, nomming up memory like there&#8217;s no tomorrow, they&#8217;re locked up and handling a long running request. If we get enough requests this means the website becomes unavailable, something I personally find intolerable. So I&#8217;ve increased the number of app servers we run and split the requests up as they come in between two pools, one of which has a few servers dedicated to handling web site requests, and likewise one of which has a few dedicated to handling API requests, with a few servers shared between the pools. This will help stability in the long run and ensure that at any moment, requests can be fulfilled in a timely manner. Varnish is also getting some tweaks to serve up old content when the backends are busy where a cached object exists.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2010/02/learning-a-tale-of-memory/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RiCal and Google Calendar</title>
		<link>http://www.talkunafraid.co.uk/2009/07/rical-and-google-calendar/</link>
		<comments>http://www.talkunafraid.co.uk/2009/07/rical-and-google-calendar/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 00:29:52 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[Charactr]]></category>
		<category><![CDATA[Code Snippets and Examples]]></category>
		<category><![CDATA[EVE Metrics]]></category>
		<category><![CDATA[MMMetrics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[eve metrics]]></category>
		<category><![CDATA[ical]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=401</guid>
		<description><![CDATA[So, there was a request on Twitter from ChainerCygnus to get Google Calendar support in Charactr, so I went ahead and implemented it. You can now access an iCal feed of skill changes on Charactr on the characters page, and it uses the Charactr API key to authenticate so it works in anything, no need [...]]]></description>
			<content:encoded><![CDATA[<p>So, there was a request on Twitter from <a href="http://twitter.com/chainercygnus/status/2556207281">ChainerCygnus</a> to get Google Calendar support in Charactr, so I went ahead and implemented it. You can now access an iCal feed of skill changes on Charactr on the characters page, and it uses the Charactr API key to authenticate so it works in anything, no need for HTTP Basic authentication support or anything.</p>
<p>Implementing was actually really easy. I grabbed the RiCal gem off Github, threw in the config.gem line in environment.rb, and added this to the characters controller index action:</p>
<div class="geshi no ruby">
<div class="head">respond_to do |format|</div>
<ol>
<li class="li1">
<div class="de1">&nbsp; <span class="kw3">format</span>.<span class="me1">html</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw3">format</span>.<span class="me1">ics</span> <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; rna = <span class="br0">&#91;</span><span class="st0">&#39;(Untrained)&#39;</span>,<span class="st0">&#39;I&#39;</span>,<span class="st0">&#39;II&#39;</span>,<span class="st0">&#39;III&#39;</span>,<span class="st0">&#39;IV&#39;</span>,<span class="st0">&#39;V&#39;</span><span class="br0">&#93;</span> <span class="co1"># Used below for roman numerals</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; cal = RiCal.<span class="me1">Calendar</span> <span class="kw1">do</span> <span class="sy0">|</span>cal<span class="sy0">|</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; cal.<span class="me1">add_x_property</span><span class="br0">&#40;</span><span class="st0">&#39;X-WR-CALNAME&#39;</span>,<span class="st0">&#39;Charactr&#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="re1">@characters</span>.<span class="me1">each</span> <span class="kw1">do</span> <span class="sy0">|</span>char<span class="sy0">|</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> char.<span class="me1">skills_in_training</span>.<span class="me1">length</span> <span class="sy0">&amp;</span>gt; <span class="nu0">0</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char.<span class="me1">skills_in_training</span>.<span class="me1">each</span> <span class="kw1">do</span> <span class="sy0">|</span>s<span class="sy0">|</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cal.<span class="me1">event</span> <span class="kw1">do</span> <span class="sy0">|</span>e<span class="sy0">|</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.<span class="me1">summary</span> <span class="st0">&quot;#{char.name} finishes #{s.type.name} #{rna[s.level]}&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.<span class="me1">description</span> <span class="st0">&quot;#{char.name} finishes #{s.type.name} #{rna[s.level]}&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.<span class="me1">dtstart</span> s.<span class="me1">end_time</span><span class="nu0">-10</span>.<span class="me1">minutes</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.<span class="me1">dtstart</span> s.<span class="me1">end_time</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><span class="co1"># event</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span> <span class="co1"># skills loop</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span> <span class="co1"># skillintraining &amp;gt; 0</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">end</span> <span class="co1"># char loop</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">end</span> <span class="co1"># calendar</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; render <span class="re3">:text</span><span class="sy0">=&amp;gt;</span>cal.<span class="me1">export</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
</ol>
</div>
<p>So as you can see, it&#8217;s a snap. Rails ships with a preconfigured MIME type for the :ics format, so it&#8217;s handled properly by nginx automatically. Still having some issues making Google Calendar accept the feed&#8217;s name as Charactr, mind you, but the rest works flawlessly and is available for all Charactr users right now.</p>
<p>On a side note, we&#8217;ve set up the <a href="http://twitter.com/mmmetrics">@mmmetrics</a> Twitter account as a shared account between all the MMMetrics team; if you&#8217;re having problems with any of the sites and use Twitter that&#8217;s a pretty good port of call. We&#8217;ll also be using that for announcements and so on, so it might make sense to follow if you&#8217;re interested in what we do.</p>
<p>It&#8217;s been a busy day on EVE Metrics 2, so I leave you with a few teaser screenshots. We&#8217;re almost done with the basic market view pages, and it&#8217;s now a matter of implementing the smaller features- market favourites, map features, and the APIs. EM2 won&#8217;t be an instant fullfilment of every feature promised over the past year or so; we&#8217;re taking the development slowly. EM2 at release won&#8217;t be as feature-packed as EM1, but it&#8217;ll work a whole lot better! Once we&#8217;ve gotten it released (hopefully in just under a week) we&#8217;ll be adding features and maintaining the site continuously to get all the features you want implemented without affecting performance.</p>

<a href='http://www.talkunafraid.co.uk/2009/07/rical-and-google-calendar/2009-07-09_1746/' title='Regional Statistics Overview'><img width="150" height="150" src="http://assets.talkunafraid.co.uk/2009/07/2009-07-09_1746-150x150.png" class="attachment-thumbnail" alt="Regional Statistics Overview" title="Regional Statistics Overview" /></a>
<a href='http://www.talkunafraid.co.uk/2009/07/rical-and-google-calendar/2009-07-09_1653/' title='Price History Graphs'><img width="150" height="150" src="http://assets.talkunafraid.co.uk/2009/07/2009-07-09_1653-150x150.png" class="attachment-thumbnail" alt="Price History Graphs" title="Price History Graphs" /></a>
<a href='http://www.talkunafraid.co.uk/2009/07/rical-and-google-calendar/2009-07-09_1923/' title='Order Lists'><img width="150" height="150" src="http://assets.talkunafraid.co.uk/2009/07/2009-07-09_1923-150x150.png" class="attachment-thumbnail" alt="Order Lists" title="Order Lists" /></a>

]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2009/07/rical-and-google-calendar/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rails and nginx/thin</title>
		<link>http://www.talkunafraid.co.uk/2009/06/rails-and-nginxthin/</link>
		<comments>http://www.talkunafraid.co.uk/2009/06/rails-and-nginxthin/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 22:04:09 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[Awesome Stuff]]></category>
		<category><![CDATA[Charactr]]></category>
		<category><![CDATA[Code Snippets and Examples]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[servers]]></category>
		<category><![CDATA[stuffisawesome]]></category>
		<category><![CDATA[thin]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=350</guid>
		<description><![CDATA[For the EVE people reading my blog, probably best to skip this one. If you&#8217;re one of my Rails readers, however, then this may interest you. Charactr has been doing quite well. We originally released it deployed on Apache with Passenger (also known as mod_rails). While the performance was tolerable it wasn&#8217;t the snappiest thing [...]]]></description>
			<content:encoded><![CDATA[<p>For the EVE people reading my blog, probably best to skip this one. If you&#8217;re one of my Rails readers, however, then this may interest you.</p>
<p>Charactr has been doing quite well. We originally released it deployed on Apache with Passenger (also known as mod_rails). While the performance was tolerable it wasn&#8217;t the snappiest thing in the world, and on a memory-limited VPS even with Ruby Enterprise Edition we were often running into memory limits. Right now however we&#8217;re on nginx and thin, the first production environment I&#8217;ve used this combination for.</p>
<p>Performance-wise, I&#8217;m impressed. Not only is the static asset hosting snappy as anything, but thin handles remarkably well and does it without chewing up much RAM. I&#8217;m pretty sure Passenger/REE would win on a box with a few gigs of RAM, but on something this small (540 megs, including the db server on the same box) the extra overhead from Passenger&#8217;s spawner was too much.</p>
<p>Configuration is where nginx really wins out, however&#8230;</p>
<p><span id="more-350"></span>There&#8217;s nothing wrong per-se with Apache&#8217;s configuration, but nginx makes life a whole lot easier for hosting Rails apps. First off, many thanks to <a href="http://forum.nginx.org/profile.php?2,47">Igor Sysoev</a> for some recommendations in this config and help debugging an issue with 502 catching (So I can display a pretty page to the users while the cluster restarts; ideally we&#8217;d avoid this entirely but I&#8217;m not sure how I&#8217;d go about doing it on a budget).</p>
<div class="geshi no perl">
<div class="head"># Your thin servers go here</div>
<ol>
<li class="li1">
<div class="de1">upstream charactrapp <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">server <span class="nu0">127.0</span><span class="nu0">.0</span><span class="nu0">.1</span>:<span class="nu0">3000</span>;</div>
</li>
<li class="li1">
<div class="de1">server <span class="nu0">127.0</span><span class="nu0">.0</span><span class="nu0">.1</span>:<span class="nu0">3001</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># The usual server</span></div>
</li>
<li class="li1">
<div class="de1">server <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw3">listen</span> &nbsp; <span class="nu0">80</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; server_name charactrapp.com www.charactrapp.com;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; access_log <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>access.<span class="kw3">log</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; error_log <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>error.<span class="kw3">log</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; root &nbsp; <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>current<span class="sy0">/</span>public<span class="sy0">/</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw3">index</span> &nbsp;<span class="kw3">index</span>.html;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1"># Compress what we can, but make sure msie6 doesn&#39;t get gzip content and don&#39;t gzip tiny stuff</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; on;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_min_length &nbsp;<span class="nu0">1000</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_proxied &nbsp; &nbsp; expired no-cache no-store private auth;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_types &nbsp; &nbsp; &nbsp; text<span class="sy0">/</span>plain application<span class="sy0">/</span>xml text<span class="sy0">/</span>css application<span class="sy0">/</span>javascript;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_disable &nbsp; &nbsp; msie6;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1"># Catches anything that isn&#39;t sent to assets. (should catch nothing)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; location ~<span class="sy0">*</span> <span class="br0">&#40;</span>css<span class="sy0">|</span>js<span class="sy0">|</span>png<span class="sy0">|</span>jpe?g<span class="sy0">|</span>gif<span class="sy0">|</span>ico<span class="br0">&#41;</span>$ <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; expires max;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1"># Will render page caches if they&#39;re there, or redirect to the cluster</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; location <span class="sy0">/</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; try_files <span class="re0">$uri</span><span class="sy0">/</span><span class="kw3">index</span>.html <span class="re0">$uri</span>.html <span class="re0">$uri</span> <span class="re0">@charactrapp</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1"># The cluster is here</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; location <span class="re0">@charactrapp</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_pass http:<span class="sy0">//</span>charactrapp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_set_header X-Real-IP <span class="re0">$remote_addr</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_set_header X-Forwarded-For <span class="re0">$proxy_add_x_forwarded_for</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_set_header Host <span class="re0">$http_host</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_redirect off;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1"># Catch servers being down and display a message. Has to be a location.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; error_page <span class="nu0">502</span> <span class="sy0">/</span><span class="nu0">502</span>.html;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; location = <span class="sy0">/</span><span class="nu0">502</span>.html <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">server <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw3">listen</span> &nbsp; <span class="nu0">443</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; server_name charactrapp.com www.charactrapp.com;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; access_log <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>access.<span class="kw3">log</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; error_log <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>error.<span class="kw3">log</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; root &nbsp; <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>current<span class="sy0">/</span>public<span class="sy0">/</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw3">index</span> &nbsp;<span class="kw3">index</span>.html;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; on;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_min_length &nbsp;<span class="nu0">1000</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_proxied &nbsp; &nbsp; expired no-cache no-store private auth;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_types &nbsp; &nbsp; &nbsp; text<span class="sy0">/</span>plain application<span class="sy0">/</span>xml text<span class="sy0">/</span>css application<span class="sy0">/</span>javascript;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_disable &nbsp; &nbsp; msie6;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1"># Enable SSL</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; ssl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;on;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; ssl_certificate &nbsp; &nbsp; &nbsp;<span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>chained.crt; <span class="co1"># This actually has the domain&#39;s cert, and the CA&#39;s cert/chain all in one file</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; ssl_certificate_key &nbsp;<span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>app.key; <span class="co1"># Key for the domain&#39;s cert</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; keepalive_timeout &nbsp; &nbsp;<span class="nu0">70</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; location ~<span class="sy0">*</span> <span class="br0">&#40;</span>css<span class="sy0">|</span>js<span class="sy0">|</span>png<span class="sy0">|</span>jpe?g<span class="sy0">|</span>gif<span class="sy0">|</span>ico<span class="br0">&#41;</span>$ <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; expires max;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; location <span class="sy0">/</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; try_files <span class="re0">$uri</span><span class="sy0">/</span><span class="kw3">index</span>.html <span class="re0">$uri</span>.html <span class="re0">$uri</span> <span class="re0">@charactrapp</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; location <span class="re0">@charactrapp</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_pass http:<span class="sy0">//</span>charactrapp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_set_header X-FORWARDED_PROTO https; <span class="co1"># Vital for ssl_requirement plugin to function correctly.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_set_header X-Real-IP <span class="re0">$remote_addr</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_set_header X-Forwarded-For <span class="re0">$proxy_add_x_forwarded_for</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_set_header Host <span class="re0">$http_host</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; proxy_redirect off;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; error_page <span class="nu0">502</span> <span class="sy0">/</span><span class="nu0">502</span>.html;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; location = <span class="sy0">/</span><span class="nu0">502</span>.html <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># Asset subdomain, just caches everything it serves with public Cache-Control.</span></div>
</li>
<li class="li1">
<div class="de1">server <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw3">listen</span> &nbsp; <span class="nu0">80</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; server_name assets.charactrapp.com;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; access_log <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>access.<span class="kw3">log</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; error_log <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>error.<span class="kw3">log</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; root &nbsp; <span class="sy0">/</span>opt<span class="sy0">/</span>www<span class="sy0">/</span>charactr<span class="sy0">/</span>current<span class="sy0">/</span>public<span class="sy0">/</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw3">index</span> &nbsp;<span class="kw3">index</span>.html;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; on;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_min_length &nbsp;<span class="nu0">1000</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_proxied &nbsp; &nbsp; expired no-cache no-store private auth;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_types &nbsp; &nbsp; &nbsp; text<span class="sy0">/</span>plain application<span class="sy0">/</span>xml text<span class="sy0">/</span>css application<span class="sy0">/</span>javascript application<span class="sy0">/</span>x-javascript;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; gzip_disable &nbsp; &nbsp; msie6;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; expires max;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; add_header Cache-Control public;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>See? That&#8217;s all of Charactr&#8217;s configs. Of course, there&#8217;s still the server config but that&#8217;s pretty simple, and the default will do just fine for that.</p>
<p>So, overall I&#8217;m impressed with nginx. Thin I&#8217;ve used before and will be doing so with EVE Metrics 2; the combination of excellent stability with an Evented architecture hasn&#8217;t failed me yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2009/06/rails-and-nginxthin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting started with Rails and Nanite</title>
		<link>http://www.talkunafraid.co.uk/2009/05/getting-started-with-rails-and-nanite/</link>
		<comments>http://www.talkunafraid.co.uk/2009/05/getting-started-with-rails-and-nanite/#comments</comments>
		<pubDate>Fri, 01 May 2009 20:35:04 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[Code Snippets and Examples]]></category>
		<category><![CDATA[EVE Metrics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ampq]]></category>
		<category><![CDATA[background processing]]></category>
		<category><![CDATA[nanite]]></category>
		<category><![CDATA[rabbitmq]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=294</guid>
		<description><![CDATA[Woo, time for a purely Ruby/Rails post. I&#8217;ve not done one in a while, so here goes. In EVE Metrics 2.0 I&#8217;ve been looking to replace the previous delayed_job system with a more robust and fault-tolerant system. A while ago I attended the Ruby Manor conference, and saw an excellent talk on Nanite by George [...]]]></description>
			<content:encoded><![CDATA[<p>Woo, time for a purely Ruby/Rails post. I&#8217;ve not done one in a while, so here goes.</p>
<p>In EVE Metrics 2.0 I&#8217;ve been looking to replace the previous delayed_job system with a more robust and fault-tolerant system. A while ago I attended the Ruby Manor conference, and saw an <a href="http://effectif.com/articles/notes-from-the-ruby-manor">excellent talk</a> on <a href="http://github.com/ezmobius/nanite/tree/master">Nanite</a> by George Palmer. It&#8217;s a very neat way of doing background processing- it depends on a mapper, agents and actors. Agents have many actors and announce their presence to the mapper regularly along with (by default) system load info, and the mapper then sends jobs to the least loaded agent which supports a given actor. It also works on AMPQ, and by default the RabbitMQ server, a very high performance queue server written in Erlang. It&#8217;s fast enough that you can stream video over it quite well, apparently, and it scales well with large queues, so should fit the bill nicely for EVE Metrics.</p>
<p>Getting started, however, can be kinda tricky. So here&#8217;s the simple &#8216;getting started&#8217; that is sadly absent from the Nanite documentation.</p>
<p><span id="more-294"></span>First, we need RabbitMQ. So, install Erlang and RabbitMQ- if you&#8217;re on Debian/Ubuntu then Erlang is in the default repositories (apt-get install erlang), and while RabbitMQ is also there I recommend grabbing the most recent version in .deb format <a href="http://www.rabbitmq.com/download.html">from their site.</a> Windows users can find a handy bundle with Erlang and RabbitMQ and a nice readme, so go ahead and sort that out. I&#8217;ll wait here.</p>
<p>Now that&#8217;s all done, it&#8217;s a simple matter of installing Nanite and it&#8217;s dependencies. Best way to do this is to clone nanite (git clone git://github.com/ezmobius/nanite.git), cd in there and run &#8216;rake gem&#8217;. Then install the gem it creates with &#8216;gem install pkg/*.gem&#8217;. Dependencies (AMPQ and EventMachine) will get autoinstalled. Note that simply running &#8216;gem install ezmobius-nanite&#8217; fails to install correctly and does not create documentation.</p>
<p>Not much further, I promise!</p>
<p>Now that we&#8217;ve got it all installed we need to tie it into Rails. While googling for this, I tripped over the highly useful and recently created <a href="http://github.com/dcu/nanite-rails/tree/master">nanite-rails plugin</a>. While it&#8217;s not perfect it&#8217;s a whole lot better than nothing and takes care of some of the nastier bits of Nanite&#8217;s workings. Install it as a plugin with script/plugin, and then generate nanite (&#8216;ruby script/generate nanite&#8217;). Voila! Now there&#8217;s only one last thing to do, and that&#8217;s to add the following line to config/environment.rb:</p>
<pre lang="ruby">config.gem "nanite"</pre>
<p>And we&#8217;re done! There&#8217;s a rake task to automagically configure RabbitMQ, and so on, but you should be set up with a nanite initializer to kick off the mapper as well as a file structure and agent generator (nanite in RAILS_ROOT). And from there, it&#8217;s back to learning. I&#8217;m still getting to grips with the actor/agent side of things and working out how to set that all up. I&#8217;ll update this post if I find some more useful info, but this lot was fairly scarcely spread over the &#8216;net so I figure it&#8217;ll be some use to people at any rate. If anyone has any guides on how to work with Nanite that I&#8217;m hugely overlooking then let me know, but it&#8217;s a shame as far as I can see that Nanite has such sparse documentation on actual real-world usage. Ho hum. Still looks like it could work really well if I can get it working.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2009/05/getting-started-with-rails-and-nanite/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Looking to the future of EVE Metrics</title>
		<link>http://www.talkunafraid.co.uk/2009/04/looking-to-the-future-of-eve-metrics/</link>
		<comments>http://www.talkunafraid.co.uk/2009/04/looking-to-the-future-of-eve-metrics/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 20:50:08 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[EVE]]></category>
		<category><![CDATA[EVE Metrics]]></category>
		<category><![CDATA[MMMetrics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[eve metrics]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=286</guid>
		<description><![CDATA[EVE Metrics has become a disorganised, sprawling project. A year or two ago I set out with the idea in my head to build something like EVE Central, but for as much data as possible. I&#8217;m a data junkie in a way- I&#8217;m the sort of person who gets a bit of a kick from [...]]]></description>
			<content:encoded><![CDATA[<p>EVE Metrics has become a disorganised, sprawling project. A year or two ago I set out with the idea in my head to build something like EVE Central, but for as much data as possible. I&#8217;m a data junkie in a way- I&#8217;m the sort of person who gets a bit of a kick from being able to see complex relationships between seemingly unrelated data and do that sort of analysis on a large scale. In short- &lt;3 databases. I set out to do this with very little Ruby/Rails experience, a fairly solid MySQL experience after my earlier projects doing high-volume event logging using Garry&#8217;s Mod for Half-Life 2 to provide an audit trail for an FPS-based roleplaying environment, and a modicum of webapp experience.</p>
<p>What I hadn&#8217;t really considered was the market. Read on to read a short bit of background and find out where the site&#8217;s heading.</p>
<p><span id="more-286"></span></p>
<p>EVE Metrics originally started out as a statistics aggregator for <em>everything</em>. I figured I could pull in killboard data, market data, map data, everything the API offered, and roll it into a huge database and make pretty statistics. After sitting down and thinking I thought that tackling one bit at a time would be a good plan- so I started with the market. It seemed logical; the largest bit of the project, in theory, and interconnected with all other elements of EVE at some level.</p>
<p>The market is <em>huge</em>. And it&#8217;s really interesting, if you&#8217;re into large-scale datasets, statistics and computational economics. After about 6 months of dabbling in the various APIs and getting Salvis working with me on the uploader, I started to harbour increasing envy towards Dr.  Eyjólfur Guðmundsson &#8211; CCP&#8217;s resident EVE economist. Having a job working on the market has gotta be awesome, honestly.</p>
<p>And then with the project in a &#8216;hey, stuff sorta works!&#8217; state, Hexxx from EBANK went ahead and plugged it. We recently hit the 1,000 user mark, which I&#8217;m hugely proud of. But there&#8217;s a catch, of course&#8230;</p>
<p>Right now the database holds:</p>
<ul>
<li>1,936,686 unique market orders</li>
<li>11,082,158 historic price indexes</li>
<li>10,330,669 historic movement records</li>
<li>606,091 EVE Metrics API call records</li>
<li>117,914 bits of uploaded data still waiting to be imported</li>
<li>2,069,769 historic system jump histories</li>
<li>1,968,425 historic system kill histories</li>
<li>165,798 non-market price reports</li>
</ul>
<p>It&#8217;s a lot of data. But the way in which it&#8217;s organised and structured, and most importantly the processes involved in getting the data in and analysing it, are not designed for this kind of volume. I figured I&#8217;d have a few thousand orders in this, but the cache uploader changed that. We got some people in Jita and other trade hubs interested and they&#8217;re just churning out uploads- over half a million distinct uploads so far- which results in a lot of data.</p>
<p>Right now, EVE Metrics grabs the upload when it hits our API, stuffs it in a job queue, and forgets about it. Some behind-the-scenes workers perform an upload filtering algoritm which marks any outliers in the uploaded data, mark old orders in the database as expired, and then add any new orders and update existing ones. Then the raw data is thrown back in the queue to be sent out to users of the Webhook service, and then discarded. When you go to a page, then, we get to do the following:</p>
<ul>
<li>Retrieve all the market orders for that item that aren&#8217;t expired or outliers for the regions the user has set as favourites or default market regions</li>
<li>Split the dataset up into Jita/non-Jita and buy/sell arrays</li>
<li>Crunch numbers to generate averages for those arrays</li>
<li>Render all the market orders on the webpage, including loading in all the appropriate system/station/region data for each order</li>
</ul>
<p>The first three steps take a little while. On the larger orders the mere step of retrieval from the database can take multiple seconds. And that&#8217;s no good. We want millisecond response times. EVE Metrics should be snappy, responsive. Upload processing can take a whole 20 seconds for a Jita upload of tritanium- the backlog of nearly 120,000 jobs should speak worlds about how ungood that is.</p>
<p>And all this leads to unhappy servers, which lead to broken websites and unhappy users, and that&#8217;s no good.</p>
<p>So, I&#8217;m hitting the reset button.</p>
<p>The data will remain, your user accounts will be ported over, and I will endeavour to keep legacy APIs supported and old links redirecting to their new homes. But the codebase and website will be entirely new. The frontend will be getting a new skin which is minimalist and flexible and has proven to be very popular with users of <a href="http://accview.mmmetrics.co.uk">accVIEW</a> in the past month.</p>
<p>I&#8217;ll be writing everything for speed, performance, and general scalability. I want this to perform well under all circumstances and have a delay from viewing an item in EVE to having the new data on the site of under a minute. And I&#8217;m going to be writing tests for everything to ensure behaviour of the site is predictable and doesn&#8217;t randomly break.</p>
<p>On the downside, EVE Metrics will be hobbling along unmaintained for a month or two while I write EM2. It&#8217;s managing fine now, mind you, but in half a year&#8217;s time it may not be working quite as well&#8230;</p>
<p>I&#8217;ll be posting up a survey for EVE Metrics users to let them decide what they&#8217;d like to see in 2.0. API integration is an absolute certainty, but things like a JS-sidebar-style-market-browser and competition filters are also on the table. I&#8217;d rather hear your opinions now than after I&#8217;ve gotten halfway through doing something that would make your idea really tricky to implement <img src='http://www.talkunafraid.co.uk/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2009/04/looking-to-the-future-of-eve-metrics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The £800 microswitch&#8230; and some other things.</title>
		<link>http://www.talkunafraid.co.uk/2009/03/the-800-microswitch-and-some-other-things/</link>
		<comments>http://www.talkunafraid.co.uk/2009/03/the-800-microswitch-and-some-other-things/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 02:10:36 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[Awesome Stuff]]></category>
		<category><![CDATA[Code Snippets and Examples]]></category>
		<category><![CDATA[EVE Metrics]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Odds and Ends]]></category>
		<category><![CDATA[Add new tag]]></category>
		<category><![CDATA[EVE]]></category>
		<category><![CDATA[eve metrics]]></category>
		<category><![CDATA[fixing]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[MMMetrics]]></category>
		<category><![CDATA[projectors]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[sso]]></category>
		<category><![CDATA[stuffisawesome]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=227</guid>
		<description><![CDATA[OK, so fixing the other projector (an Epson EMP-50) was a little bit trickier than the first one. Problem: It didn&#8217;t power up. No lights. Nothing. Nada. OK, I figured that was a power supply issue. Stripped it down to it&#8217;s component parts (left the optical engine and ballast), spotted the bad connection- this projector [...]]]></description>
			<content:encoded><![CDATA[<p>OK, so fixing the other projector (an Epson EMP-50) was a little bit trickier than the first one.</p>
<p>Problem: It didn&#8217;t power up. No lights. Nothing. Nada. OK, I figured that was a power supply issue. Stripped it down to it&#8217;s component parts (left the optical engine and ballast), spotted the bad connection- this projector had been damaged by being dropped, and the whole frame had warped a bit. This connection, between the IEC connector on the side for power and the horizontal power supply board, had fallen out entirely. Reconnected and resoldered, and subsequently reassembled- and I get a &#8216;circuit error&#8217; when trying to power up.</p>
<p>So, back to the disassembly. Took out the ballast unit on a hunch and spotted a microswitch which a service manual claims detects when the lamp housing is open. Unfortunately, this doesn&#8217;t work too well when the frame&#8217;s a bit bent, so I soldered over that on the mainboard. Reassembled, again.</p>
<p>Getting a little bored with the constant dis/reassembly at this point- and it still doesn&#8217;t start. Bulb struck, which was a great morale booster, but it then shut down and burned it&#8217;s fans at maximum for 5 minutes before turning off. Not too useful.</p>
<p>Poked around a bit and considered these symptoms were similar to what my other projector had- lo and behold, the fan on the smoothing unit is jammed! One of the support struts for the fan was snapped, and a quick spot of superglue fixed that in place and let it spin freely again. Reassembled, and bam! Working projector #2. I&#8217;ll post pics sometime.</p>
<p>All in all that&#8217;s two projectors for £0 which I&#8217;ve gotten working again with long remaining bulb lifes in each. Total resources required: Three screwdrivers, a Torx driver, three forceps (Seriously- best tool I&#8217;ve ever had for electronics work), some narrownose pliers, antistatic gloves and static control kit (to avoid frying the mainboard), soldering iron (Got a new Weller temperature controlled iron, which is doing great), approximately 4mm of solder, a dab of Loctite superglue, an IEC power lead and some spare time. Oh, and lots of caffeine.</p>
<p>If I get a chance tomorrow I&#8217;ll see about throwing a post up about some of the under-the-hood changes I&#8217;ve been making and have planned for EVE Metrics and other sites. I&#8217;m looking more seriously at a single-sign-on solution between all the MMMetrics sites (ISKsense, EM, AccVIEW)- but the question is, if I do a SSO solution why not make that a <em>global</em> SSO solution with OpenID support for pluging in other sites? More to the point, allowing centralised API key management between applications that need it (EVE Metrics would use this to store/retrieve keys) would be great- give application your MMMetrics ID, MMMetrics prompts you to give access to your account data to that site, optionally letting you provide one or more API keys to the site. Kinda like a badass Gatecamper 2 that doesn&#8217;t suck so badly. Thoughts?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2009/03/the-800-microswitch-and-some-other-things/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Killboards Questionnaire Results</title>
		<link>http://www.talkunafraid.co.uk/2009/01/killboards-questionnaire-results/</link>
		<comments>http://www.talkunafraid.co.uk/2009/01/killboards-questionnaire-results/#comments</comments>
		<pubDate>Sun, 11 Jan 2009 18:10:30 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[MMMetrics]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[nexus]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[work in progress]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=183</guid>
		<description><![CDATA[Firstly, an apology- I&#8217;ve not been updating as often as I should perhaps do. This was mostly down to the mild concussion I suffered fairly early on Wednesday morning, which limited my capacity for clear thinking for quite a while. Now, onwards- with a summary of what we got from the killboard questionnaire. Most Wanted [...]]]></description>
			<content:encoded><![CDATA[<p>Firstly, an apology- I&#8217;ve not been updating as often as I should perhaps do. This was mostly down to the mild concussion I suffered fairly early on Wednesday morning, which limited my capacity for clear thinking for quite a while. Now, onwards- with a summary of what we got from the killboard questionnaire.</p>
<p><strong>Most Wanted Features</strong></p>
<ol>
<li>API import of losses and kills</li>
<li>In-detail fitting information/fitting database</li>
<li>Accurate price data</li>
<li>Scoring/points</li>
<li>Standings import</li>
</ol>
<p><strong>Most Wanted Fixes</strong></p>
<ol>
<li>Needs to be quick</li>
<li>Needs to be easily themed and styled</li>
<li>Needs good documentation</li>
<li>Needs a better admin panel than EDK</li>
<li>Needs easier installation</li>
</ol>
<p>Medals and ranks were a close runner up, as were better engagement summary tools.</p>
<p>So, let&#8217;s go into a little more detail and see how we&#8217;re covering each of these for Nexus.</p>
<p><span id="more-183"></span></p>
<p><em>API import of losses and kills</em></p>
<p>Already done! Works a treat. Does corporate feeds as well as personal.</p>
<p><em>In-detail fitting information/fitting database</em></p>
<p>This is built into the killboard. Instead of a kill having associated modules and a ship, we store that as a fitting and reference it from the kill. So we have a fitting database built on the side from the word &#8216;go&#8217;. Of course, kills aren&#8217;t the only way to load in fittings.</p>
<p><em>Accurate price data</em></p>
<p>We have a simple-to-extend framework implemented in Nexus for price sources. Here&#8217;s our EVE Central source.</p>
<div class="geshi no ruby">
<div class="head"># EVE Central Updater</div>
<ol>
<li class="li1">
<div class="de1"><span class="co1"># Author:: Ix Forres</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># Remote API Version:: 2.0</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># Example URI:: http://eve-central.com/api/marketstat?typeid={type_id}</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># Notes:</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">#   No key required for this service</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">class</span> <span class="re2">Nexus::PriceUpdaters::EVECentral</span> <span class="sy0">&amp;</span>lt; <span class="re2">Nexus::PriceUpdaters::Base</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">def</span> get_price</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; r = <span class="re2">Net::HTTP</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="kw4">URI</span>.<span class="me1">parse</span><span class="br0">&#40;</span>@source.<span class="me1">retrieval_url</span>.<span class="kw3">gsub</span><span class="br0">&#40;</span><span class="st0">&#39;{type_id}&#39;</span>,@type.<span class="me1">id</span>.<span class="me1">to_s</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; x = Hpricot<span class="br0">&#40;</span>r<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">return</span> <span class="br0">&#40;</span>x<span class="sy0">/</span><span class="st0">&quot;evec_api&quot;</span><span class="sy0">/</span><span class="st0">&quot;marketstat&quot;</span><span class="sy0">/</span><span class="st0">&quot;type&quot;</span><span class="sy0">/</span><span class="st0">&quot;sell&quot;</span><span class="sy0">/</span><span class="st0">&quot;median&quot;</span><span class="br0">&#41;</span>.<span class="me1">inner_html</span>.<span class="me1">to_f</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">end</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">end</span></div>
</li>
</ol>
</div>
<p>So, there you go. A simple updater. You get a web interface which lets you add sources which use these updaters- setting up the URL, priority, and what that source should be used for. We have this set up in a way which enables you to display different prices to corporation members, alliance members, and so on. If your corporation has in-house shops, those shops can be easily added and used for corporate members.</p>
<p><em>Scoring/points</em></p>
<p>Ooer. We&#8217;ve not gone near this, yet. It&#8217;s always a difficult subject, and plenty of people have plenty of different ideas about how you should do this. Whatever we end up doing, rest assured there will be plenty of flexibility about how the system is configured. Possibly a modular system, though that might be overcomplicating things.</p>
<p><em>Standings Import</em></p>
<p>Again, we&#8217;ve not gone near this yet. We&#8217;re currently using the restful_authentication plugin with some extra filters (fc_required, admin_required, and so on). This isn&#8217;t great. One of the things we need to do is to move over to a more flexible framework (we&#8217;re looking at Lockdown) for authentication, and set up a proper usergroup/permission system. For example, you might want everyone in certain alliances/corps to have access to reimbursement, but not everyone you&#8217;re blue to or your alliance is blue to. It&#8217;s a can of worms, programatically, and we&#8217;re leaving it till we&#8217;ve got the basics sorted.</p>
<p><em>Needs to be quick</em></p>
<p>Ok, no problems here. Not only is the system just faster in design, we&#8217;re also providing extensive support for action and fragment caching in pages, counter caches in the database, and so on. We&#8217;re experiencing great performance for a large number of users on an already overworked server, even without any caching enabled. Caching will support a variety of backends, notably memcached.</p>
<p>There&#8217;s no risk of servers being bogged down by large killmails taking ages to parse and be added as can sometimes occur- when a mail is submitted, it gets put on a queue, and a worker will pick it up in the background. It&#8217;ll appear on the site when the worker&#8217;s done building the kill, checking it&#8217;s sane, and retrieving prices/portraits/corp logos associated with the kill and attackers.</p>
<p><em>Needs to be easily themed/styled<br />
</em></p>
<p>Ok, again, not much work done here. We&#8217;re using Haml for our views by and large, but nothing is stopping you writing Erb templates or anything like that. Views are split into partials where it makes sense (the killboard is so far around 20 templates), and there&#8217;s a global layout which is easily adjusted. Stylesheets are authored with Sass, which gets automatically compiled into a minified .css file. Javascript extras can be done with the included script.aculo.us library, which comes with a lot of effects and handy tools.</p>
<p>Themes are certainly doable and we might add support for this later if there&#8217;s demand for it.</p>
<p>On the same topic of styling/theming, the whole system is written with internationalisation (I18n) support for every aspect of the interface. So if you&#8217;ve got a non-English corp or alliance, you&#8217;ll be able to have Nexus in French, Dutch, German&#8230; whatever people voluntarily translate Nexus into. There&#8217;s around the order of 450 strings to translate, though we&#8217;ve reused quite a few of those so they might need splitting up in places for other languages.</p>
<p><em>Needs good documentation</em></p>
<p>We document all the code inline, and build RDoc from that, so there&#8217;s a goodly starting point there. The official site (when it&#8217;s up) will include user documentation for all the features, as well as administrator guides and tutorials for installation.</p>
<p><em>Needs a better admin panel than EDK</em></p>
<p>Right now I&#8217;d say EDK is winning on this in some ways. We&#8217;re currently lacking a central admin panel. But it&#8217;s a few templates away, and I might get around to it this evening.</p>
<p><em>Needs easier installation</em></p>
<p>I can&#8217;t promise anything! It all depends on the host, really. If your host will let you install gems for your Ruby setup, and will let you run an always-running rake task in the background, and will let you set up a cronjob (Basically: Any VPS host, most shared hosts, any dedicated host) then it&#8217;s a piece of cake. But the always-running Rake task might be a problem for some people, notably those running on shared hosts.</p>
<p>Installation really hasn&#8217;t been looked at in any detail whatsoever. We have a &#8216;developer friendly&#8217; writeup on the Nexus development wiki, but it&#8217;s not for the shared hosters amongst us, and goes through building the Nexus database from the EVE database sources, a step which we want to avoid by providing prepackaged starting templates.</p>
<p>So, there you have it- what you want and what we&#8217;re doing to accomodate you. Of course, we&#8217;re now going to go away and work on what we&#8217;re not doing so well on. I&#8217;ll be pushing up the MMMetrics website in the next week or so, complete with some Nexus screenshots and so on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2009/01/killboards-questionnaire-results/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Workflows in Rails Development</title>
		<link>http://www.talkunafraid.co.uk/2009/01/workflows-in-rails-development/</link>
		<comments>http://www.talkunafraid.co.uk/2009/01/workflows-in-rails-development/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 19:20:01 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[Nexus]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[nexus]]></category>
		<category><![CDATA[qa]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=178</guid>
		<description><![CDATA[What&#8217;s your workflow like for Rails development? For Nexus we&#8217;ve got a fairly good workflow set up, though we&#8217;re only using it with 2 developers. When I&#8217;m working on standalone projects (ISKsense, EVE Metrics, and other sites where there&#8217;s just me working on the code) then I use pretty much the same workflow. Here&#8217;s how [...]]]></description>
			<content:encoded><![CDATA[<p>What&#8217;s your workflow like for Rails development? For Nexus we&#8217;ve got a fairly good workflow set up, though we&#8217;re only using it with 2 developers. When I&#8217;m working on standalone projects (ISKsense, EVE Metrics, and other sites where there&#8217;s just me working on the code) then I use pretty much the same workflow. Here&#8217;s how it works.</p>
<p><a href="http://git-scm.com/">Git</a> (hosted at <a href="http://github.com">github.com</a>) stores the project source code. For a given problem, I fork, make changes, merge back in, and push. That results in the Git repository on Github having the most up-to-date version on the &#8216;master&#8217; branch.</p>
<p>At this point, <a href="http://cruisecontrolrb.thoughtworks.com/">CruiseControl.rb</a> (A great continuous integration tool) picks up the update, and tries to run the full <a href="http://rspec.info/">RSpec</a> test suite on the project. Emails are sent out to all developers when the tests pass or fail, with associated error information if it&#8217;s the latter, as well as a HTML report on our CCrb instance.</p>
<p>Assuming we&#8217;re ready to deploy, I fire up <a href="http://www.capify.org/">Capistrano</a> (an excellent pure-Ruby tool for deployment) on my development box, and run &#8216;cap deploy&#8217;. Capistrano connects to the server, makes a Git clone of the most recent master copy, copies in keys/database configs (So they&#8217;re kept out of Git), migrates the database, and then makes a symlink to the new project so Apache (running Passenger) is updated as to where it should be looking. And voila, we&#8217;re deployed!</p>
<p>I&#8217;d be interested to hear what workflows other people use for Rails development. This works fine, and Git means it scales fairly easily to accept more developers, as well as providing incredibly flexible distributed control (So I can work on my laptop away from the internet, committing, branching and so on as needed). But I&#8217;d be at a loss to make this work on a more complex deployment, say with <a href="http://aws.amazon.com/">EC2</a> or other virtualisation software. A continuous integration tool that played better with RSpec would be awesome, too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2009/01/workflows-in-rails-development/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>EVE Corporation Logo Generator</title>
		<link>http://www.talkunafraid.co.uk/2008/12/eve-corporation-logo-generator/</link>
		<comments>http://www.talkunafraid.co.uk/2008/12/eve-corporation-logo-generator/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 16:57:49 +0000</pubDate>
		<dc:creator>James Harrison</dc:creator>
				<category><![CDATA[Awesome Stuff]]></category>
		<category><![CDATA[Code Snippets and Examples]]></category>
		<category><![CDATA[Nexus]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[corporation]]></category>
		<category><![CDATA[EVE]]></category>
		<category><![CDATA[generator]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rmagick]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.talkunafraid.co.uk/?p=83</guid>
		<description><![CDATA[I figured it was high time something was done about the lack of such a tool- a tool to generate the icons for corporations in EVE Online, which are constructed from three pictures with their related shaders, given the data from the API corporation sheet. So here it is. With many thanks to Entity for [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_81" class="wp-caption alignright" style="width: 74px"><a href="http://assets.talkunafraid.co.uk/2008/12/test2.png" rel="lightbox[83]"><img class="size-full wp-image-81" title="Corp Logo on White Background" src="http://assets.talkunafraid.co.uk/2008/12/test2.png" alt="VAF Logo ftw!" width="64" height="64" /></a><p class="wp-caption-text">VAF Logo ftw!</p></div>
<p>I figured it was high time something was done about the lack of such a tool- a tool to generate the icons for corporations in EVE Online, which are constructed from three pictures with their related shaders, given the data from the API corporation sheet. So here it is. With many thanks to Entity for doing the hard work getting the image data out of EVE and working out the finer details of EVE&#8217;s image formatting.</p>
<p><em>Really can&#8217;t be bothered to host your own? Take a look at my freely available <a href="http://www.talkunafraid.co.uk/2008/12/corporation-logo-server/">corporation logo generator server</a>, which uses this library to provide corporation logos for those of a less technical nature!</em></p>
<p>This is a pure-Ruby library with a bundle of prerendered corporation image components, which are combined at runtime to display the image. It is recommended that you cache corporation logos generated with this plugin.</p>
<div id="attachment_82" class="wp-caption alignleft" style="width: 74px"><a href="http://assets.talkunafraid.co.uk/2008/12/test_transparency.png" rel="lightbox[83]"><img class="size-full wp-image-82" title="Transparent Logos" src="http://assets.talkunafraid.co.uk/2008/12/test_transparency.png" alt="Transparent Logos are also supported" width="64" height="64" /></a><p class="wp-caption-text">Transparent Logos are also supported</p></div>
<p><a href="http://github.com/JamesHarrison/eve_corplogo_generator/tree/master">Browse source/Download (Github)</a></p>
<p>While it&#8217;s designed as a Rails plugin it should work equally well as a standalone pure-Ruby plugin. The only dependency is on RMagick, a Ruby interface to ImageMagick. The library is hosted on Github, so you&#8217;ll need git to grab it, or you can hit the download link on Github to grab a tarball or zip.</p>
<p>Usage is as simple as the following:</p>
<div class="geshi no ruby">
<div class="head">require &#39;eve_corplogo_generator&#39;</div>
<ol>
<li class="li1">
<div class="de1"><span class="re2">Eve::CorporateLogo::Logo</span>.<span class="me1">new</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="nu0">437</span>,<span class="nu0">456</span>,<span class="nu0">478</span><span class="br0">&#93;</span>, <span class="br0">&#91;</span><span class="nu0">674</span>,<span class="nu0">677</span>,<span class="nu0">677</span><span class="br0">&#93;</span>, <span class="st0">&#39;output.png&#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># Optional fourth parameter is a colour name to use as the background.</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1"># Third parameter is optional- blob data can be grabbed using .image.to_blob</span></div>
</li>
</ol>
</div>
<p>If you use this and want to say thanks, please do so with ISK- both to Entity and Ix Forres. As far as I know there should be no legal issues with this, other than to give CCP credit as with all ingame assets used out of game. And, of course, many thanks to CCP for adding the data needed into the API. If you really must, the Python version by Entity is over <a href="http://myeve.eve-online.com/ingameboard.asp?a=topic&amp;threadID=942719">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.talkunafraid.co.uk/2008/12/eve-corporation-logo-generator/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
