<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Notes on Notes</title>
    <link>https://www.simplicidade.org/notes/index.xml</link>
    <description>Recent content in Notes on Notes</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>melo@simplicidade.org (Pedro Melo)</managingEditor>
    <webMaster>melo@simplicidade.org (Pedro Melo)</webMaster>
    <copyright>(c) 2016 Pedro Melo.</copyright>
    <lastBuildDate>Thu, 30 Mar 2017 22:37:08 +0000</lastBuildDate>
    <atom:link href="/notes/index.xml" rel="self" type="application/rss+xml" />
    <atom:link rel="hub" href="https://pubsuhhubbub.superfeedr.com/"/>
    
    <item>
      <title>New Mac</title>
      <link>https://www.simplicidade.org/notes/2017/03/30/new-mac/</link>
      <pubDate>Thu, 30 Mar 2017 22:37:08 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2017/03/30/new-mac/</guid>
      <description>&lt;p&gt;I got a new Mac at work a couple of weeks back and I&amp;rsquo;ve been slowly moving my life to it. It is the new Macbook Pro 13&amp;rdquo; with a 2.9GHz i5 and Touch Bar. The only upgrade I did was bumping the memory to 16GB.&lt;/p&gt;

&lt;p&gt;For comparison, my previous Mac was still a Late 2008 Macbook, fully upgraded with the unofficially supported 8GB and after market SSD (two in fact, replaced the DVD a year back with a second SSD). And yes, apart from the slowness (a 2.0GHz Core 2 Duo can take only so far these days&amp;hellip;) it is still a perfectly good Mac, and I still use it on occasion.&lt;/p&gt;

&lt;p&gt;The build quality on the new Mac is excellent with one exception. I don&amp;rsquo;t like the keyboard at all, it is too shallow for me. On the other hand, 99% of the time I use an external keyboard, so I can live with it. Still, I would trade a thicker laptop for a better keyboard. This is a &amp;ldquo;feeling&amp;rdquo;-thing. In actual use the keyboard is precise enough for my casual needs, I just don&amp;rsquo;t like shallow keyboards.&lt;/p&gt;

&lt;p&gt;The screen is wonderful, but don&amp;rsquo;t get to enjoy it much because I mostly use the Mac with non-retina external displays. Compared to the old Macbook the difference is striking.&lt;/p&gt;

&lt;p&gt;The SSD is wicked fast, it feels like magic, and I love having 8 hours of battery. This are actual real life number for my usage: text editors, Perl, a bit of Go, and a light Docker - heavy Docker cuts this to 5 to 6 hours.&lt;/p&gt;

&lt;p&gt;The Touch Bar is useless to me. Even when I&amp;rsquo;m using the laptop keyboard, there is very little that the Touch Bar provides that makes my life simpler or more productive. As productivity enhancer, I don&amp;rsquo;t have many needs for an analog input mechanism. The only thing analog that I use in there is the sound and brightness controls, and I&amp;rsquo;m perfectly happy with the keys for those on my external keyboard.&lt;/p&gt;

&lt;p&gt;I do really miss the Esc key&amp;hellip;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve thought about of exchanging this one with the model without a Touch Bar, but that one is inferior in at least two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;only has two USB-C ports: yes, this is relevant, see below;&lt;/li&gt;
&lt;li&gt;the CPU is 30% slower, and even with the upgrade you don&amp;rsquo;t reach the less expensive Touch Bar model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also remember reading that the internal Thunderbolt is half the capacity of the Touch Bar models, but I don&amp;rsquo;t have the reference at hand at the moment.&lt;/p&gt;

&lt;p&gt;So I&amp;rsquo;m keeping the four-port Touch Bar model.&lt;/p&gt;

&lt;p&gt;Regarding dongles, yes, they are unfortunate, but I like the fact that I now have a laptop with USB-C 3.1 and TB3. I can plug some really nice external devices with this, and I don&amp;rsquo;t mind this dongle iteration. Over the years I&amp;rsquo;ve owned and used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;serial DB9 mice, DIN-5 keyboards, and parallel port printers;&lt;/li&gt;
&lt;li&gt;DIN-6, PS/2 style, keyboards and mice;&lt;/li&gt;
&lt;li&gt;USB-A, USB-B, and all the mini and micro variants;&lt;/li&gt;
&lt;li&gt;SCSI-I, -II cables;&lt;/li&gt;
&lt;li&gt;Firewire 400 and Firewire 800;&lt;/li&gt;
&lt;li&gt;VGA, DVI, HDMI, and too many display port variants.
&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;rsquo;m not naive enough to believe that this will be the last interface type, but I&amp;rsquo;m hopeful that it lasts as long as USB-A did. If he can do that, at the physical connector level, I&amp;rsquo;ll be happy enough.&lt;/p&gt;

&lt;p&gt;I mentioned above that I needed more than 2 ports. This is true. I currently have the following adapters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a Multi-AV VGA adapter from Apple: VGA and one USB-A, plus power passthrough - this is a decent mini-docking station for the office;&lt;/li&gt;
&lt;li&gt;a Gigabit ethernet adapter from Belkin: due to my work, a physical network connection is a requirement;&lt;/li&gt;
&lt;li&gt;a external SSD USB-C 3.1 Gen2 enclosure: really really fast - and the best way to keep a set of large git repos and build tools between two computers - the speed is very good over USB 3.1 Gen2;&lt;/li&gt;
&lt;li&gt;a Apple USB-C to USB-C connector: this one works, there are a lot of really bad dongles out there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I need at least three ports at the office, I can live with two during the weekend but I can&amp;rsquo;t connect to the external display at home. I might need to buy another AV connector there, but I&amp;rsquo;m looking into other options.&lt;/p&gt;

&lt;p&gt;My hope is to see a decent 27&amp;rdquo; or 30&amp;rdquo; display, TB3, with two USB-A, a ethernet port, and hopefully one or two USB-C or TB3 ports. That would be the perfect docking station for me. The idiotic LG 5K is a TB3 monitor but has no extra ports!&lt;/p&gt;

&lt;p&gt;One final warning: I bought a USB-C =&amp;gt; 3x USB-A + Ethernet adapter at a local retailer (identical to &lt;a href=&#34;https://www.amazon.co.uk/Gigabit-Ethernet-Adapter-MacBook-Devices/dp/B00WFQPTLM/ref=sr_1_5?s=computers&amp;amp;amp;ie=UTF8&amp;amp;amp;qid=1490913269&amp;amp;amp;sr=1-5&amp;amp;amp;keywords=usb-c+usb-a+ethernet+adapter&#34;&gt;this one&lt;/a&gt; but from another brand). This is a low-quality dongle. The USB-A and Ethernet ports work fine, but the moment you plug it in, the Wifi connection dies. This is most likely related to poor shielding somewhere.&lt;/p&gt;

&lt;p&gt;In terms of build to order upgrades, I would recommend that you at the very least max out the RAM: you won&amp;rsquo;t be able to do it later, and a Mac with 16GB of RAM will last a couple of years more. If you do any type of virtualisation or Docker, you will see a big difference.&lt;/p&gt;

&lt;p&gt;After the memory, it depends. I don&amp;rsquo;t value CPU power that much, the i5 I have is more than enough, but others might. I think my second upgrade would be bumping the SSD to 512GB if you have big iTunes libraries like me.&lt;/p&gt;

&lt;p&gt;Now the big question: would I buy the new Macbook Pro again, or would I go back to the previous generation without USB-C ports? I think this is easy to answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if you are a true road warrior, moving from place to place, and with a myriad of connectivity scenarios, you will probably be better served with the previous model, without USB-C - you will save a lot on dongles to cary around and loose. I might change my mind if a small USB-C dock, with video (VGA + HDMI), USB and ethernet shows up soon;&lt;/li&gt;
&lt;li&gt;if not, if you are mostly stuck to a desk or move between one or two places, I recommend the new one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We&amp;rsquo;ll talk again in 8 years.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>User interaction is not allowed</title>
      <link>https://www.simplicidade.org/notes/2017/03/24/user-interaction-is-not-allowed/</link>
      <pubDate>Fri, 24 Mar 2017 18:23:03 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2017/03/24/user-interaction-is-not-allowed/</guid>
      <description>&lt;p&gt;This errors happened to me sometime ago, but today I saw it again on a coworker Mac.&lt;/p&gt;

&lt;p&gt;You&amp;rsquo;ll get the error on the Terminal, with commands that want to use MacOS Keychain passwords. I&amp;rsquo;m sure there is another element at work here, but I could not find it.&lt;/p&gt;

&lt;p&gt;In this case, the error on &lt;code&gt;docker login&lt;/code&gt; was this (you&amp;rsquo;ll get a similar error with &lt;code&gt;git fetch&lt;/code&gt; or &lt;code&gt;git pull&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Error saving credentials: error storing credentials - err: exit status 1, out: `User interaction is not allowed`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The command line tool is trying to access a Keychain Item, and this item is protected to only be used by some applications. On normal conditions, this would trigger a graphical pop-up asking for permission for this new application to access said item, but in this case he fails to launch the pop-up and therefore, rejects the action.&lt;/p&gt;

&lt;p&gt;To fix, open the Keychain Access application, search for the domain you were trying to access (in the case of &lt;code&gt;docker login&lt;/code&gt; it would be the private registry address, or &lt;code&gt;hub.docker.com&lt;/code&gt;), edit the entry, select the tab &amp;ldquo;Access Control&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.simplicidade.org/img/user_interaction_not_allowed_screenshot_1.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;

&lt;p&gt;You can then add permission to the application you need by taping the &amp;ldquo;+&amp;rdquo; button on the lower left, and picking the correct file, but I don&amp;rsquo;t have a easy way to discover what is the correct file to add. If the problem is &lt;code&gt;docker login&lt;/code&gt; you could first try to add the command &lt;code&gt;/Applications/Docker.app/Contents/Resources/bin/docker-credential-osxkeychain.bin&lt;/code&gt;. For &lt;code&gt;git pull&lt;/code&gt; or &lt;code&gt;git fetch&lt;/code&gt; issues, try to add &lt;code&gt;/Library/Developer/CommandLineTools/usr/libexec/git-core/git-credential-osxkeychain&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you don&amp;rsquo;t know which command line application is the culprit, you can just disable access control for this password item by making sure that the &amp;ldquo;Allow all applications to access this item&amp;rdquo; option is selected and &amp;ldquo;Save Changes&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;You should try to find the correct application if possible, but the second options will work. No security, but it would work.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Question mark dock icons</title>
      <link>https://www.simplicidade.org/notes/2017/03/17/question-mark-dock-icons/</link>
      <pubDate>Fri, 17 Mar 2017 08:55:02 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2017/03/17/question-mark-dock-icons/</guid>
      <description>&lt;p&gt;On my new Mac (more on that later), I&amp;rsquo;ve noticed that some apps (in my case Slack and Mattermost) would revert to big gray question mark icons when I restarted them.&lt;/p&gt;

&lt;p&gt;The key piece of information that set me on the right path was  &lt;a href=&#34;https://forums.vandyke.com/showthread.php?t=12513#post46546&#34;&gt;a comment &lt;/a&gt; on the Vandyke support forum.&lt;/p&gt;

&lt;p&gt;While that solution worked for me, it seemed a bit too geeky. When you copied the app from the DMG or Download folder into Applications, Finder should have taken care of this for you.&lt;/p&gt;

&lt;p&gt;My simpler solution: quit the application, drag it out of the Applications folder (to the desktop or another place, not important), and then copy it back to Applications.&lt;/p&gt;

&lt;p&gt;This worked for me.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>brew info</title>
      <link>https://www.simplicidade.org/notes/2017/03/17/brew-info/</link>
      <pubDate>Fri, 17 Mar 2017 08:40:15 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2017/03/17/brew-info/</guid>
      <description>&lt;p&gt;Small, quick, tip: before installing the latest wow app with &lt;code&gt;brew install wow-app&lt;/code&gt;, take a minute to scan &lt;code&gt;brew info wow-app&lt;/code&gt; in a separate terminal.&lt;/p&gt;

&lt;p&gt;Two main reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;some of the time, it will tell you that you have a lot of options to enable or disable some features. You might need some of them, and usually this requires a new compilation;&lt;/li&gt;
&lt;li&gt;most of the time this includes what next steps are required of you to properly configure, and you can read them while the app installs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either way, this will save you some time, and you might learn something new.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Where to eat: Figueira da Foz edition</title>
      <link>https://www.simplicidade.org/notes/2016/09/22/where-to-eat-figueira-da-foz-edition/</link>
      <pubDate>Thu, 22 Sep 2016 00:36:51 +0100</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2016/09/22/where-to-eat-figueira-da-foz-edition/</guid>
      <description>&lt;p&gt;A friend asked for good places to eat around Figueira da Foz, where I live.&lt;/p&gt;

&lt;p&gt;He was not the first, it is a common request, so I wrote a page with some of the places I go to on a regular basis.&lt;/p&gt;

&lt;p&gt;So enjoy, &lt;a href=&#34;https://www.simplicidade.org/eat/figueira_da_foz/&#34;&gt;Eating in Figueira da Foz&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>iOS (null) Applications</title>
      <link>https://www.simplicidade.org/notes/2016/08/27/ios-null-applications/</link>
      <pubDate>Sat, 27 Aug 2016 07:21:48 +0100</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2016/08/27/ios-null-applications/</guid>
      <description>&lt;p&gt;Over the past weeks, I wasn&amp;rsquo;t able to complete any of my iPhone backups, and without a backup (actually two, iCloud and iTunes, just because) I didn&amp;rsquo;t want to upgrade to the latest iOS. Last night I decided to investigate why.&lt;/p&gt;

&lt;p&gt;The Console.app error I got was this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;26/8/16 10:28:09.285 PM AppleMobileBackup[42056]: ERROR: Backup message response:
     101 Unable to open domain directory: No such file or directory (2) at path
     &amp;quot;/var/mobile/Containers/Shared/AppGroup/453DA9D8-45A4-4B88-9D43-57A5772B6C57&amp;quot;
     (MBErrorDomain/101)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not very useful. I guessed that if I could find which app it was, I could delete it, but googling for &lt;code&gt;453DA9D8-45A4-4B88-9D43-57A5772B6C57&lt;/code&gt; or parts of it didn&amp;rsquo;t give me any hints.&lt;/p&gt;

&lt;p&gt;Eventually, while browsing &lt;em&gt;Definitions &amp;gt; General &amp;gt; Storage and iCloud Usage &amp;gt; Manage Storage&lt;/em&gt; I found a application without an icon:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.simplicidade.org/img/ios_null_applications/ios_null_app.png&#34; alt=&#34;My (null) application, lots of useful information...&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Selecting it I was able to see just two things: the version and the size, nothing more.&lt;/p&gt;

&lt;p&gt;I searched a bit about these &lt;em&gt;(null)&lt;/em&gt; applications and there are a lot of tips and tricks to delete them. In my case, deleting it by long-press and using the small &lt;em&gt;x&lt;/em&gt; didn&amp;rsquo;t work, neither going to the &lt;em&gt;Manage Storage&lt;/em&gt; section of the definitions and deleting it from there.&lt;/p&gt;

&lt;p&gt;The other solution was finding out what the application was, using the size as a guide, and installing it again.&lt;/p&gt;

&lt;p&gt;It turns out that there is a simple way of figuring out which application it is based on size. I opened iTunes, and inspected the iPhone apps, sorted by size, and it was very simple to identify it:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://www.simplicidade.org/img/ios_null_applications/itunes_by_size.png&#34; alt=&#34;Jackpot!&#34; /&gt;&lt;/p&gt;

&lt;p&gt;I was now pretty sure that this was the application that got stuck. Unfortunately, re-installing it did not solve the issue, the application was now stuck on installation, and removing it was still impossible.&lt;/p&gt;

&lt;p&gt;I decided to use iTunes to try and do it. I clicked the &lt;em&gt;Remove&lt;/em&gt; button in the image above, and sync&amp;rsquo;ed my iPhone. This worked, and the application was removed.&lt;/p&gt;

&lt;p&gt;With this application out of the way, I was able to complete my iPhone backups and upgrade to the latest iOS.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Crossroads</title>
      <link>https://www.simplicidade.org/notes/2016/08/10/crossroads/</link>
      <pubDate>Wed, 10 Aug 2016 11:39:31 +0100</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2016/08/10/crossroads/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve finished reading &lt;a href=&#34;https://queue.acm.org/detail.cfm?id=2349257&#34;&gt;A Generation Lost in the Bazaar&lt;/a&gt; by Poul-Henning Kamp (of Varnish fame).&lt;/p&gt;

&lt;p&gt;The key takeaway is simple enough: quality happens only when someone is responsible for it.&lt;/p&gt;

&lt;p&gt;Right now, I&amp;rsquo;m working on my personal/family project, modernising the infrastructure of a 16 years old Perl application, and moving some parts to other languages to make it easier for us to hire resources. I love Perl, and still is my favourite language, but getting people to work on it in Portugal is a very hard proposition.&lt;/p&gt;

&lt;p&gt;But the future is uncertain. What should I do after I finish this task? So I go back to what I&amp;rsquo;ve been doing over the past three years, managing a team of developers, nurturing young talent and give freedom and cover to senior developers to do its thing?&lt;/p&gt;

&lt;p&gt;Or should I keep it small, build the hand-full of services I would like to build, not something that is brand spanking new, but my own personal view how those systems should be work? Be one more SaaS out there, selling my work directly to companies?&lt;/p&gt;

&lt;p&gt;Should I go back to the factories, or go for the boutique?&lt;/p&gt;

&lt;p&gt;I honestly don&amp;rsquo;t know yet&amp;hellip; There are still somethings I would like to do, that are only available at a factory. But the thing is, one of the major decisive points to leave my previous employer was that I could not longer control the quality of the work my team was doing, and that is a position where I never want to be again.&lt;/p&gt;

&lt;p&gt;Quality happens only when someone is responsible for it. And I want to be that someone, somewhere. Just not sure where that will be.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Phoenix, take 2</title>
      <link>https://www.simplicidade.org/notes/2016/07/26/phoenix-take-2/</link>
      <pubDate>Tue, 26 Jul 2016 13:06:25 +0100</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2016/07/26/phoenix-take-2/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In Greek mythology, a phoenix or phenix (Greek: φοῖνιξ phoinix; Latin: phoenix, phœnix, fenix) is a long-lived bird that is cyclically regenerated or reborn.
&amp;ndash; via Wikipedia, Phoenix (Mythology) entry&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A couple months back, the server where this site was hosted died in a horrible disk crash. I had (more or less) decent backups so nothing was lost, but the time to bring it back to life didn&amp;rsquo;t materialize. For the past 3+ years, I was deeply involved with a couple of eCommerce sites that took all my free time.&lt;/p&gt;

&lt;p&gt;I left my previous employer on June 30th, and took a couple weeks of holidays to be with the family. And now I&amp;rsquo;m back to figure out what to do next.&lt;/p&gt;

&lt;p&gt;For the past years, I felt the need to write about current events and technical issues that I found interesting, but lacked the place to do it. So one of the first priorities I had was to recover this site. The previous setup was still using a &lt;a href=&#34;https://movabletype.org/&#34;&gt;Movable Type&lt;/a&gt; 3.x installation, but I wanted some sort of modern setup, with the same &amp;ldquo;burn to static files&amp;rdquo; approach that MT had. I decided to use &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; as it seems a very sensible and straightforward solution to the problem, and it is written in &lt;a href=&#34;https://gohugo.io/&#34;&gt;Go&lt;/a&gt;, a language that I&amp;rsquo;ve been learning over the past year or so. I also picked the &lt;a href=&#34;https://github.com/enten/hyde-y&#34;&gt;Hyde-y theme for Hugo&lt;/a&gt; as a simple enough layout. Not sure if it will stick, but good enough for now.&lt;/p&gt;

&lt;p&gt;To avoid any further hosting snafu&amp;rsquo;s, I&amp;rsquo;m publishing the site using &lt;a href=&#34;https://pages.github.com/&#34;&gt;GitHub pages&lt;/a&gt;. This unfortunately means that I have to update the RSS feed URL. You should use &lt;a href=&#34;https://www.simplicidade.org/index.xml&#34;&gt;&lt;code&gt;https://www.simplicidade.org/index.xml&lt;/code&gt;&lt;/a&gt; to subscribe to updates.&lt;/p&gt;

&lt;p&gt;Next steps was to convert/copy the old MT posts to this new site, and add a couple of alias to make the old URLs work properly. This is still work in progress, I&amp;rsquo;ve placed the scripts I&amp;rsquo;m using in a new repository, &lt;a href=&#34;https://github.com/melo/movable_type2hugo&#34;&gt;movable_type2hugo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It was not ready yet, still needs tweaking, but I got everything back. I had to migrate some posts from DB (with all the original metadata), some by scraping the static HTML pages that MT generated, and others from &lt;a href=&#34;https://www.red-sweater.com/marsedit/&#34;&gt;MarsEdit&lt;/a&gt;, with only some of the metadata. For some reason, my backup has all the HTML pages for the site, but the DB that was backed up at the same time, only has some of the pages. Weird.&lt;/p&gt;

&lt;p&gt;Most of the previous &lt;a href=&#34;https://www.simplicidade.org/notes/2014/05/13/phoenix/&#34;&gt;Phoenix&lt;/a&gt; post is still valid, but now I&amp;rsquo;m back for more.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Fat scripts</title>
      <link>https://www.simplicidade.org/notes/2014/11/12/fat-scripts/</link>
      <pubDate>Wed, 12 Nov 2014 21:53:19 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2014/11/12/fat-scripts/</guid>
      <description>&lt;p&gt;Recently we installed &lt;a href=&#34;http://hipchat.com&#34;&gt;HipChat&lt;/a&gt; at the office, and I want to write a small script to send messages to it. To make it easier for others to use I wanted to distributed it as a single standalone script, no dependencies.&lt;/p&gt;

&lt;p&gt;I wrote the script, &lt;a href=&#34;https://gist.github.com/melo/a1b05a0d2cc95a4ec843&#34;&gt;x-hipchat&lt;/a&gt;, with all the bells and whistles I felt were important, and then turned to the process of pack it into a single no-dependencies script. The simplest method I could find is &lt;a href=&#34;https://metacpan.org/release/App-fatten&#34;&gt;App::fatten&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For best results, you should create a configuration file somewhere, and use the &lt;code&gt;--config-path&lt;/code&gt; to point to it. In fact, if you don&amp;rsquo;t create it, you keep getting &amp;ldquo;ERROR 412: Profile &amp;lsquo;your-script-name&amp;rsquo; not found in configuration file&amp;rdquo;. In the configuration file, the section name is the base name of your script. My config file looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[profile=x-hipchat]
overwrite=1
exclude_core=1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first attempts ran fine, but the fat script failed to find &lt;code&gt;JSON::backportedPP&lt;/code&gt; and later &lt;code&gt;HTTP::Tiny&lt;/code&gt;. And if I manually included them with &lt;code&gt;include=MODULE&lt;/code&gt; on my config file (oh, there is a bug in 0.13, if put a single &lt;code&gt;include&lt;/code&gt; statement, it borks - &lt;a href=&#34;https://github.com/perlancar/perl-App-fatten/issues/3&#34;&gt;issue open&lt;/a&gt;), &lt;code&gt;HTTP::Tiny&lt;/code&gt; will die later on, I&amp;rsquo;m guessing because some of the internal modules that HTTP::Tiny could not be found.&lt;/p&gt;

&lt;p&gt;I tried to use &lt;code&gt;trace_method=prereqscanner_lite_recurse&lt;/code&gt; configuration option and &lt;code&gt;fatten&lt;/code&gt; found more modules, but too many to include, and some were Core, which caused problems with a different version of perl.&lt;/p&gt;

&lt;p&gt;The final solution for this was to install with perlbrew a older version of perl (I choose 5.10.1), and create a perlbrew lib just for packing:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;perlbrew install -j 4 perl-5.10.1
perlbrew lib create perl-5.10.1@fatten
perlbrew use perl-5.10.1@fatten
cpanm App::fatten Module::CoreList
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(we force &lt;code&gt;Module::CoreList&lt;/code&gt; because &lt;code&gt;App::tracepm&lt;/code&gt; requires a more recent version that she declares.)&lt;/p&gt;

&lt;p&gt;This gives me a sufficiently old perl that lacks most of the more recent core modules, and will force them into the script. This actually helped, but I still got &amp;ldquo;599 Internal Exception&amp;rdquo; from &lt;code&gt;HTTP::Tiny&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I switched to &lt;code&gt;trace_method=require&lt;/code&gt; that actually runs your code. This is much better because a lot of modules are only loaded later, when needed. Here &lt;code&gt;App::fatten&lt;/code&gt; could make my life easier. My script requires parameters but I could not find a way of pass them. A command line option to give extra parameters to the program would be nice. Fortunately I had environment variables for most options, so I used those.&lt;/p&gt;

&lt;p&gt;Eventually I found the culprit: HipChat API is HTTPS-only, and &lt;code&gt;HTTP::Tiny&lt;/code&gt; and perl in general require XS modules to use HTTPS, and XS modules cannot be fat packed.&lt;/p&gt;

&lt;p&gt;So I could not create a standalone script for this because of my HTTPS dependency. Oh well&amp;hellip;&lt;/p&gt;

&lt;p&gt;I think this is a good example for me to dust up my &lt;a href=&#34;https://golang.org&#34;&gt;Go&lt;/a&gt; knowledge&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Messaging</title>
      <link>https://www.simplicidade.org/notes/2014/08/02/messaging/</link>
      <pubDate>Sat, 02 Aug 2014 10:27:23 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2014/08/02/messaging/</guid>
      <description>

&lt;p&gt;A &lt;a href=&#34;http://twitter.com/rjbs/status/494953072943046657&#34;&gt;thread showed up on Twitter about messaging software options&lt;/a&gt;. My story is
not 140-charaters material, so here we are.&lt;/p&gt;

&lt;p&gt;If you do insist on a tldr; version: use &lt;a href=&#34;http://nsq.io&#34; title=&#34;NSQ - a realtime distributed messaging platform&#34;&gt;NSQ&lt;/a&gt; if you need something that
works out of the box, use &lt;a href=&#34;http://redis.io&#34; title=&#34;Redis&#34;&gt;Redis&lt;/a&gt; if you want
to build your own.&lt;/p&gt;

&lt;p&gt;At work, we use a lot of message queues to plug different components
together. They are a great tool to have on your belt but the
landscape is filled with solutions so picking your own solution can
be a daunting task.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve also gone through several solutions over the past 19 years working
on ISP and Web-related businesses, I have scars to prove this, so what
you&amp;rsquo;ll read below is the summary, obviously biased, of my experiences.&lt;/p&gt;

&lt;p&gt;I divided this into four sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defining the problem;&lt;/li&gt;
&lt;li&gt;Solutions out there;&lt;/li&gt;
&lt;li&gt;What do I use?;&lt;/li&gt;
&lt;li&gt;Tips and tricks I collected over the years.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;defining-the-problem&#34;&gt;Defining the problem&lt;/h2&gt;

&lt;p&gt;To help us understand one another, I&amp;rsquo;ll give you the mental model I use
to think about this problem.&lt;/p&gt;

&lt;p&gt;There are three types of actors involved:&lt;/p&gt;

&lt;p&gt;First you have producers. You have two main types: some generate
messages that represent work tasks that someone must perform, others
just emit messages that represent significant events that might be worth
reacting to on another part of your system. A producer can do both
during its lifetime. The big difference is that the work tasks usually
have higher requirements of persistency. You should not loose a message
that triggers a email to a client on a successful order for example.&lt;/p&gt;

&lt;p&gt;Then you have consumers. They collect the messages from producers and do
&amp;ldquo;stuff&amp;rdquo; with them. You imagination is the limit on &amp;ldquo;stuff&amp;rdquo; here. You can
perform the task you got, collect statistics, log events, you name it.
Consumers are usually producers too, generating further messages to
other consumers in line.&lt;/p&gt;

&lt;p&gt;For CS geeks, producers and consumers usually form a acyclic
directed graph.&lt;/p&gt;

&lt;p&gt;And then you have you queue software, the message broker. I usually like
to divide them into three main categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;centralised: you have one central message broker that producers and
consumers talk to. Given it&amp;rsquo;s SPOF nature, some provide you with
clustering solutions;&lt;/li&gt;
&lt;li&gt;distributed: you have message brokers everywhere, producers can
connect to any of them, consumers may need to connect to all of them
or only to some if the broker provides forwarding services (typical
tradeoff, where do you put the complexity, on the broker or the
client). The solutions here vary a lot on how producers and consumers
discover message brokers or each other for a direct connection, and
what kind of consistent view of the network is provided. Assume there
is some warm up period during which messages could be lost;&lt;/li&gt;
&lt;li&gt;embedded: the queue software runs on your producers/consumers process
space and connect to each other directly or via tiny dumb message
routers. They tend to produce distributed topologies, but you get to
solve you problem at a lower level in the stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The message broker is there to provide you one main service: decoupling.
Two dimensions of decoupling are important to have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;location: producers should not know or need to know who the consumers
are, or how many there are, or where they are, and you should be able
to add/drop consumers at any point in time;&lt;/li&gt;
&lt;li&gt;time: something produced right now should be available to a consumer
that connects at a latter point in time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You also should look at what type of message routing options and fan-out
strategies are provided. The two main ones are pub/sub and round robin
respectively. Check what kind of options are available to use them
together inside the broker, usually a powerful combination.&lt;/p&gt;

&lt;p&gt;Pub/sub will broadcast messages to all consumers, some solutions will
provide a routing only on topic, others hierarchical topics (you can
subscribe to subtrees), and some even complex filtering solutions. Round
robin will distribute incoming messages over all of the consumers, each
message getting to only one consumer. One thing to keep an eye out is
how good the broker is at allowing you to cluster multiple consumer
connections as a single one, for load balancing purposes.&lt;/p&gt;

&lt;p&gt;Then you need to consider message delivery guarantees, a key phrase to
look for when you are shopping for this systems. Personally I tend to
look for &amp;ldquo;at least once&amp;rdquo; semantics, as I believe them to be the better
trade-off. &amp;ldquo;Only once&amp;rdquo; is usually too resource intensive, and all the
others are too unreliable for my use cases. Removing duplicates on the
consumer side is easy enough with either a memory cache with decent
expire policies or if you store the message ID on the destination system
as a unique key.&lt;/p&gt;

&lt;p&gt;Finally you should think how the system deals with the two main problems
that you&amp;rsquo;ll see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;slow consumers: how can you avoid or deal with a message broker
holding hundreds of thousands of messages;&lt;/li&gt;
&lt;li&gt;dead consumers: what happens to the messages the consumer received
just before his life was over.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fun stuff, and I even had to mention byzantine failures yet!&lt;/p&gt;

&lt;h1 id=&#34;solutions-out-there&#34;&gt;Solutions out there&lt;/h1&gt;

&lt;p&gt;There are lots. I believe that we have very good generic tools now,
providing you the required building blocks for this type of systems, and
this caused an cambrian explosion. It seems almost all startups out
there decided to roll their own, and publish it as the best thing since
sliced bread. Guilty as charged&amp;hellip;&lt;/p&gt;

&lt;p&gt;I have a borderline fetish interest on this stuff, so I always look at
any solution that crosses my radar. Below I&amp;rsquo;ll list the main candidates
I think you should look into.&lt;/p&gt;

&lt;p&gt;First for rolling your own, you have two generic tools:
&lt;a href=&#34;http://zeromq.org&#34; title=&#34;Code Connected - zeromq&#34;&gt;ZeroMQ&lt;/a&gt; and Redis.&lt;/p&gt;

&lt;p&gt;On the mostly built, just use it section, you have AMQP-based solutions,
&lt;a href=&#34;https://github.com/sapo/sapo-broker&#34;&gt;SAPO Broker&lt;/a&gt;, &lt;a href=&#34;http://gearman.org&#34; title=&#34;Gearman Job Server&#34;&gt;Gearman&lt;/a&gt; and NSQ.&lt;/p&gt;

&lt;h2 id=&#34;zeromq&#34;&gt;ZeroMQ&lt;/h2&gt;

&lt;p&gt;ZeroMQ is fast, very fast, but also very &lt;em&gt;very&lt;/em&gt; low-level. It is an
embedded system, but also includes a &lt;a href=&#34;http://api.zeromq.org/4-0:zmq-
proxy &amp;quot;zmq_proxy(3&#34;&gt;small message router&lt;/a&gt; - 0MQ Api&amp;rdquo;) that you can spin up to provide you
location decoupling, and some basic translation services, from Queue to
Broadcast for example. You can build basically any topology, but you do
it by hand, using the building blocks. It&amp;rsquo;s basically for custom-made
solutions.&lt;/p&gt;

&lt;p&gt;You have pub/sub and you can also load balance messages between
different workers.&lt;/p&gt;

&lt;p&gt;Previous version had disk-based storage for overflow messages, but this
was deprecated and removed in more recent versions.&lt;/p&gt;

&lt;p&gt;There some higher level systems that use ZeroMQ as the backbone, but
none ever caught my eye as interesting enough.&lt;/p&gt;

&lt;p&gt;Basically, a fast low-level embedded library where the sky is the limit
on what you can do as long as you know you get to keep this baby all
for yourself.&lt;/p&gt;

&lt;h2 id=&#34;redis&#34;&gt;Redis&lt;/h2&gt;

&lt;p&gt;Redis is a memory-only system (it had a complex VM system before, but it
was dropped; there is a unofficial VM branch, I wouldn&amp;rsquo;t trust it), so
all your queued messages will be in memory. You need to understand that
you can fill up your entire memory and crash or stop accepting commands.
It has protections agains this, look into them.&lt;/p&gt;

&lt;p&gt;So, either you have (as in &amp;ldquo;you build one) a serious flow control system
to pause producers, or you need an escape valve, a special &amp;ldquo;consumer&amp;rdquo;
that goes into big queues, dumps messages to disk and puts them back
later, or just drop them and let your producer or bean counter system
inject them again later.&lt;/p&gt;

&lt;p&gt;Publish and subscribe works, even in the future cluster version, but
consumers need to be subscribed before the message is published. There
is no queueing for subscribers, none.&lt;/p&gt;

&lt;p&gt;To work around this, most systems use the BLPOPRPUSH command which
reliably takes a message from a inbox queue and inserts into your own
private queue for processing. As long as you have a system to look at
those private queues and inject messages from the private queues
back into the inbox, you can build a pretty fast and reliable queue
with this.&lt;/p&gt;

&lt;p&gt;A solid centralised system, that you can use to build whatever
semantics you need.&lt;/p&gt;

&lt;h2 id=&#34;amqp&#34;&gt;AMQP&lt;/h2&gt;

&lt;p&gt;AMQP-based systems are centralised, with a very flexible routing
solution, that allows you to build almost any topology you need.&lt;/p&gt;

&lt;p&gt;I started a pure-perl implementation of the client, that would take the
XML protocol specification (the best part of AMQP actually) and generate
the Perl code for it, but while doing that I was always thinking &amp;ldquo;do you
really need all this protocol complexity?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;I moved to simpler things. I really didn&amp;rsquo;t like the centralised aspects
of it, and most clustering solutions look to me as a fix for a design
decision, not a good symptom.&lt;/p&gt;

&lt;p&gt;Still, it has it&amp;rsquo;s place if you need a central system for environments
with strong requirements of auditing for compliance purposes.&lt;/p&gt;

&lt;h2 id=&#34;sapo-broker&#34;&gt;SAPO Broker&lt;/h2&gt;

&lt;p&gt;I used this a lot when I worked at SAPO. It is a distributed system,
very fast, with a rich set of semantics, and clients in multiple
languages.&lt;/p&gt;

&lt;p&gt;It includes a forwarding service, so you can subscribe to topics
locally and the network reacts and starts forwarding relevant messages
to your node.&lt;/p&gt;

&lt;p&gt;The node can become the bottleneck on big topics. I haven&amp;rsquo;t looked at it
recently, but you cannot setup your own node to receive only a subset of
the entire traffic, so that you could distribute a single topic set of
consumers over a set of nodes.&lt;/p&gt;

&lt;p&gt;Again, I haven&amp;rsquo;t looked at it recently, it might already have a solution
for this, but I do know the author and the code is solid. In heavy use
at SAPO for quite some time.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;http://oss.sapo.pt/#!broker&#34;&gt;Look into it&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;gearman&#34;&gt;Gearman&lt;/h2&gt;

&lt;p&gt;One of Brad Fitzpatrick (of memcached, perlbal, Open ID fame&amp;hellip;) pearls.&lt;/p&gt;

&lt;p&gt;A distributed system focused on work tasks, doesn&amp;rsquo;t support
pub/sub at all.&lt;/p&gt;

&lt;p&gt;Pretty good semantics to guarantee you don&amp;rsquo;t loose messages, although
persistence was only added later.&lt;/p&gt;

&lt;p&gt;Also includes a feedback system to report work status back to the
client, including progress messages, something you don&amp;rsquo;t see often.&lt;/p&gt;

&lt;p&gt;It just works.&lt;/p&gt;

&lt;h2 id=&#34;nsq&#34;&gt;NSQ&lt;/h2&gt;

&lt;p&gt;Built from scratch in Go by the Bitly people, processing huge amounts
of messages there.&lt;/p&gt;

&lt;p&gt;Very easy to install, has three main components: the message broker
&lt;code&gt;nsqd&lt;/code&gt;, the topology/discovery service &lt;code&gt;nsqlookupd&lt;/code&gt; and a decent admin
interface with &lt;code&gt;nsqadmin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;nsqd&lt;/code&gt; works standalone, reports topology to a set of &lt;code&gt;nsqlookupd&lt;/code&gt;
servers. Logic is on the client side that aggregates information
received from all the discovery services to form a coherent picture of
the network, and finds out to which brokers he needs to connect to to
collect all messages on the topic he is interested on.&lt;/p&gt;

&lt;p&gt;Allows you to stream messages to clients, keeping a per-client
configuration number of in-flight unacknowledged messages, works
wonderfully well for asynchronous consumers, or for consumers that need to
batch messages and process them in a single operation.&lt;/p&gt;

&lt;p&gt;My recommendation at the moment.&lt;/p&gt;

&lt;h1 id=&#34;what-do-i-use&#34;&gt;What do I use?&lt;/h1&gt;

&lt;p&gt;I gone through several solutions: AMQP, Gearman, ZeroMQ, Redis
and now NSQ.&lt;/p&gt;

&lt;h2 id=&#34;amqp-1&#34;&gt;AMQP&lt;/h2&gt;

&lt;p&gt;I dropped AMQP altogether. The centralised nature doesn&amp;rsquo;t provide me
enough benefits to compensate for a complex protocol. It is very
flexible, but I find it a heavy complex solution.&lt;/p&gt;

&lt;p&gt;Having said that, if you want/need to use AMQP, use
&lt;a href=&#34;http://www.rabbitmq.com&#34; title=&#34;RabbitMQ - Messaging that
just works&#34;&gt;RabbitMQ&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;zeromq-1&#34;&gt;ZeroMQ&lt;/h2&gt;

&lt;p&gt;Some of the AMQP authors agreed with my complexity assessment, they
dropped AMQP and created ZeroMQ (and one of them is even doing
&lt;a href=&#34;http://nanomsg.org&#34; title=&#34;nanomsg&#34;&gt;nanomsg&lt;/a&gt;, an even simpler system).&lt;/p&gt;

&lt;p&gt;I still keep ZeroMQ at hand for very specialised solutions, with very
stable topologies, where speed is the number one concern. I don&amp;rsquo;t expect
any kind of reliability of systems build from this, so I usually wrap
them into a end-to-end reliability blanket like a opportunistic
transactional queuing system (see [Tips and tricks][] section).&lt;/p&gt;

&lt;p&gt;For speed, you cannot beat ZeroMQ. nanomsg seems saner but I don&amp;rsquo;t think
is ready yet.&lt;/p&gt;

&lt;h2 id=&#34;redis-1&#34;&gt;Redis&lt;/h2&gt;

&lt;p&gt;I absolutely adore Redis&amp;hellip; It is my favourite swiss army knife. You can
do just about anything with it, and it has all the tools you need to
write you own queuing system. At least, that&amp;rsquo;s what 99% of all startups
think, because &lt;a href=&#34;https://github.com/search?q=redis+queue&amp;amp;amp;ref=cmdform&#34;&gt;queuing systems using
Redis&lt;/a&gt; is
probably the major software category on &lt;a href=&#34;https://github.com&#34;&gt;Github&lt;/a&gt; at
the moment.&lt;/p&gt;

&lt;p&gt;It was my go to system for quite some time, and I still use it if I need
something quickly, very simple to get it right, but it reacts badly to
slow consumers, you have to be very careful with that.&lt;/p&gt;

&lt;p&gt;You can use use several out-of-the box solutions.
&lt;a href=&#34;http://resquework.org&#34; title=&#34;Resque: the rock-solid job queue&#34;&gt;Resque&lt;/a&gt; is
one of the most popular, and it is available on most languages, but
logic is on the consumer side, so each version might not be compatible
with the others.&lt;/p&gt;

&lt;p&gt;My favorite is &lt;a href=&#34;https://github.com/seomoz/qless&#34;&gt;qless&lt;/a&gt;, a Resque
inspired solution, but that uses server side Lua for all the logic,
which means that all languages can share the exact same logic (see the
&lt;a href=&#34;https://github.com/seomoz/qless-core&#34;&gt;qless-core repository&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&#34;gearman-1&#34;&gt;Gearman&lt;/h2&gt;

&lt;p&gt;This is rock solid stuff, Etsy processes a huge amount of tasks with it
(I believe I saw the number 6000 per second over 5 servers on the
mailing list).&lt;/p&gt;

&lt;p&gt;The discovery part is the non-existing bit. If you add a new broker, you
need to tell all your producers and consumers.&lt;/p&gt;

&lt;p&gt;If you want to use this, look at &lt;a href=&#34;http://www.consul.io&#34; title=&#34;Consul&#34;&gt;Consul&lt;/a&gt;
for the discovery part.&lt;/p&gt;

&lt;h2 id=&#34;nqs&#34;&gt;NQS&lt;/h2&gt;

&lt;p&gt;My current favourite, and the one I use now. It gets so many
things right:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dead easy installation: you can just use the provided binaries, but
there is no GPG signature on those at the moment, something that I
hope to be fixed soon;&lt;/li&gt;
&lt;li&gt;decent &amp;ldquo;at least one&amp;rdquo; semantics;&lt;/li&gt;
&lt;li&gt;decent buffer to disk semantics, although we try to avoid this
situations with producer flow control (see tips and tricks section);&lt;/li&gt;
&lt;li&gt;the pubsub + channels with round-robin is my favourite topology;&lt;/li&gt;
&lt;li&gt;the nsqlookupd solves the discovery problem nicely: we use three
of them, they share the same AWS micro instance that hosts the
Consul cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We run a central cluster of 2 servers for general use, but we also keep
one &lt;code&gt;nsqd&lt;/code&gt; per instance. We use it for system integration, monitoring,
and logging (we have a couple of consumers that take batches of messages
and publish to &lt;a href=&#34;https://www.loggly.com&#34;&gt;Loggly&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;We also have a couple of consumer gateways between NQS and &lt;a href=&#34;https://github.com/wandenberg/nginx-
push-stream-module&#34;&gt;nginx-push-stream-module&lt;/a&gt;, allows some messages to reach client browsers in
real-time.&lt;/p&gt;

&lt;p&gt;Still, I would like to see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nsqlookupd&lt;/code&gt; should publish topology changes over a nsq topic: this
would allow consumers to react faster to new producers;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nsqd&lt;/code&gt; to &lt;code&gt;nsqlookupd&lt;/code&gt; protocol should be over a public channel, that
other systems could leverage for cluster monitoring and control.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;rsquo;m still learning all the details of NSQ and getting into the
community, so maybe some of this is already there and I just
haven&amp;rsquo;t found it.&lt;/p&gt;

&lt;p&gt;For Perl mongers out there, I&amp;rsquo;m writing a &lt;a href=&#34;https://github.com/melo/perl-anyevent-
nsq&#34;&gt;NSQ client using AnyEvent&lt;/a&gt;, basically extracting the internal working code into a public
distribution. My goal is to release it on August 14th, CPAN day, but I
can only work on it during weekends.&lt;/p&gt;

&lt;p&gt;Our code deals keeping track of the topology using &lt;code&gt;nsqlookupd&lt;/code&gt; and
connecting to multiple &lt;code&gt;nsqd&lt;/code&gt;, although the in-flight message management
might still need some TLC. Currently, on my CPU laptop, I can do a bit
more than 1M message per minute (no processing of course), but the
benchmark is clearly CPU bound (sum of broker, producer and consumer
give 180% CPU usage on my dual core CPU&amp;hellip; well, I was listening to
iTunes and browsing the web at the moment&amp;hellip;), a faster CPU would give
you better numbers.&lt;/p&gt;

&lt;h1 id=&#34;tips-and-tricks&#34;&gt;Tips and tricks&lt;/h1&gt;

&lt;h2 id=&#34;opportunistic-transactional-queuing&#34;&gt;Opportunistic transactional queuing&lt;/h2&gt;

&lt;p&gt;My motto is &amp;ldquo;trust but verify&amp;rdquo;. I usually build the queuing solution
assuming it will loose messages, but I keep a checks and balances system
on the side that will re-inject a message if they doesn&amp;rsquo;t show up on the
queue system.&lt;/p&gt;

&lt;p&gt;The main ingredient I use is something I call oportunistic transactional
queueing. This derives from an observation: the messages that need the
highest reliability usually happen at the end of a database transaction.&lt;/p&gt;

&lt;p&gt;The common scenario is a client that does something over the web or API
that changes the state on your system and you need to perform further
work on it, preferably asynchronous. If you have a work log, a place to
keep stuff that you need to do later, on the same database, then you can
insert a row there in the same transaction that updated the user state.
The expensive part is the transaction commit, so adding a new row is
marginal. At the same time you send the message to your queueing system.&lt;/p&gt;

&lt;p&gt;You also need a bean counter software. It will scan those work log
tables from time to time (once a minute is fine, unless you have a lot
of them), and make sure they are either done (and in this case you can
archive them), or lost (and in this case re-inject them).&lt;/p&gt;

&lt;p&gt;This will scale with your application because you can shard this work
log. You can have as many work logs as you want.&lt;/p&gt;

&lt;p&gt;As long as you don&amp;rsquo;t scan this tables often and as long as you archive
them aggressively, you should avoid most of the problems usually
associated with &amp;ldquo;database as a queue&amp;rdquo; problem. The main thing you should
remember is the work log is just to check the reliability of your queue,
not as your queue.&lt;/p&gt;

&lt;h2 id=&#34;topology-discovery-messages&#34;&gt;Topology discovery messages&lt;/h2&gt;

&lt;p&gt;Mapping the topology and monitoring it can be a hard problem to solve
with this systems, specially if they are distributed.&lt;/p&gt;

&lt;p&gt;Engineer your consumers and producers to support discovery messages.
When a discovery message is received by a consumer, he needs to do
two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;report that you got it: the message should include a URL, consumers
post a small JSON blob saying who he is, where he is, where did he
receive the message from, which topics is he subscribed to, which
topics does he publish to, and optional statistic information (total
messages processed, uptime, messages processed since last tracer, time
since last discovery message, whatever else you fancy);&lt;/li&gt;
&lt;li&gt;publish the message to all topics that you would normally publish to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This simple system allows you to collect those reports somewhere (I use
Redis myself), and show a unified view of your network (with pretty load
graphs even) on a browser.&lt;/p&gt;

&lt;h2 id=&#34;end-to-end-message-tracing&#34;&gt;End-to-end message tracing&lt;/h2&gt;

&lt;p&gt;Include a UUID on the message you generate, and make sure this UUID is
passed along, from publisher to consumer.&lt;/p&gt;

&lt;p&gt;By searching your logs for this UUID you can see all the consumers the
message travelled through and even show it as a timeline, with parallel
tasks in separate lines.&lt;/p&gt;

&lt;p&gt;I usually publish a log message on a separate topic, include the
consumer identification, the UUID of the task, and the time it took to
process, and then have a Redis-based collector that keeps track of the
last couple of hours of messages, to see how much they took end-to-end,
and where are they spending their time.&lt;/p&gt;

&lt;p&gt;I can quickly spot hot spots in the network with this system.&lt;/p&gt;

&lt;h2 id=&#34;have-at-least-three-priorities&#34;&gt;Have at least three priorities&lt;/h2&gt;

&lt;p&gt;No matter the technology I use, I try very hard to have three levels
of priority:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;urgent: this message should take precedence over all others;&lt;/li&gt;
&lt;li&gt;normal: basic stuff, normal traffic;&lt;/li&gt;
&lt;li&gt;bulk: lowest priority, consume this if you have nothing better to do.
It can introduce delays on bulk message processing, but you can
detect that, and spin up a new consumer (even a dedicated consumer
just for bulk).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes I split normal into &amp;ldquo;normal normal&amp;rdquo; and &amp;ldquo;normal but generated
by clients&amp;rdquo;, but unless you have other problems with some slow
components on your system that need this type of split to give priority
of your clients messages, I don&amp;rsquo;t bother.&lt;/p&gt;

&lt;p&gt;On NSQ and Redis this is usually implemented by using the topic name and
a prefix (&lt;code&gt;_bulk&lt;/code&gt;, &lt;code&gt;_urgent&lt;/code&gt; prefixes for the two non-normal queues.)&lt;/p&gt;

&lt;h2 id=&#34;producers-flow-control&#34;&gt;Producers flow control&lt;/h2&gt;

&lt;p&gt;With slow consumers, you have to be careful not to flood your broker
network with messages that they will have to spend time writing to disk
and reading back. I find it easier to pause producers.&lt;/p&gt;

&lt;p&gt;This of course assume that you can do that. On my uses cases, I&amp;rsquo;m
fortunate enough to have producers that can limit their output rate. If
you deal with end-user traffic, you might get spikes you can&amp;rsquo;t control.
Hopefully you&amp;rsquo;ll be able to launch more instances to cope with them.&lt;/p&gt;

&lt;p&gt;I do this in several ways, depending if I&amp;rsquo;m using Redis or NSQ. Some
tricks you can try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;on very simple situations where you are using a Redis list a small
queue between two systems, when you push into the queue, Redis returns
the number of messages in there. If this number is larger than you
high-water threshold, just pause, check from time to time until it
reaches the low-water threshold and resume;&lt;/li&gt;
&lt;li&gt;on NSQ you can periodically query the broker you are publishing to and
find out the size of the outgoing channels backlog. Use that
information to manage your output rate. Works well, supports multiple
consumers per topic, but it&amp;rsquo;s only hop-by-bop;&lt;/li&gt;
&lt;li&gt;include on your messages a &amp;ldquo;pause&amp;rdquo; URL: if a consumer is felling
overwhelmed, you can use the URL to pause and resume the producer.
Works throughout your network, no matter how many levels it has;&lt;/li&gt;
&lt;li&gt;if you use the topology discovery messages above, the system that
collects them can periodically generate traffic report messages on a
separate channel with the recommended rate of input on each topic, by
analysing each flow report he gets. Producers subscribe to this report
channel and use it as a guideline. This is a complex system to get
right, but when it does, it is a beauty to see.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;rsquo;m sure there are other ways, but these four so far allowed me to solve
this problem whenever it showed up.&lt;/p&gt;

&lt;p&gt;I love the last one, and I&amp;rsquo;m currently toying with a system like this,
I&amp;rsquo;ll write more about it later, when I have enough experience to know if
it is working or not.&lt;/p&gt;

&lt;p&gt;The third is a good compromise. It is very nice to have a callback into
the producer to tell him to shut up for a bit, and works with any system.&lt;/p&gt;

&lt;h1 id=&#34;final-words&#34;&gt;Final words&lt;/h1&gt;

&lt;p&gt;Enough words already. Go and start having fun with this stuff. Send me
links about your work, love to read about real world problems solved
with this systems.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>800</title>
      <link>https://www.simplicidade.org/notes/2014/06/02/800/</link>
      <pubDate>Mon, 02 Jun 2014 17:46:34 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2014/06/02/800/</guid>
      <description>

&lt;p&gt;WWDC is a couple of hours from starting. Some thoughts about it.&lt;/p&gt;

&lt;h3 id=&#34;800-pound-gorilla&#34;&gt;800-pound gorilla&lt;/h3&gt;

&lt;p&gt;I was at Imagine conference a couple of weeks back, and one presentation clicked a lot of different articles I&amp;rsquo;ve read recently.&lt;/p&gt;

&lt;p&gt;You can read &lt;a href=&#34;http://www.wired.com/2014/04/its-only-a-matter-of-time-before-apple-becomes-the-next-way-you-pay/&#34;&gt;this Wired article&lt;/a&gt; to get the basic business logic behind this. Basically, Apple is the company with the largest number of credit cards on file, by far. Almost 4 times Amanzon.&lt;/p&gt;

&lt;p&gt;So my WWDC prediction is that they will take advantage of this by doing two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating a iOS/Mac OS X framework that allows you to integrate direct payments on your apps: that part that I don&amp;rsquo;t like of this prediction is that I don&amp;rsquo;t thing they would be able to charge the same 30% they charge on other payments via the Apple Store;&lt;/li&gt;
&lt;li&gt;exposing this framework as a global JavaScript API on their browsers: this would allow checkout processes through out the world to immediately taking advantage of this, at least on all iOS-native browsers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With 800 million users, and most of them with a credit card, this would make them the largest mobile payment service overnight.&lt;/p&gt;

&lt;h3 id=&#34;one-more-thing&#34;&gt;One more thing&lt;/h3&gt;

&lt;p&gt;The twist of this is that, by having the same customer base, and using the same trick, a JavaScript-based API built-in into the browsers they control, they could also become a leading identity provider.&lt;/p&gt;

&lt;p&gt;One-click/swipe/button-press login on all your accounts online.&lt;/p&gt;

&lt;h3 id=&#34;what-i-would-like-to-see&#34;&gt;What I would like to see&lt;/h3&gt;

&lt;p&gt;Apple TV 4, or at least an announcement that we would be able to install Apps on a future Apple TV hardware.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I think this WWDC will be very interesting to watch indeed!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Phoenix</title>
      <link>https://www.simplicidade.org/notes/2014/05/13/phoenix/</link>
      <pubDate>Tue, 13 May 2014 09:03:48 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2014/05/13/phoenix/</guid>
      <description>&lt;p&gt;This blog should be renamed to &lt;a href=&#34;http://bit.ly/1hnSQjG&#34;&gt;Phoenix&lt;/a&gt;&amp;hellip;&lt;/p&gt;

&lt;p&gt;Since we last spoke, a lot has changed but most remained the same.&lt;/p&gt;

&lt;p&gt;I still have three kids, and a dog. I&amp;rsquo;m still married to the same smart beautiful woman.&lt;/p&gt;

&lt;p&gt;I still use Perl as my main language, although I&amp;rsquo;ve been using a lot of JavaScript and Go (my favourite new language; in 3 years it will be a major contender, mark my words) whenever I can get away with it. I still truly completely hate significant white-space.&lt;/p&gt;

&lt;p&gt;I still use daemontools supervise everywhere, but I&amp;rsquo;ve been playing with Docker more and more, and I might finally retire my decades-old deployment setup, as soon as I figure out a decent way of linking containers across different hosts securely (geard of Project Atomic looks good for this). Also OpenShift Origin is nice. And with version 1.6, Vagrant will finally become my preferred developer environment.&lt;/p&gt;

&lt;p&gt;I still use qmail and ezmlm-idx for all my mail and newsletters needs.&lt;/p&gt;

&lt;p&gt;I still find that, for small companies, hosting in a cloud like AWS is much more expensive than dedicated hosting, but I&amp;rsquo;ve learned to appreciate the cosy environment they provide if you have enough scale and some money. I love that AWS BeanStalk supports Docker containers now.&lt;/p&gt;

&lt;p&gt;I still buy books, in their natural dead tree format, although I do have a lot of them in eBook format on my iPad. Yes, I finally caved in last Christmas and bought myself a iPad Air. I could not find a decent Moveable Type client though. Yes, I still use MT too, although my ageing setup is no longer CGI-powered, I&amp;rsquo;ve switched to a Plack-based setup around the original CGIs with Starman.&lt;/p&gt;

&lt;p&gt;I still have my (now) 14 years old startup, I still have a lot to do there. But I also needed a new challenge, so I took a new job (well, a year ago). I&amp;rsquo;m responsible for a couple of eCommerce sites in Portugal, doing very fun stuff with Node.JS, AngularJS, Redis and Perl of course. BTW, we are hiring, ping me if you like any of the previous stuff. It is nice to have sites that make money.&lt;/p&gt;

&lt;p&gt;Yes, I still think Redis is the best thing since sliced bread. Seriously. The only thing better than Redis is Git. And possible Camlistore.&lt;/p&gt;

&lt;p&gt;I still use MySQL. And I use it as a document-oriented DB, with either compressed JSON or Sereal documents. I do keep extra tables with some of the document attributes for decent reporting though. I&amp;rsquo;m curious about ArangoDB. And the 9.4 Postgres release, with JSON indexes, looks awesome. Can I haz it in MySQL soon?&lt;/p&gt;

&lt;p&gt;I still search with SphinxSearch, although I find ElasticSearch cute.&lt;/p&gt;

&lt;p&gt;I still like XMPP, but I haven&amp;rsquo;t had the time to work with it recently.&lt;/p&gt;

&lt;p&gt;I still use Mac&amp;rsquo;s, they still last 6+ years each on my hands (currently using late 2008 Macbook). I still use my iPhone4, and I don&amp;rsquo;t plan to switch for at least one year more. I like hardware that lasts that long.&lt;/p&gt;

&lt;p&gt;I still think people who believe iOS or Android will ever dominate the other should search history for cases of zero-sum games.&lt;/p&gt;

&lt;p&gt;I still love Portugal, although I miss a lot of friends that left us for greener pastures over the last two years.&lt;/p&gt;

&lt;p&gt;Health-wise I had a kidney stone. I&amp;rsquo;ll just say that you should ask for the real drugs from the start. Probably the most painful experience ever&amp;hellip;&lt;/p&gt;

&lt;p&gt;Best of all, I&amp;rsquo;m still happy.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Californication</title>
      <link>https://www.simplicidade.org/notes/2013/04/15/californication/</link>
      <pubDate>Mon, 15 Apr 2013 06:54:56 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2013/04/15/californication/</guid>
      <description>&lt;p&gt;There will always be extreme in Californication, from the initial minutes of a blasphemous moment in a church by a agreeable nun, to the moment that dreams do come true.&lt;/p&gt;

&lt;p&gt;Maybe boys will be boys and we just enjoy lewdness, or maybe there is a grain of truth in it. But 6 years ago when I started watching &lt;em&gt;the&lt;/em&gt; show, I never though the roller coast of emotions it would trigger.&lt;/p&gt;

&lt;p&gt;Based on a set of never ending love stories, some peaceful, other just normal and a big sad one, it keeps rocking my socks off with the impossible real situations, and the fulsome dialogs.&lt;/p&gt;

&lt;p&gt;You get to live an alternative universe in a even dozen instalments every year, and the only thing left after you are done, is a longing for the next fix.&lt;/p&gt;

&lt;p&gt;Thank you, Hank Moody, you degenerate impossible lucky bastard. See you next year.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dreaming in sync</title>
      <link>https://www.simplicidade.org/notes/2013/01/07/dreaming-in-sync/</link>
      <pubDate>Mon, 07 Jan 2013 11:32:10 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2013/01/07/dreaming-in-sync/</guid>
      <description>&lt;p&gt;If you ever get me talking about applications and synchronisation of data, you might notice that I&amp;apos;m very passionate about sync.&lt;/p&gt;

&lt;p&gt;You&amp;apos;d be right. My favourite topic in college was distributed operating systems. Today, when I design a system, I always envision it as a set of cooperating processes, working together and in parallel for a common goal.&lt;/p&gt;

&lt;p&gt;Over the past 15 years, I&amp;apos;ve kept refining a set of rules of what I think is the ideal features any application that does sync should have.&lt;/p&gt;

&lt;p&gt;I&amp;apos;ve narrowed down to three.&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;1. Close your laptop and go&lt;/h3&gt;
&lt;p&gt;If you see a &amp;quot;sync now&amp;quot; button, they blew it.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;To paraphrase &lt;a href=&#34;http://www.brainyquote.com/quotes/quotes/v/vincelomba125237.html&#34; title=&#34;Winning is not a sometime thing...&#34;&gt;Vince Lombardi&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Sync is not a sometime thing; it&amp;apos;s an all time thing. You don&amp;apos;t sync once in a while, you don&amp;apos;t do things right once in a while, you do them right all the time. Sync is habit.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;If you share application state with your co-workers (say for example a project management app, with issues, goals, notes, design documents, whatever), when you are sitting in your office, your own version of the application is running on your laptop. It has a copy of the state. Maybe not all of the state, maybe just the part that relates to you, but for now let&amp;apos;s assume that it has all of the state.&lt;/p&gt;

&lt;p&gt;When you close the laptop lid and move to another place, the information on your local copy should be the update version of the shared state up to the moment you lost network connectivity.&lt;/p&gt;

&lt;p&gt;There should be any &amp;quot;oh I&amp;apos;ll just wait a bit and sync before I disconnect&amp;quot; though crossing your mind. Sync should not be part of your thinking process. It should just be the normal world view, it should be subconscious. &lt;/p&gt;

&lt;p&gt;One of the best outcomes of this always-in-sync subliminal state? Given that you&amp;apos;ll be always seeing, manipulating, the latest version of something, the opportunity for conflicts based on mis-information is rare.&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;2. Cherish thy conflicts&lt;/h3&gt;
&lt;p&gt;Which brings us to the big bad wolf of synchronisation: conflicts. This is the primary fear most people who think about implementing a sync solution share.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;What I&amp;apos;m here to tell you, is that conflicts are you friends. They are the tether that binds you to humanity, because they only come up when someone has a different world view from your own.&lt;/p&gt;

&lt;p&gt;Having someone who disagrees with you is glorious! It gives you the opportunity to get out of your bubble and interact. And you get to choose how to do so. Maybe you just IM or mail him, or maybe you call him, or even share a few minutes of his time in a hall near a whiteboard.&lt;/p&gt;

&lt;p&gt;Conflicts are nature way of telling you that you need to get out a bit and talk to someone.&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;3. Be a packrat, collect it all&lt;/h3&gt;
&lt;p&gt;The most important lesson I got from &lt;a href=&#34;http://git-scm.com&#34; title=&#34;Git&#34;&gt;git&lt;/a&gt; was not the graph of objects on which it was built, but the fact that git never stores diffs. It will always store a complete version of the new state.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;The main advantage of having the entire state blob for each version is simple: you can always improve your conflict resolution, or your diff algorithm, or any part of the UX of both, because you have the raw data available. If you store diff&amp;apos;s, you&amp;apos;ll be using the state of the art diff algorithm at that moment, and going back to any version means replaying all the diffs since the last full version.&lt;/p&gt;

&lt;p&gt;You might think that this is a huge waste of space, and it could be if you have big state blobs on which only a small percentage change between versions, but I posit that this is not the most common case. In fact, big state blobs should sound warning bells in your head, and start to break them up into smaller concepts.&lt;/p&gt;

&lt;p&gt;No, you want small state blobs, connected together. They are faster to sync individually, and they provide a smaller surface for conflict resolution when those blissful events are casted upon you.&lt;/p&gt;

&lt;p&gt;And with small state blobs, when state changes, you should always store &lt;/p&gt;

&lt;p&gt;&lt;h2&gt;Let&amp;apos;s be about it&lt;/h2&gt;
&lt;p&gt;So you are hyped now, you want your next application to have sync. What is your next step?&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;The Dropbox generation&lt;/h3&gt;
&lt;p&gt;The sync experience of Dropbox is comparable to the automobile experience of a Model T. Or the the sexual pleasure of masturbation. It gets the job done, barely, but you end up thinking that should be more to life than this.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;It should, and there is.&lt;/p&gt;

&lt;p&gt;Dropbox is a fine product, I depend on it daily for a lot of things, but most of them are files.&lt;/p&gt;

&lt;p&gt;To sync files between devices and across several operating systems, there aren&amp;apos;t many other solutions out there with the same proven track record. So in recent time, a lot of applications that deal with files have added builtin Dropbox support as their solution for the sync problem. And it works fine, for files, and single user scenarios.&lt;/p&gt;

&lt;p&gt;But when you start talking about application state, with multiple users, if you plan on using Dropbox, you better start modelling your data store as a series of independent files. And forget about data protection of any kind.&lt;/p&gt;

&lt;p&gt;But it can be done. For the single user case, it is more than enough.&lt;/p&gt;

&lt;p&gt;The best example I know (and use, and recommend by the way) is 1Password. A couple of versions back, they switched from a single file to a file bundle as their storage system. You can read all about the &lt;a href=&#34;http://help.agilebits.com/1Password3/agile_keychain_design.html&#34; title=&#34;Agile Keychain Design | 1Password 3 User Guide&#34;&gt;Agile keychain design&lt;/a&gt;, good stuff in there.&lt;/p&gt;

&lt;p&gt;What they did was break a large state blob into several smaller ones.&lt;/p&gt;

&lt;p&gt;But the &lt;a href=&#34;https://www.dropbox.com/developers/reference/api&#34;&gt;Dropbox API&lt;/a&gt; lacks any way to be notified in real-time of changes others may have made to your files. Sure, the desktop client uses a private Dropbox API to be notified of new stuff, but that is not available to you.&lt;/p&gt;

&lt;p&gt;So, if you plan on using Dropbox as the sync service for your app, remember that always-in-sync scenario requires the Dropbox desktop client, and you have to monitor (fsevents on Mac OS X, or inotify on Linux, kqueue on FreeBSD...) the filesystem yourself to detect changes.&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;But, but, but git is magical!&lt;/h3&gt;
&lt;p&gt;Yes it is. But only for some things. Files, source code, text articles.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;If you plan on basing your sync solution on git, thats fine. It is a viable option now that libgit2 is stable.&lt;/p&gt;

&lt;p&gt;Just remember that source code conflicts are easier to solve because they happen on something that has structure, something that can be validated,at syntax level by your language compiler or interpreter, and at semantic level by your test suite. You do have one of those, right?&lt;/p&gt;

&lt;p&gt;There is no possible test suite that covers your application data semantics. You can have some business rules that must be checked before accepting changes to application state, but they will never be comprehensive.&lt;/p&gt;

&lt;p&gt;Also, git lacks any way to notify you in real-time of new commits on remote branches, so you have to roll your own too.&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;Natives need not apply&lt;/h3&gt;
&lt;p&gt;You might think that all of this is my subtle way of pushing you from your friendly web to the evil seductive native apps embrace, but no.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;Yes, I do believe that the vast majority of your app logic should be executed on the client side. It&amp;apos;s not only my distributed systems engineer wet dream, but also your ecological duty not to wast all those processor cycles sitting on your lap or nicely wrapped in your hand.&lt;/p&gt;

&lt;p&gt;I also believe that no matter how much bandwidth you have, how blazing fast your servers are, you can&amp;apos;t beat the latency of a local app working on local data.&lt;/p&gt;

&lt;p&gt;And besides, even if you have always-hopefully-on internet connectivity, isn&amp;apos;t it better to hide all those wishful thoughts about &amp;quot;when the user presses this button I will have network access, my server will be up, and everything is peachy&amp;quot; in the smallest part of your application as you can manage it? If your entire app uses local data, and then, in the background, those changes are sent to the remote peers, the user experience is much faster.&lt;/p&gt;

&lt;p&gt;So keep you mad Web skills, they are your best bet it this the brave new continent you&amp;apos;re about to explore. Just think about bringing along a simple HTTPS server, sitting right there on your local device, holding a copy of your app, and your state.&lt;/p&gt;

&lt;p&gt;&lt;h3&gt;Interactive sync&lt;/h3&gt;
&lt;p&gt;There is a crop of products that focus on real-time collaboration. Software like SubEthaEdit and recently Ex-Google Wave.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;They are very specific niches of the whole synchronisation topic, and I don&amp;apos;t think they are a good solution for most apps. A bit of overkill.&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;Action!&lt;/h2&gt;
&lt;p&gt;Finally, my brain dump from having done some synchronisation work.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;Divide and conquer. Start with a simple problem. Don&amp;apos;t make sync a feature in a future version, plan it from the start. It is very hard to bold sync later on, believe me.&lt;/p&gt;

&lt;p&gt;Cherish immutable content, or single-owner content, like comments. No conflicts there. A post has a set of comments, this set is conflict free.&lt;/p&gt;

&lt;p&gt;Embrace that conflicts are a human problem, not a technical one, and instead of wasting your time dreading them, focus on the best UX you can provide to make the work of two or more people involved easier to do: how to pick the new world view?&lt;/p&gt;

&lt;p&gt;Start with a central meeting place, where all changes flow through. It is easier to do at first, just make sure this central place never accepts conflicted information. All conflicts must be solved on the client side befor any changes are sent.&lt;/p&gt;

&lt;p&gt;Start with &amp;quot;rolling sync&amp;quot;, the simplest approach to merges: if you have been offline for a bit of, first undo all your offline changes, apply all remote changes done since your last sync, and then roll your changes over that to catch any conflicts. If you know git, think rebase, not merge.&lt;/p&gt;

&lt;p&gt;Use UUID&amp;apos;s or SHA1 of content as identifiers: there is no clear cut rule on which one to pick, it really depends on the situation.&lt;/p&gt;

&lt;p&gt;Remember the truth about clocks: everybody has one, and each one keeps his own perfect time. If only they could agree on what that perfect time is...&lt;/p&gt;

&lt;p&gt;Don&amp;apos;t ask permission to collect all of what you can from your peers, just do it. Later, your person can always check why was something changed, and who did it. &lt;/p&gt;

&lt;p&gt;&lt;h2&gt;Its a brave new world&lt;/h2&gt;
&lt;p&gt;Sync is not just a feature anymore, it must be something that its just there, unquestioned, subliminal.&lt;/p&gt;&lt;/p&gt;

&lt;p&gt;Do your part, and start designing your apps with &amp;quot;Sync first!&amp;quot; mentality.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>tidyall: TextMate command, and other tidbits</title>
      <link>https://www.simplicidade.org/notes/2012/09/21/tidyall-textmate-command-and-other-tidbits/</link>
      <pubDate>Fri, 21 Sep 2012 10:41:11 +0000</pubDate>
      <author>melo@simplicidade.org (Pedro Melo)</author>
      <guid>https://www.simplicidade.org/notes/2012/09/21/tidyall-textmate-command-and-other-tidbits/</guid>
      <description>&lt;p&gt;I&amp;apos;ve started using &lt;a href=&#34;http://www.openswartz.com/&#34;&gt;Jonathan Swartz&lt;/a&gt; excellent &lt;a href=&#34;https://metacpan.org/module/tidyall&#34;&gt;&lt;code&gt;tidyall&lt;/code&gt;&lt;/a&gt; for all my tidy needs. This is &lt;a href=&#34;http://macromates.com/&#34;&gt;TextMate&lt;/a&gt; command that I use to replace the Tidy command distributed with the Perl bundle.&lt;/p&gt;&lt;pre class=&#34;brush: bash;&#34;&gt;
require_cmd tidyall &amp;apos;Requires tidyall, install from CPAN&amp;apos;

### Have a default tidyall.ini on your home, override per project
config=&amp;quot;$HOME/.tidyall.ini&amp;quot;
for ini in tidyall.ini .tidyall.ini ; do
  if [ -e &amp;quot;${TM_PROJECT_DIRECTORY}/${ini}&amp;quot; ] ; then
    config=&amp;quot;${TM_PROJECT_DIRECTORY}/${ini}&amp;quot;
  fi
done

## Override target file if the current scope is perl: useful when
## tidying a selection of perl code inside a Mason document
target=&amp;quot;$TM_FILEPATH&amp;quot;
if [ &amp;quot;${TM_SCOPE:0:11}&amp;quot; == &amp;quot;source.perl&amp;quot; ] ; then
  target=&amp;quot;${TM_PROJECT_DIRECTORY}/perl.pl&amp;quot;
fi

tidyall --root &amp;quot;$TM_PROJECT_DIRECTORY&amp;quot; \
        --conf-file &amp;quot;${config}&amp;quot;        \
        --pipe &amp;quot;$target&amp;quot;
&lt;/pre&gt;&lt;p&gt;To use it, create a new command in your own personal bundle, and set:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Save: Nothing;&lt;/li&gt;&lt;li&gt;Command(s): the above code;&lt;/li&gt;&lt;li&gt;Input: Selected Text or Document&lt;/li&gt;&lt;li&gt;Output: Replace Selected Text&lt;/li&gt;&lt;li&gt;Activation: Key Equivalent Ctrl+Shift+H (the same as Tidy);&lt;/li&gt;&lt;li&gt;Source: source.perl, comment.documentation.perl&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The last one, Source, you should also add other scopes that your &lt;code&gt;tidyall&lt;/code&gt; config covers.&lt;/p&gt;

&lt;p&gt;My current &lt;code&gt;tidyall.ini&lt;/code&gt; is this:&lt;/p&gt;&lt;pre class=&#34;brush: plain&#34;&gt;
[PerlTidy]
select = **/*.{pl,pm,t}

[PodTidy]
argv = --column=100
select = **/*.{pm,pod}

[Perl::AlignMooseAttributes]
select = **/*.pm

[Perl::IgnoreMethodSignaturesSimple]
select = **/*.{pl,pm,t}

[MasonTidy]
select = **/*.{mc,mi,html}
select = **/{autohandler,dhandler}
&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;MasonTidy&lt;/code&gt; section is still new to me, I&amp;apos;m not sure if I like it or not. The rest is very good, specially the clean integration to tidy &lt;a href=&#34;https://metacpan.org/module/Method::Signatures&#34;&gt;Method::Signatures&lt;/a&gt; declarations provided by the &lt;a href=&#34;https://metacpan.org/module/Code::TidyAll::Plugin::Perl::IgnoreMethodSignaturesSimple&#34;&gt;Perl::IgnoreMethodSignaturesSimple plugin&lt;/a&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Although this plugin targets the &lt;a href=&#34;https://metacpan.org/module/Method::Signatures::Simple&#34;&gt;Method::Signatures::Simple&lt;/a&gt;, I&amp;apos;m using it with &lt;a href=&#34;https://metacpan.org/module/Method::Signatures&#34;&gt;Method::Signatures&lt;/a&gt;, my preferred version of the concept, without problems&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I&amp;apos;ve also used &lt;a href=&#34;http://www.openswartz.com/2012/09/05/tidying-and-checking-code-on-commit/&#34;&gt;the recent git pre-commit hooks&lt;/a&gt; code for a bit, but I&amp;apos;m having problems with it and haven&amp;apos;t had the time to really look into it. The code stashes stuff that is not in the index before running, to make sure it is only tidying the parts you are going to commit, and then pops the rest from the stash. This last part causes me a lot of merge failures.&lt;/p&gt;

&lt;p&gt;If you don&amp;apos;t use hunk or line-based commit building, you should be fine though.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>