<?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>The Fluther Blog &#187; Technical</title>
	<atom:link href="http://blog.fluther.com/category/howd-they-do-that/technical/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.fluther.com</link>
	<description>Tapping and Collecting</description>
	<lastBuildDate>Wed, 21 Mar 2012 10:27:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.3</generator>
		<item>
		<title>How’d they do that? Breaking the server.</title>
		<link>http://blog.fluther.com/howd-they-do-that-breaking-the-server/</link>
		<comments>http://blog.fluther.com/howd-they-do-that-breaking-the-server/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 00:46:15 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[Fluther]]></category>
		<category><![CDATA[How'd they do that?]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://blog.fluther.com/blog/?p=227</guid>
		<description><![CDATA[Some of you may have noticed the hour that Fluther was down this afternoon. I thought I’d give you a little insight into what we’ve&#8230;]]></description>
			<content:encoded><![CDATA[<p>Some of you may have noticed the hour that Fluther was down this afternoon. I thought I’d give you a little insight into what we’ve been I’ve been up to while Bacio fiddles the bits on the server.</p>
<p>Not wanting anyone to accuse us of not running with the cool kids, I decided to implement a STOMP <a href="http://morethanseven.net/2008/09/14/using-python-and-stompserver-get-started-message-q/" target="_blank">messaging queue</a> system* for Fluther in November. Now, whenever a question gets asked we can offload the matching algorithm to a different machine. The result? You get a much snappier Fluther.</p>
<p>I’ve also rewritten our twisted-based notify server to use the message queue as well, so watch out for better emails when there’s activity on your questions.</p>
<p>Here’s how this afternoon went down. Many of these steps are run automatically using our custom capistrano scripts:</p>
<ul>
<li>Post an MOTD that the site will go down.</li>
<li>Remove one of our webservers from behind perlbal, our load balancer. We use this to test our production environment later.</li>
<li>Take the site down. (Disable the fluther apache site, enable the maintenance apache site)</li>
<li>Using capistrano, update all of our servers with the latest messaging code (which we call lemur)</li>
<li>Update all the servers with the latest fluther code</li>
<li>Migrate the database (we’ve just switched over from using a home-brewed capistrano migration system to <a href="http://south.aeracode.org/" target="_blank">south</a>, it’s nifty!)</li>
<li>Update the new notifier codebase (we call it hydra)</li>
<li>Restart all of our processes: apache, lighttpd, memcached, lemur, and hydra</li>
<li>Check the logs to make sure that everything is running.</li>
<li>Use our web server that we’ve taken out of the load balancer to run a few spot tests.</li>
<li>Reenable the website</li>
<li>Add our web server back into the load balancing pool.</li>
</ul>
<p>In practice, there were a few snags (mostly dependency issues with the new codebase), but overall everything is running very smoothly now.</p>
<p> </p>
<p>* The messaging system is a customized version of <a href="http://djangopeople.net/brosner/">Brian Rosner</a>’s engine library and resembles starling — it’s pluggable for different queue types, provides a nice interface for deferring functions, and has sample clients that consume messages off the queue. Let me know if this interests you!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fluther.com/howd-they-do-that-breaking-the-server/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>django + vim</title>
		<link>http://blog.fluther.com/django-vim/</link>
		<comments>http://blog.fluther.com/django-vim/#comments</comments>
		<pubDate>Fri, 17 Oct 2008 20:59:53 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[How'd they do that?]]></category>
		<category><![CDATA[Technical]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.fluther.com/blog/?p=213</guid>
		<description><![CDATA[I’ve finally weaned myself off Komodo, since the vim bindings had just enough tiny errors to annoy me, and I was never satisfied with how&#8230;]]></description>
			<content:encoded><![CDATA[<p>I’ve finally weaned myself off Komodo, since the vim bindings had just enough tiny errors to annoy me, and I was never satisfied with how long it took to find and open a file inside the project.</p>
<p>The one thing I was really missing in vim, though, was solid code-completion feature. After much haranguing, I finally figured out how to enable omnicomplete with django.</p>
<h3 id="Downloadandinstallvim">Download and install vim for OS X</h3>
<ul>
<li>By far the easiest way to get a version of vim that has python compiled is through <a class="ext-link" href="http://www.macports.org/"><span class="icon">macports</span></a>.</p>
<pre class="wiki">sudo port install vim +python
</pre>
</li>
<li>Now replace your old version of vim in your default path (useful for when a shell command calls vim as the editor)
<pre class="wiki">sudo cp /usr/bin/vim /usr/bin/vim7.0
sudo cp /opt/local/bin/vim /usr/bin/vim
</pre>
</li>
<li>Verify that you have python compiled by typing <tt>:python print “Hello”</tt> while in vim
</li>
</ul>
<h3 id="Enableomnicompletion">Enable omnicompletion</h3>
<ul>
<li>I’ve enabled omnicomplete for a bunch of different different completers. Add these lines to your <tt>.vimrc</tt>:</p>
<pre class="wiki">autocmd FileType python set omnifunc=pythoncomplete#Complete
autocmd FileType javascript set omnifunc=javascriptcomplete#CompleteJS
autocmd FileType html set omnifunc=htmlcomplete#CompleteTags
autocmd FileType css set omnifunc=csscomplete#CompleteCSS
</pre>
</li>
</ul>
<h3 id="Runvimsothatyoucanactuallycompletedjangofiles">Run vim so that you can actually complete django files</h3>
<ul>
<li>Omnicomplete imports the modules behind the scenes to help you with completion. Problem is, it won’t be able to import django.db since you don’t have a settings module specified… so any module that imports models won’t work. Not very useful.</p>
<pre class="wiki">DJANGO_SETTINGS_FILE=myapp.settings vim
</pre>
</li>
<li>Verify that imports will work by typing <tt>:python from django import db</tt>
</li>
<li>Now you can just press <tt>&lt;C-X&gt;&lt;C-O&gt;</tt> to omnicomplete!
</li>
</ul>
<p>
I also <strong>highly</strong> recommend the <a class="ext-link" href="http://rope.sourceforge.net/ropevim.html"><span class="icon">rope</span></a> plugin for vim. It simplifies opening files within your project, and even will organize your imports! for you!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fluther.com/django-vim/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>mogileFS for Django</title>
		<link>http://blog.fluther.com/mogilefs-for-django/</link>
		<comments>http://blog.fluther.com/mogilefs-for-django/#comments</comments>
		<pubDate>Fri, 05 Sep 2008 06:28:45 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[Fluther]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://blog.fluther.com/blog/?p=198</guid>
		<description><![CDATA[In preparation for DjangoCon, I thought I’d release a little bit of quickly-written-code (read: easily improvable!) that we use to serve our avatars on Fluther.&#8230;]]></description>
			<content:encoded><![CDATA[<p>In preparation for DjangoCon, I thought I’d release a little bit of quickly-written-code (read: easily improvable!) that we use to serve our avatars on Fluther.</p>
<p>Here’s the basic rundown:</p>
<ol>
<li>Get mogilefs on your box</li>
<li>Patch django to support different FileBackends</li>
<li>Get data into mogile</li>
<li>Get data out of mogile</li>
</ol>
<p><strong>Getting mogile</strong></p>
<p>We use Ubuntu on our production boxes, and it just so happens that I’m the debian maintainer for mogile. So. Get the packages from <a href="https://edge.launchpad.net/~awmcclain/+archive" target="_blank">https://edge.launchpad.net/~awmcclain/+archive</a> (add the entries for your distro onto your source.list, run apt-get update then apt-get install mogilefsd mogstored). Setting up mogile is a little beyond this document, but check out the <a href="http://code.google.com/p/mogilefs/" target="_blank">google group</a> if you have any troubles.</p>
<p> </p>
<p><strong>Patch Django (optional)</strong></p>
<p>I see that Marty’s work has been incoporated into Django’s 1.0 beta (congrats, Marty!), but if you’re running an older version (like we are), you’ll need to patch your codebase to support file storage backends. See the patch at <a href="http://code.djangoproject.com/ticket/5361">http://code.djangoproject.com/ticket/5361</a></p>
<p><strong>Install the mogile backend</strong></p>
<p><a href="http://blog.fluther.com/wp-content/uploads/2008/09/mogilefs_for_django1.zip">Download</a> the zip of the files and throw filestorage.py and mogilefs.py somewhere on your pythonpath. The models.py file contains some example code, as well as an urls entry. </p>
<p><strong>Set up the mogile backend</strong></p>
<p>The mogile filestorage backend is fairly simple: it uses URLs (or, rather, parts of URLs) as keys into the mogile database. When the user requests a file stored by mogile (say, an avatar), the URL gets passed to a view which, using a client to the mogile tracker, retrieves the “correct” path (the path that points to the actual file data). The view will then either return the path(s) to perlbal to reproxy, or, if you’re not using perlbal to reproxy (which you should), it serves the data of the file directly from django.</p>
<p>In order for the backend to work, we need to add a few settings variables:</p>
<ul>
<li>MOGILEFS_DOMAIN: The mogile domain that files should read from/written to, e.g “production”</li>
<li>MOGILEFS_TRACKERS: A list of trackers to connect to, e.g. [“foo.sample.com:7001″,“bar.sample.com:7001″]</li>
<li>MOGILEFS_MEDIA_URL (optional): The prefix for URLs that point to mogile files. This is used in a similar way to MEDIA_URL, e.g. “/mogilefs/”</li>
<li>SERVE_WITH_PERLBAL: Boolean that, when True, will pass the paths back in the response in the ‘X-REPROXY-URL’ header. If False, django will serve all mogile media files itself (bad idea for production, but useful if you’re testing on a setup that doesn’t have perlbal running)</li>
<li>DEFAULT_FILE_STORAGE: This is the class that’s used for the backend. You’ll want to set this to “project.app.filestorage.MogileFSStorage” (or wherever you’ve installed the backend) </li>
</ul>
<p> </p>
<p><strong>Gettings files into mogile </strong></p>
<p>The great thing about file backends is that we just need to specify the backend in the model file and everything is taken care for us — all the default save() methods work correctly.</p>
<p>For Fluther, we have two main media types we use mogile for: avatars and thumbnails. Mogile defines “classes” that dictate how each type of file is replicated — so you can make sure you have 3 copies of the original avatar but only 1 of the thumbnail.</p>
<p>In order for classes to behave nicely with the backend framework, we’ve had to do a little tomfoolery. (This is something that may change in future versions of the filestorage framework).</p>
<p>Here’s what the models.py file looks like for the avatars:</p>
<div class="highlight">
<pre><span style="color: #007020; font-weight: bold">from</span> <span style="color: #0e84b5; font-weight: bold">django.core.filestorage</span> <span style="color: #007020; font-weight: bold">import</span> storage</pre>
<pre><span style="color: #60a0b0; font-style: italic"># TODO: Find a better way to deal with classes. Maybe a generator?</span>
<span style="color: #007020; font-weight: bold">class</span> <span style="color: #0e84b5; font-weight: bold">AvatarStorage</span>(storage<span style="color: #666666">.</span>__class__):
    mogile_class <span style="color: #666666">=</span> <span style="color: #4070a0">'avatar'</span> </pre>
<pre><span style="color: #007020; font-weight: bold">class</span> <span style="color: #0e84b5; font-weight: bold">ThumbnailStorage</span>(storage<span style="color: #666666">.</span>__class__):
    mogile_class <span style="color: #666666">=</span> <span style="color: #4070a0">'thumb'</span>

<span style="color: #007020; font-weight: bold">class</span> <span style="color: #0e84b5; font-weight: bold">Avatar</span>(models<span style="color: #666666">.</span>Model):
    user <span style="color: #666666">=</span> models<span style="color: #666666">.</span><span style="color: #007020">ForeignKey</span>(User, null<span style="color: #666666">=</span><span style="color: #007020">True</span>, blank<span style="color: #666666">=</span><span style="color: #007020">True</span>)
    image <span style="color: #666666">=</span> models<span style="color: #666666">.</span><span style="color: #007020">ImageField</span>(storage<span style="color: #666666">=</span>AvatarStorage())
    thumb <span style="color: #666666">=</span> models<span style="color: #666666">.</span><span style="color: #007020">ImageField</span>(storage<span style="color: #666666">=</span>ThumbnailStorage())</pre>
</div>
<p>Each of the custom storage classes defines a “class” attribute which gets passed to the mogile backend behind the scenes.  If you don’t want to worry about mogile classes, don’t need to define a custom storage engine or specify it in the field — the default should work just fine.</p>
<p><strong>Serving files from mogile</strong></p>
<p><strong></strong> Now, all we need to do is plug in the view that serves up mogile data. Here’s what we use:</p>
<div class="highlight">
<pre>urlpatterns <span style="color: #666666">+=</span> patterns(<span style="color: #4070a0">''</span>,
    (<span style="color: #4070a0">r'^</span><span style="color: #70a0d0; font-style: italic">%s</span><span style="color: #4070a0">(?P&lt;key&gt;.*)'</span> <span style="color: #666666">%</span> settings<span style="color: #666666">.</span>MOGILEFS_MEDIA_URL[<span style="color: #40a070">1</span>:], <span style="color: #4070a0">'panda.main.filestorage.serve_mogilefs_file'</span>)
)</pre>
</div>
<p>Any url beginning with the value of MOGILEFS_MEDIA_URL will get passed to our view. Since MOGILEFS_MEDIA_URL requires a leading slash (like MEDIA_URL), we strip that off and pass the rest of the url over to the view.</p>
<p>That’s it! Happy mogiling!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fluther.com/mogilefs-for-django/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.558 seconds -->

