<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Orr Sella</title>
    <description>Code and technology musings by Orr Sella</description>
    <link>https://orrsella.com/</link>
    <atom:link href="https://orrsella.com/rss.xml" rel="self" type="application/rss+xml" />
    <pubDate>Wed, 02 May 2018 17:35:00 -0700</pubDate>
    <lastBuildDate>Wed, 02 May 2018 17:35:00 -0700</lastBuildDate>
    <generator>Jekyll v3.1.2</generator>
    
      <item>
        <title>Summary of Brendan Gregg&#39;s Linux Performance Analysis Tools</title>
        <description>&lt;p&gt;Brendan Gregg &lt;a href=&quot;http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html&quot;&gt;wrote a great post on his first 60,000 milliseconds&lt;/a&gt; when trying to diagnose a server with a performance issue. If you haven’t yet, you should go &lt;a href=&quot;http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html&quot;&gt;read his post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are many great tips there, and I really wish I could remember all of them. Unfortunately I don’t get to use most of these day-to-day, but only every once in a while. And when I do – they come in &lt;em&gt;very&lt;/em&gt; handy.&lt;/p&gt;

&lt;p&gt;To help me remember these, and not have to open up his blog post every time, I added a handy alias to my dot files, &lt;a href=&quot;https://orrsella.com/2016/10/29/managing-local-and-remote-dot-files/&quot;&gt;which I take with me everywhere&lt;/a&gt;. This alias prints a summary of all the tools, with brief descriptions for each tool based on Brendan’s advise.&lt;/p&gt;

&lt;p&gt;Here’s what it looks like when running it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;$ perf-tools
Linux Performance Analysis in 60,000 Milliseconds
Source: http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html
Even more tools: http://techblog.netflix.com/2015/08/netflix-at-velocity-2015-linux.html

 1) uptime              Load averages, indicate the number of tasks (processes) wanting to run (CPU and I/O).
 2) dmesg | tail        Last 10 system messages (if there are any).
 3) vmstat 1            Virtual memory stat, 1 second summaries. CPU stats are on average, across all CPUs:
                          - r          Number of processes running on CPU and waiting for a turn (CPU only, no I/O). Value &amp;gt; cores = saturation
                          - free       Free memory in kilobytes; see (7) for more info on free mem
                          - si/so      Swap-ins and swap-outs; if these are non-zero, you\&amp;#39;re out of memory
                          - us         User time
                          - sy         System time (kernel), necessary for I/O processing
                          - id         Idle
                          - wa         Wait I/O (like idle for I/O reason), constant value points to a disk bottleneck
                          - st         Stolen time
 4) mpstat -P ALL 1     CPU time breakdowns per CPU, allows to check for an imbalance (a single hot CPU can be evidence of a single-threaded application).
 5) pidstat 1           Per-process summary, useful for watching patterns over time. CPU column is the total across all CPUs (cores).
 6) iostat -xz 1        Workload and performance of block devices:
                          - r/s        Reads per second
                          - w/s        Writes per second
                          - rkB/s      Read Kbytes per second
                          - wkB/s      Write Kbytes per second
                          - await      The average time for the I/O in milliseconds (time the application suffers, as it includes both time queued and time being serviced)
                          - avgqu-sz   The average number of requests issued to the device; values greater than 1 can be evidence of saturation
                          - %util      Device utilization during internal (1 second in this case)
 7) free -m             Memory stats in Mbytes. Cached memory can be reclaimed quickly if apps need it, so it should be considered free (-/+ buffers/cache line). Also buffers and cached shouldn&amp;#39;t be near-zero in size.
 8) sar -n DEV 1        Network interface throughput:
                          - rxkB/s     Received Kbytes per second (x8 for Kbits)
                          - txkB/s     Transmitted Kbytes per second (x8 for Kbits)
                          - %ifutil    Device utilization (max of both directions for full duplex)
 9) sar -n TCP,ETCP 1   Summarized view of some key TCP metrics:
                          - active/s   Number of locally-initiated TCP connections per second
                          - passive/s  Number of remotely-initiated TCP connections per second
                          - retrans/s  Number of TCP retransmits per second (sign of a network or server issue)
10) top/htop            Non-rolling system overview (which makes it hard to see patterns over time). Pro-tip: Ctrl-S to pause, Ctrl-Q to continue.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Want to add this to your dot files? Just copy the &lt;code&gt;perf-tools&lt;/code&gt; &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/bash/ssh/functions&quot;&gt;function from here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks Brendan for your great tips, as always!&lt;/p&gt;
</description>
        <pubDate>Fri, 11 Nov 2016 00:00:00 -0800</pubDate>
        <link>https://orrsella.com/2016/11/11/summary-of-brendan-greggs-linux-performance-analysis-tools/</link>
        <guid isPermaLink="true">https://orrsella.com/2016/11/11/summary-of-brendan-greggs-linux-performance-analysis-tools/</guid>
        
        
      </item>
    
      <item>
        <title>Managing Local and Remote Dot Files</title>
        <description>&lt;p&gt;This post describes how I like to think about and manage the dot files on both my local macOS dev machine, as well as any remote Linux server I use regularly – in one single setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Check out &lt;a href=&quot;https://github.com/orrsella/dotfiles&quot;&gt;my dot files repo&lt;/a&gt; for the code. To get started you can just clone/fork and run one of the setup scripts.&lt;/p&gt;

&lt;h3 id=&quot;my-dot-files&quot;&gt;My Dot Files&lt;/h3&gt;

&lt;p&gt;We all love dot files. A lot &lt;a href=&quot;https://zachholman.com/2010/08/dotfiles-are-meant-to-be-forked/&quot;&gt;has&lt;/a&gt; &lt;a href=&quot;https://medium.com/@webprolific/getting-started-with-dotfiles-43c3602fd789&quot;&gt;been&lt;/a&gt; &lt;a href=&quot;https://developer.atlassian.com/blog/2016/02/best-way-to-store-dotfiles-git-bare-repo/&quot;&gt;written&lt;/a&gt; &lt;a href=&quot;https://www.foraker.com/blog/get-your-dotfiles-under-control&quot;&gt;about&lt;/a&gt; them, and there are &lt;a href=&quot;https://github.com/mathiasbynens/dotfiles&quot;&gt;many&lt;/a&gt; &lt;a href=&quot;https://github.com/holman/dotfiles&quot;&gt;popular&lt;/a&gt; &lt;a href=&quot;https://github.com/search?o=desc&amp;amp;q=dotfiles&amp;amp;s=stars&amp;amp;type=Repositories&amp;amp;utf8=%E2%9C%93&quot;&gt;GitHub repos&lt;/a&gt; with &lt;a href=&quot;https://github.com/webpro/awesome-dotfiles&quot;&gt;cool examples&lt;/a&gt;. What makes mine different is the fact that I like to take them with me everywhere I go, including when SSH-ing into any server – both for work and personal use – even for the ones I’ve never used before!&lt;/p&gt;

&lt;p&gt;They serve two purposes for me:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Not being attached to any particular dev machine – I rely on my dot files and the &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/setup-brew.sh&quot;&gt;various&lt;/a&gt; &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/setup-macos.sh&quot;&gt;setup&lt;/a&gt; &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/setup-symlinks.sh&quot;&gt;scripts&lt;/a&gt; for a very quick ramp-up when moving to a new Mac.&lt;/li&gt;
  &lt;li&gt;Having maximum convenience and productivity anywhere possible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My dot files include a lot of the typical shell/tools setup:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Shell&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
    &lt;ul&gt;
      &lt;li&gt;Config&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/bash/local/prompt&quot;&gt;Prompt&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Environment variables&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/bash/common/aliases&quot;&gt;Aliases&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/bash/common/functions&quot;&gt;Handy&lt;/a&gt; &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/bash/local/functions&quot;&gt;utility&lt;/a&gt; &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/bash/ssh/functions&quot;&gt;functions&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Vim&lt;/li&gt;
  &lt;li&gt;Tmux/Screen&lt;/li&gt;
  &lt;li&gt;Git/Mercurial&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also store the config files for some of my native Mac apps, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Alfred&lt;/li&gt;
  &lt;li&gt;Sublime Text&lt;/li&gt;
  &lt;li&gt;IntelliJ&lt;/li&gt;
  &lt;li&gt;iTerm&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h3&gt;

&lt;p&gt;My setup includes careful integration of the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Using git to store and version all files.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/links&quot;&gt;Precisely managing which dot file goes where&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Supporting both local (macOS) and remote (Linux) dot files, while also reusing the common parts.&lt;/li&gt;
  &lt;li&gt;Using the great &lt;a href=&quot;https://github.com/Russell91/sshrc&quot;&gt;sshrc&lt;/a&gt; script.&lt;/li&gt;
  &lt;li&gt;Configuring &lt;code&gt;tmux&lt;/code&gt;/&lt;code&gt;screen&lt;/code&gt; to work with &lt;code&gt;sshrc&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setup includes cloning the repo locally&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and symlinking all files listed in &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/links&quot;&gt;&lt;code&gt;links&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When SSH-ing somewhere, I use the &lt;code&gt;sshrc&lt;/code&gt; command, which zips all files found in the &lt;code&gt;~/.sshrc.d&lt;/code&gt; directory (also managed by &lt;code&gt;links&lt;/code&gt;), and extracts them to a temporary directory on the destination server. It then sources &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/bash/ssh/.sshrc&quot;&gt;&lt;code&gt;.sshrc&lt;/code&gt;&lt;/a&gt; to configure everything.&lt;/p&gt;

&lt;p&gt;Lastly, I use &lt;a href=&quot;https://github.com/orrsella/dotfiles/blob/master/bash/ssh/functions&quot;&gt;my custom&lt;/a&gt; &lt;code&gt;screenrc&lt;/code&gt; and &lt;code&gt;tmuxrc&lt;/code&gt; commands on the server to open new sessions. These make sure that new sessions are initialized with everything extracted by &lt;code&gt;sshrc&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This might sound complicated, but it works seamlessly and effortlessly. I no longer have to worry about keeping the various snowflake instances of my dot files on the various servers I use in sync, and I get to share a lot of the code that makes sense with my local Mac setup. I also don’t litter any server I connect to with local copies of my personal files since &lt;code&gt;sshrc&lt;/code&gt; uses tmp files and cleans up after itself.&lt;/p&gt;

&lt;p&gt;Interested? Take it for a spin: &lt;a href=&quot;https://github.com/orrsella/dotfiles&quot;&gt;https://github.com/orrsella/dotfiles&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have a cool addition? Fork and add! Send a pull request if you think I should include in my setup as well.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;I only use bash. I find comfort in knowing that any environment I work with has bash, without relying a specific configuration – that’s out of my control – having other shells like zsh, fish, etc. I feel like my dot files make it so I get a lot of the convenience of using other modern shells while having a consistent experience everywhere. This doesn’t mean you have to do the same. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;I like to use &lt;code&gt;~/.dotfiles&lt;/code&gt;. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 29 Oct 2016 00:00:00 -0700</pubDate>
        <link>https://orrsella.com/2016/10/29/managing-local-and-remote-dot-files/</link>
        <guid isPermaLink="true">https://orrsella.com/2016/10/29/managing-local-and-remote-dot-files/</guid>
        
        
      </item>
    
      <item>
        <title>Preparing For a System Architecture Interview</title>
        <description>&lt;p&gt;This is the second part of my previous post on &lt;a href=&quot;https://orrsella.com/2016/05/14/preparing-for-a-facebook-google-software-engineer-interview/&quot;&gt;Preparing for a Facebook/Google Software Engineer Interview&lt;/a&gt;. If you haven’t yet, I suggest you go read it and then come back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer 1:&lt;/strong&gt; Obviously, &lt;a href=&quot;https://orrsella.com/disclaimer&quot;&gt;opinions are my own&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer 2:&lt;/strong&gt; None of the things I’m sharing here are things I’ve learned after starting my job or from the interviews themselves (like every other candidate I’ve signed NDAs).&lt;/p&gt;

&lt;h3 id=&quot;system-architecture-interviews&quot;&gt;System Architecture Interviews&lt;/h3&gt;

&lt;p&gt;Software engineering interviews with Facebook/Google (and similar companies) usually entail 1-2 sessions of system architecture questions. These questions tend to be more abstract – usually with little to no coding – and are trickier to prepare for. They are much easier if you have actual experience with system architecture&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; or are well versed in the topic.&lt;/p&gt;

&lt;p&gt;In addition to seeing how experienced you are with large-scale – usually distributed – systems, these questions examine, among other things, how you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Articulate complex and abstract ideas.&lt;/li&gt;
  &lt;li&gt;Think on your feet and tackle unknown obstacles, while asking the right questions.&lt;/li&gt;
  &lt;li&gt;Zoom out to examine a system as a whole.&lt;/li&gt;
  &lt;li&gt;Make real-world assumptions and balance trade-offs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, system architecture questions are sometimes used to gauge how experienced a candidate is (along with their past work experience). Your performance in these interview sessions might impact the seniority level assigned to you as a candidate.&lt;/p&gt;

&lt;h3 id=&quot;wait-is-this-a-system-architecture-question&quot;&gt;Wait, Is This a System Architecture Question?&lt;/h3&gt;

&lt;p&gt;Or, how to know you’re being asked a system architecture question.&lt;/p&gt;

&lt;p&gt;Architecture questions are often presented in a very vague and under-specified manner. This is routinely intentional, as it enables the interviewer to discern how you “peel-off” an unknown assignment, which clarifying questions you ask, and assumptions you make. This is true for both “regular” coding questions and system architecture ones, but is more crucial in the latter as these tend to be very open-ended, and can be addressed in totally different ways.&lt;/p&gt;

&lt;p&gt;One side-effect of presenting questions this way is that you might not realize you’re being asked a system architecture question. For example, consider the following:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How can we repeatedly find a string in a large dataset?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An eager candidate might immediately jump to the conclusion that having a large dataset searched repeatedly means it must be sorted and then binary-searched in &lt;code&gt;log(n)&lt;/code&gt;, and will start writing the code for mergesort on the whiteboard. All while the interviewer is thinking of a large document corpus and trying to get them to design a search engine.&lt;/p&gt;

&lt;p&gt;Unless you ask some clarifying questions, like: “How big is the data set?”, “What are its characteristics?”, “How do we obtain it?”, you might not realize what you’re up against.&lt;/p&gt;

&lt;p&gt;If you’re uncertain, a good trick here is to try and frame the question as a method signature. If it’s a system architecture question, it will force the interviewer to steer you away from it and think in more abstract terms.&lt;/p&gt;

&lt;h3 id=&quot;concepts-you-should-know&quot;&gt;Concepts You Should Know&lt;/h3&gt;

&lt;p&gt;Here’s a list of concepts/considerations/tools that you should have in your tool belt when approaching system architecture questions. In no particular order, and without being exhaustive:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Amount of data (disk)&lt;/li&gt;
  &lt;li&gt;Amount of RAM (memory)
    &lt;ul&gt;
      &lt;li&gt;Does everything need to be in RAM? (often times – yes)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;RAID configurations&lt;/li&gt;
  &lt;li&gt;Requests/sec&lt;/li&gt;
  &lt;li&gt;Request time&lt;/li&gt;
  &lt;li&gt;Latency&lt;/li&gt;
  &lt;li&gt;Data transfer rates&lt;/li&gt;
  &lt;li&gt;Network limits within a single data center&lt;/li&gt;
  &lt;li&gt;Geographically separated locations (multiple data centers)&lt;/li&gt;
  &lt;li&gt;Sharding/Partitioning (by user/date/content-type/alphabetically)
    &lt;ul&gt;
      &lt;li&gt;How do you re-balance?&lt;/li&gt;
      &lt;li&gt;Consistent hashing for sharding/partitioning&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;CAP theorem&lt;/li&gt;
  &lt;li&gt;MapReduce&lt;/li&gt;
  &lt;li&gt;Distributed hash tables&lt;/li&gt;
  &lt;li&gt;Difference between frontend/backend&lt;/li&gt;
  &lt;li&gt;SOA (service oriented architectures, also “micro-services”)&lt;/li&gt;
  &lt;li&gt;Backups
    &lt;ul&gt;
      &lt;li&gt;Backup a single user on how many servers?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Caching
    &lt;ul&gt;
      &lt;li&gt;Many requests for the same data/lots of updates – should be in cache&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Distribute so that the network is negligible&lt;/li&gt;
  &lt;li&gt;Parallelizing network requests&lt;/li&gt;
  &lt;li&gt;Fan-out (scatter and gather)&lt;/li&gt;
  &lt;li&gt;Load-balancing&lt;/li&gt;
  &lt;li&gt;High availability&lt;/li&gt;
  &lt;li&gt;CDNs (content delivery networks)&lt;/li&gt;
  &lt;li&gt;POPs (points of presence)&lt;/li&gt;
  &lt;li&gt;Queues&lt;/li&gt;
  &lt;li&gt;Failures
    &lt;ul&gt;
      &lt;li&gt;Timeouts&lt;/li&gt;
      &lt;li&gt;Fault tolerance&lt;/li&gt;
      &lt;li&gt;Failing fast&lt;/li&gt;
      &lt;li&gt;Circuit breakers&lt;/li&gt;
      &lt;li&gt;Throttling&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Consensus (e.g. Paxos, Raft) and membership protocols (heartbeats, SWIM)&lt;/li&gt;
  &lt;li&gt;Compression&lt;/li&gt;
  &lt;li&gt;Possible to work harder on writes in order to make reads easier&lt;/li&gt;
  &lt;li&gt;Operations should almost never be more than &lt;code&gt;n*log(n)&lt;/code&gt;, preferably &lt;code&gt;n&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href=&quot;https://github.com/orrsella/soft-eng-interview-prep/blob/master/topics/system-architecture.md&quot;&gt;System Architecture&lt;/a&gt; page of my interview prep notes for more examples, explanations, and links for further reading.&lt;/p&gt;

&lt;h3 id=&quot;numbers&quot;&gt;Numbers&lt;/h3&gt;

&lt;p&gt;Having your “numbers” down is crucial for tackling these questions. What does this mean? It means that you should know by heart how long it takes to make an L1 cache reference, what reading from HDD/SSD means, and how many seconds are in a day, for example. You should also be very comfortable with order-of-magnitude calculations. Without thinking about it too much, you should know how much data is 10^12 bytes, or estimate how much memory is needed to store a trillion web addresses (also RAM vs disk; does it matter?).&lt;/p&gt;

&lt;p&gt;Finally, you’ll be better off if you can easily convert between powers of two and ten. For example, know that 2^20 is roughly 10^6 (and also 1 MB, or more precisely 1 &lt;a href=&quot;https://en.wikipedia.org/wiki/Mebibyte&quot;&gt;MiB&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Doing these calculations correctly and fast sends a very positive signal. In contrast, not being able to make these under pressure can derail your interview into an arithmetic duel, of which rarely can you come out victorious (even if you’ll end up being right).&lt;/p&gt;

&lt;p&gt;Check out my summary of the &lt;a href=&quot;https://github.com/orrsella/soft-eng-interview-prep/blob/master/topics/numbers.md&quot;&gt;Numbers&lt;/a&gt; you should memorize.&lt;/p&gt;

&lt;h3 id=&quot;designing-platforms&quot;&gt;Designing Platforms&lt;/h3&gt;

&lt;p&gt;System architecture questions are usually to solve a specific problem or design a product. Rarely you might be asked to design a more broad platform or a lower-level service. These questions try to gauge what you think good platforms should have, and the types of services/feature you expect to have and use in a distributed environment.&lt;/p&gt;

&lt;p&gt;If tasked with this challenge, here are some features of modern platforms you can throw up on the whiteboard and design with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Monitoring
    &lt;ul&gt;
      &lt;li&gt;Applications (response time, throughput, errors)&lt;/li&gt;
      &lt;li&gt;Operating systems&lt;/li&gt;
      &lt;li&gt;Hardware&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Alerting&lt;/li&gt;
  &lt;li&gt;Metrics (counters)&lt;/li&gt;
  &lt;li&gt;Logging&lt;/li&gt;
  &lt;li&gt;Distributed tracing (cross-service)&lt;/li&gt;
  &lt;li&gt;Datastores&lt;/li&gt;
  &lt;li&gt;Caching&lt;/li&gt;
  &lt;li&gt;Queues&lt;/li&gt;
  &lt;li&gt;Service discovery&lt;/li&gt;
  &lt;li&gt;Configuration&lt;/li&gt;
  &lt;li&gt;Debugging, profiling&lt;/li&gt;
  &lt;li&gt;ALM (application lifecycle management) and deployment
    &lt;ul&gt;
      &lt;li&gt;Continuous deployment&lt;/li&gt;
      &lt;li&gt;Blue-green deployment&lt;/li&gt;
      &lt;li&gt;Rollbacks&lt;/li&gt;
      &lt;li&gt;Canary changes&lt;/li&gt;
      &lt;li&gt;Shadow traffic&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Auto scaling&lt;/li&gt;
  &lt;li&gt;Load balancing, traffic splitting/control&lt;/li&gt;
  &lt;li&gt;KPIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;approaching-a-question&quot;&gt;Approaching a Question&lt;/h3&gt;

&lt;p&gt;I like the following approach to solving these questions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Begin by asking qualifying questions to understand the system you want to design. It’s a good idea to get up to the whiteboard as early as you can, and start writing some features/assumptions you’re making at the edge of the board. Write down the 1-3 key features of the system. What are the most important features this system should have in your opinion?&lt;/li&gt;
  &lt;li&gt;Throw out some numbers to gauge the size of the problem. Give rough estimates to the amount of data/users/requests you’ll need to handle, and deduce the number of servers/HDD/datacenters you’ll need to implement it. Explain the rationale for your assumptions and write them on the board.&lt;/li&gt;
  &lt;li&gt;If you and your interviewer agree on the problem and its size, start a very high level design of the system. This should probably be some rectangles with arrows between them. For example: We’ll have these modules, these types of workers, this queue, that datastore, etc. As you make this high-level design, keep writing things you’ll need to consider or come back to at the edge of the board. Use tools from &lt;a href=&quot;#concepts-you-should-know&quot;&gt;“Concepts You Should Know”&lt;/a&gt; above.&lt;/li&gt;
  &lt;li&gt;Get a sense of what interests your interviewer, which parts they think are key, and dive into them in greater resolution. Do we want to focus on data input? Efficiency? Error handling? Backup? The question can go in so many places, so make sure you’re addressing the most important and relevant parts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;

&lt;p&gt;Finally, you should run through a few examples while preparing for your interview. There are many examples for system architecture questions in sites like Glassdoor. Checkout &lt;a href=&quot;https://github.com/checkcheckzz/system-design-interview#-hot-questions-and-reference&quot;&gt;github.com/checkcheckzz/system-design-interview&lt;/a&gt; for some nice ones.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;These questions are typically asked in interviews of more experienced candidates. New-grads aren’t usually expected to be able to solve them. Instead, some companies ask a lighter variation which mostly revolves around designing APIs for a client application. If you’re not sure what’s expected of you – ask your recruiter! &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 28 May 2016 00:00:00 -0700</pubDate>
        <link>https://orrsella.com/2016/05/28/preparing-for-a-system-architecture-interview/</link>
        <guid isPermaLink="true">https://orrsella.com/2016/05/28/preparing-for-a-system-architecture-interview/</guid>
        
        
      </item>
    
      <item>
        <title>Preparing for a Facebook/Google Software Engineer Interview</title>
        <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; &lt;a href=&quot;https://github.com/orrsella/soft-eng-interview-prep&quot;&gt;This is the theoretical stuff&lt;/a&gt; I think you should &lt;em&gt;know&lt;/em&gt; for an interview with Facebook/Google. Read on for some background and tips.&lt;/p&gt;

&lt;p&gt;In late 2015 I interviewed at both Facebook and Google for a software engineering position. I received offers from both, and eventually decided to &lt;a href=&quot;https://orrsella.com/about&quot;&gt;take Facebook’s one&lt;/a&gt;. In the months leading up to the interviews I prepared &lt;em&gt;a lot&lt;/em&gt;. In this post I’d like to share how I think one should prepare for such an interview and give some tips.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer 1:&lt;/strong&gt; Obviously, &lt;a href=&quot;https://orrsella.com/disclaimer&quot;&gt;opinions are my own&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer 2:&lt;/strong&gt; None of the things I’m sharing here are things I’ve learned after starting my job or from the interviews themselves (like every other candidate I’ve signed NDAs).&lt;/p&gt;

&lt;h3 id=&quot;your-job&quot;&gt;Your Job&lt;/h3&gt;

&lt;p&gt;Or, what an interview is and isn’t.&lt;/p&gt;

&lt;p&gt;Before we get to business, here’s my take on how you should view an interview with Facebook/Google.&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; A lot has been written about how a typical interview with these companies is structured (phone screen, on-site, types of sessions, lengths, whiteboard/paper/computer coding, etc.). If you haven’t already, go read up on Glassdoor/other sites to get familiar with the format. It’s very important that you know what to expect. The more you know beforehand, the easier it will be and more comfortable you’ll feel.&lt;/p&gt;

&lt;p&gt;Regardless of the technicalities – which again, &lt;em&gt;are&lt;/em&gt; important – here’s how I think you should look at this interview. Let’s assume that you’ve already made up your mind that you’d like to work at these companies.&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; From your point of view, the purpose of the interview is to help you &lt;em&gt;get an offer&lt;/em&gt;. That’s it. It is not to showcase your impressive résumé, or make you feel good about yourself, or to show how smart you are. You want to get that offer.&lt;/p&gt;

&lt;p&gt;Your &lt;em&gt;task&lt;/em&gt; in an interview with these companies is obviously to successfully solve the questions you’ll be presented with, but more importantly do it while showing your interviewer how you &lt;em&gt;think&lt;/em&gt; and approach problem solving. Your &lt;em&gt;goal&lt;/em&gt; is to send the right signal that your interviewer is looking to pick up. He or she will most likely be interviewing anywhere between 2 to 5 candidates a week. Remember that and think how you can help them see that you’re a good fit for the company. See &lt;a href=&quot;#dos-and-donts&quot;&gt;more tips below&lt;/a&gt; on how to achieve this.&lt;/p&gt;

&lt;h3 id=&quot;how-to-prepare&quot;&gt;How To Prepare&lt;/h3&gt;

&lt;p&gt;I like to separate preparation to three parts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Theory&lt;/li&gt;
  &lt;li&gt;Coding Problems&lt;/li&gt;
  &lt;li&gt;System Architecture Questions&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;theory&quot;&gt;Theory&lt;/h4&gt;

&lt;p&gt;This includes everything you’re expected to know as a software engineer.&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; Things like: complexity analysis, data structures, algorithms, bit manipulation, operating systems, multi-threading, system architecture, numbers,&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; how hardware works, and networking – to name a few. These are a mix of things that you’ll learn in school, from work experience, and by reading books/blogs/research/etc.&lt;/p&gt;

&lt;p&gt;This is the basis for any discussions you’ll have during your interviews, for the code you’ll write, and for the system architecture solutions you’ll draw on the whiteboard. It’s essential that you have your theory nailed-down, and there’s no reason not to.&lt;/p&gt;

&lt;p&gt;In my preparation, I summarized everything I thought I should’ve &lt;em&gt;known by heart&lt;/em&gt; when coming for the interviews. Once summarized, I read it a few times during the weeks leading up to the interviews and one last time 2-3 days before each of the sessions.&lt;/p&gt;

&lt;p&gt;You can find all my notes here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/orrsella/soft-eng-interview-prep&quot;&gt;https://github.com/orrsella/soft-eng-interview-prep&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or in GitBook format &lt;a href=&quot;https://orrsella.gitbooks.io/soft-eng-interview-prep/content/&quot;&gt;here&lt;/a&gt;. It shouldn’t be a very long read – a few hours should suffice.&lt;/p&gt;

&lt;p&gt;To compile these I read thru &lt;a href=&quot;http://www.amazon.com/gp/product/0262033844?tag=orrsellacom-20&quot;&gt;Cormen&lt;/a&gt; and &lt;a href=&quot;http://www.amazon.com/gp/product/1848000693?tag=orrsellacom-20&quot;&gt;Skiena&lt;/a&gt;, as well as countless other blog posts and Wikipedia articles (some are linked from the notes). It contains both explanations and code examples for what I think is important.&lt;/p&gt;

&lt;h4 id=&quot;coding-problems&quot;&gt;Coding Problems&lt;/h4&gt;

&lt;p&gt;Most of what you’ll do during an interview is write code to solve various problems (other things will be technical discussions, system architecture questions, and &lt;a href=&quot;#ask-questions&quot;&gt;your own questions&lt;/a&gt;). They will usually require at most a few dozens of lines (it’s hard to fit a lot more than that on a whiteboard in ~40 minutes). The best way to prepare for these is to simply practice and solve as many as you can.&lt;/p&gt;

&lt;p&gt;The best resources I used to practice coding questions are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0984782850?tag=orrsellacom-20&quot;&gt;Cracking the Coding Interview, 6th Edition&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/1479274836?tag=orrsellacom-20&quot;&gt;Elements of Programming Interviews&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My recommendation would be to get at least one of these books and solve it cover-to-cover. There are lots of other online tools like &lt;a href=&quot;https://leetcode.com/&quot;&gt;LeetCode&lt;/a&gt; and &lt;a href=&quot;https://knaidu.gitbooks.io/problem-solving/content/index.html&quot;&gt;various&lt;/a&gt; &lt;a href=&quot;http://www.ardendertat.com/2012/01/09/programming-interview-questions/&quot;&gt;question&lt;/a&gt; banks. Quora also has some gems, if you search for something more specific.&lt;/p&gt;

&lt;p&gt;After you feel comfortable with solving these types of questions, run thru some actual questions that were recently asked during interviews at the company you’re interviewing for, by searching Glassdoor.&lt;/p&gt;

&lt;p&gt;In general – unsurprisingly – the more code you’ll write and problems you’ll encounter, the less likely it is that you’ll be surprised when you get to the interview. At some point questions start to repeat themselves, and you’ll recognize the patterns rather quickly.&lt;/p&gt;

&lt;h4 id=&quot;system-architecture-questions&quot;&gt;System Architecture Questions&lt;/h4&gt;

&lt;p&gt;These are a completely different beast than coding questions. They are much more nuanced, and involve a lot more talking/explaining and almost no actual code. Preparing for these is harder and less straight-forward, especially if you haven’t worked on distributed systems before. &lt;a href=&quot;https://orrsella.com/2016/05/28/preparing-for-a-system-architecture-interview/&quot;&gt;See my post on how to prepare for these&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also read these parts of my notes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/orrsella/soft-eng-interview-prep/blob/master/topics/system-architecture.md&quot;&gt;System Architecture&lt;/a&gt; (specifically the &lt;a href=&quot;https://github.com/orrsella/soft-eng-interview-prep/blob/master/topics/system-architecture.md#system-design-question-concepts&quot;&gt;Concepts section&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/orrsella/soft-eng-interview-prep/blob/master/topics/system-architecture-examples.md&quot;&gt;System Architecture Examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And these helpful resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://highscalability.com/&quot;&gt;HighScalability.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/checkcheckzz/system-design-interview&quot;&gt;System Design Interview&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://dancres.github.io/Pages/&quot;&gt;A Distributed Systems Reading List&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;dos-and-donts&quot;&gt;Do’s and Dont’s&lt;/h3&gt;

&lt;p&gt;Some tips, in no particular order:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Write actual code that works, not pseudocode&lt;/li&gt;
  &lt;li&gt;Opt for a mainstream programming language (Java, C/C++, Python, JavaScript)&lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;Practice coding on a whiteboard&lt;sup id=&quot;fnref:6&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;Practice coding on paper (preferably blank, without lines)&lt;/li&gt;
  &lt;li&gt;Write clean code:
    &lt;ul&gt;
      &lt;li&gt;Use good names (classes/functions/variables)&lt;/li&gt;
      &lt;li&gt;Show good modularity (classes/functions)&lt;/li&gt;
      &lt;li&gt;Leave time for error checking and edge cases, even better to start with them (or add &lt;code&gt;TODO&lt;/code&gt;s for yourself)&lt;/li&gt;
      &lt;li&gt;If you’re cutting corners state that out loud, and say what you would do if you had more time (e.g., in Java: &lt;em&gt;I’m using public fields for brevity here, but would otherwise use getters/setters&lt;/em&gt;)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Use proper algorithms and data structures and make sure to state Big-O for all of them&lt;/li&gt;
  &lt;li&gt;When first approaching a problem:
    &lt;ul&gt;
      &lt;li&gt;Make sure you understand the task. Repeat it to show that to yourself and the interviewer&lt;/li&gt;
      &lt;li&gt;Don’t begin by writing code immediately!&lt;/li&gt;
      &lt;li&gt;Ask questions about the task, inputs, assumptions, formats; most questions are &lt;em&gt;under specified&lt;/em&gt; on purpose&lt;/li&gt;
      &lt;li&gt;Assume nothing! Or state you’re doing so&lt;/li&gt;
      &lt;li&gt;Think out loud, share what you’re thinking (brainstorm)&lt;/li&gt;
      &lt;li&gt;Try to show how you think thru the issue&lt;/li&gt;
      &lt;li&gt;Silence isn’t good, long ones are &lt;em&gt;bad&lt;/em&gt;&lt;/li&gt;
      &lt;li&gt;Make sure the interviewer has a clear idea of how you’re doing (so they can help!)&lt;/li&gt;
      &lt;li&gt;Start with a simple example, later add detailed ones&lt;/li&gt;
      &lt;li&gt;Clarify the function signature of the problem early on. This will help focus your thoughts, and possibly invite subtle guidance from your interviewer&lt;/li&gt;
      &lt;li&gt;Start with a &lt;em&gt;simple&lt;/em&gt; inefficient solution (simple != easy)&lt;/li&gt;
      &lt;li&gt;Improve the inefficient one&lt;/li&gt;
      &lt;li&gt;Break down the problem to parts&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Questions are in-depth, usually don’t have an &lt;em&gt;easy&lt;/em&gt; solution (can be simple tho)&lt;/li&gt;
  &lt;li&gt;Think about input validation, constraints&lt;/li&gt;
  &lt;li&gt;Think about test cases, run thru them to make sure code is correct (but don’t assume it’s correct, really check as if someone else wrote it)&lt;/li&gt;
  &lt;li&gt;If the interviewer gave examples/hints &lt;em&gt;use them&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;When done ask if you can refine the code, improving variable names, extracting other methods, etc.&lt;/li&gt;
  &lt;li&gt;Leave out trivial parts as functions that you need to implement, and only go back to those if you have time&lt;/li&gt;
  &lt;li&gt;Upon completion of first solution, either try to improve it, or try to come up with a different solution that is better (e.g.: recursion vs. imperative code)&lt;/li&gt;
  &lt;li&gt;Assumptions might now change, and so the solution needs to be adapted&lt;/li&gt;
  &lt;li&gt;Glossing over standard APIs if you’re not sure is OK, make sure you state that and give a reasonable API to work with&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ask-questions&quot;&gt;Ask Questions&lt;/h3&gt;

&lt;p&gt;At the end of each interview session, your interviewer will usually leave a couple of minutes for your questions. Use this time to ask meaningful questions. This both helps you know the company you’re interviewing for, but also sends a good signal about you. You should come prepared with a few questions, that can range from technical to organizational. Not having any questions isn’t a good sign, so make sure you’re covered.&lt;/p&gt;

&lt;h4 id=&quot;good-luck&quot;&gt;Good Luck!&lt;/h4&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;This, and a lot of other things from this post, also apply to other tech companies – YMMV. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;I recognize that the hiring process by these companies is controversial, and that many people don’t think that it really evaluates your expertise as a software engineer. I’m deliberately ignoring this, and assuming that this is what you want. If you want to get an offer from these companies then this is the “game” you’ll have to play. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;I’m thinking about this from the point of view of an engineer with 3-10-ish years of experience. I assume that if you’re a new grad, expectations are a bit different. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;You’d be surprised how &lt;a href=&quot;https://github.com/orrsella/soft-eng-interview-prep/blob/master/topics/numbers.md&quot;&gt;handy these&lt;/a&gt; could be. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;You can most likely program in any language you want, but you’re better off if your interviewer knows your language of choice and can help if you get stuck. These choices increase the odds of that. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot;&gt;
      &lt;p&gt;Seriously, buy a whiteboard for home to practice on. It will make you feel much more comfortable with it, and you’ll learn how to better manage the space on it. &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 14 May 2016 00:00:00 -0700</pubDate>
        <link>https://orrsella.com/2016/05/14/preparing-for-a-facebook-google-software-engineer-interview/</link>
        <guid isPermaLink="true">https://orrsella.com/2016/05/14/preparing-for-a-facebook-google-software-engineer-interview/</guid>
        
        
      </item>
    
      <item>
        <title>Getting Started With Pants Build for Scala Projects</title>
        <description>&lt;p&gt;I’ve recently been examining a new build tool for large JVM projects (specifically tools aimed at monorepos). There is actually a surprising amount of options for such a tool: Google’s &lt;a href=&quot;http://bazel.io/&quot;&gt;Bazel&lt;/a&gt;, Facebook’s &lt;a href=&quot;http://buckbuild.com/&quot;&gt;Buck&lt;/a&gt;, and &lt;a href=&quot;https://pantsbuild.github.io/&quot;&gt;Pants&lt;/a&gt;, which is developed by Twitter, Foursquare, Square and others – are among the most popular.&lt;/p&gt;

&lt;p&gt;When you start reading the docs for each of them, you get a sense of Déjà vu. And it’s for good reason – all three were modeled after &lt;a href=&quot;http://google-engtools.blogspot.com/2011/08/build-in-cloud-how-build-system-works.html&quot;&gt;Google’s internal build tool&lt;/a&gt;  Blaze.&lt;/p&gt;

&lt;p&gt;From Bazel’s &lt;a href=&quot;http://bazel.io/faq.html&quot;&gt;FAQ&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;What’s up with the word “Blaze” in the codebase?&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;This is an internal name for the tool. Please refer to Bazel as Bazel.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and Pants’ &lt;a href=&quot;https://pantsbuild.github.io/first_concepts.html&quot;&gt;overview&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] Pants models code modules (known as “targets”) and their dependencies in BUILD files—in a manner similar to Google’s internal build system. […]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After going through quite a lot of the docs, I decided to give Pants a try. Besides having a decent amount of documentation, a deployable you can simply install (and not have to build from source), and being actively developed, Pants &lt;a href=&quot;https://pantsbuild.github.io/scala.html&quot;&gt;supports Scala&lt;/a&gt; out-of-the-box, which is exactly what I’m looking for.&lt;/p&gt;

&lt;p&gt;After throughly reading the &lt;a href=&quot;https://pantsbuild.github.io/first_concepts.html&quot;&gt;Overview&lt;/a&gt; and &lt;a href=&quot;https://pantsbuild.github.io/first_tutorial.html&quot;&gt;Tutorial&lt;/a&gt;, I got to Pants’ &lt;a href=&quot;https://pantsbuild.github.io/install.html&quot;&gt;Installation page&lt;/a&gt;, which begins with the following statement:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;As of September 2014, alas, Pants is not something you can just install and use. To be precise: you can install it, but unless you’ve also &lt;a href=&quot;https://pantsbuild.github.io/setup_repo.html&quot;&gt;Set up your code workspace to work with Pants&lt;/a&gt;, it won’t work. You can use it in a workspace in which some Pants expert has set it up.&lt;/p&gt;

  &lt;p&gt;We’re fixing this problem, but we’re not done yet.&lt;/p&gt;

  &lt;p&gt;If want to try out Pants and no Pants expert has set it up for you, you might try &lt;a href=&quot;https://github.com/twitter/commons&quot;&gt;https://github.com/twitter/commons&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;[They are not exaggerating – it really won’t work ;)]&lt;/p&gt;

&lt;p&gt;So that’s exactly what I did – used &lt;a href=&quot;https://github.com/twitter/commons&quot;&gt;twitter/commons&lt;/a&gt; and other &lt;a href=&quot;https://github.com/search?q=filename%3Apants+extension%3Aini&amp;amp;ref=searchresults&amp;amp;type=Code&amp;amp;utf8=%E2%9C%93&quot;&gt;existing projects already configured by “pants experts”&lt;/a&gt; to understand the minimal setup required for a Pants Build project. It wasn’t easy, but eventually payed off. I reduced everything into one small project, which can be found here: &lt;a href=&quot;https://github.com/orrsella/pants-getting-started&quot;&gt;pants-getting-started&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This simple project, which has one &lt;a href=&quot;https://github.com/orrsella/pants-getting-started/blob/master/example/src/main/scala/com/example/HelloWorld.scala&quot;&gt;code file&lt;/a&gt;, and two &lt;a href=&quot;https://github.com/orrsella/pants-getting-started/tree/master/example/src/test/scala/com/example&quot;&gt;tests&lt;/a&gt;, requires the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;BUILD.tools&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;pants.ini&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;ivysettings.xml&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;7 &lt;code&gt;3rdparty&lt;/code&gt; dependencies&lt;/li&gt;
  &lt;li&gt;10 &lt;code&gt;BUILD&lt;/code&gt; files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aside from the cumbersome bootstrapping experience, I’m really enjoying working with Pants so far, and would definitely recommend that you check it out. Want to get started? Use this quick template as a starting point: &lt;a href=&quot;https://github.com/orrsella/pants-getting-started&quot;&gt;https://github.com/orrsella/pants-getting-started&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;tldr&quot;&gt;TL;DR&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip install pantsbuild.pants
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone git@github.com:orrsella/pants-getting-started.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;pants-getting-started/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pants &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;example:&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Sun, 31 May 2015 00:00:00 -0700</pubDate>
        <link>https://orrsella.com/2015/05/31/getting-started-with-pants-build-for-scala-projects/</link>
        <guid isPermaLink="true">https://orrsella.com/2015/05/31/getting-started-with-pants-build-for-scala-projects/</guid>
        
        
      </item>
    
      <item>
        <title>Init.d and Start Scripts for Scala/Java Server Apps</title>
        <description>&lt;p&gt;I like to use two scripts for running and managing the lifecycle of server applications: a &lt;code&gt;start&lt;/code&gt; script and an &lt;code&gt;init.d&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;start&lt;/code&gt; script does the actual job of launching the application. In the case of Scala or Java it fires up the JVM and adds all the necessary arguments (memory, GC, etc.). It should also provide the basic configuration for your application: main entry point, classpath, config file, logging config file, etc. You should be able to easily run the application by simply launching the &lt;code&gt;start&lt;/code&gt; script; however this is not something you’re most likely ever do to – for that you have the &lt;code&gt;init.d&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;init.d&lt;/code&gt; script is used to control the application’s process state and lifecycle: start and stop it, check whether it’s running, and restart it if necessary. It should also manage the application’s &lt;code&gt;pid&lt;/code&gt; file. It could be used for event monitoring, like letting &lt;a href=&quot;https://docs.newrelic.com/docs/agents/java-agent/instrumentation/recording-deployments-java-agent&quot;&gt;an external system know&lt;/a&gt; that the service’s state has changed. The &lt;code&gt;init.d&lt;/code&gt; script doesn’t interact with the app itself, but rather with its &lt;code&gt;start&lt;/code&gt; script. This allows you to decouple application specific configuration from the lifecycle and state of the operating system process.&lt;/p&gt;

&lt;p&gt;Below are the two scripts that I use. These are actually &lt;a href=&quot;http://jinja.pocoo.org/&quot;&gt;jinja2&lt;/a&gt; templates that I use in conjunction with &lt;a href=&quot;http://www.ansible.com/home&quot;&gt;Ansible&lt;/a&gt; to deploy &lt;a href=&quot;https://github.com/orrsella/scala-e2e-testing&quot;&gt;multiple services&lt;/a&gt;. They assume that your application is deployed as a thin jar in &lt;code&gt;BIN_DIR&lt;/code&gt;, with all of its dependencies in the same directory (as can be achieved by using &lt;a href=&quot;http://ant.apache.org/ivy/history/latest-milestone/standalone.html&quot;&gt;standalone Ivy&lt;/a&gt;, &lt;a href=&quot;http://maven.apache.org/&quot;&gt;Maven&lt;/a&gt; and its &lt;code&gt;dependency:get&lt;/code&gt; &lt;a href=&quot;http://maven.apache.org/plugins/maven-dependency-plugin/&quot;&gt;plugin&lt;/a&gt;, or simply by exploding a fat jar downloaded on the server).&lt;/p&gt;

&lt;h3 id=&quot;start-script&quot;&gt;Start Script&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;MAIN_CLASS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={{&lt;/span&gt; main_class &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;APP_CONFIG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={{&lt;/span&gt; app_config &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;LOG_CONFIG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={{&lt;/span&gt; log_config &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;BIN_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={{&lt;/span&gt; bin_dir &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# ***********************************************&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ***********************************************&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;ARGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;-Dconfig.file=${APP_CONFIG} -Dlogback.configurationFile=${LOG_CONFIG}&amp;quot;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;java &lt;span class=&quot;nv&quot;&gt;$ARGS&lt;/span&gt; -cp &lt;span class=&quot;s2&quot;&gt;&amp;quot;$BIN_DIR/*&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$MAIN_CLASS&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(Gist found &lt;a href=&quot;https://gist.github.com/orrsella/e6b74108270fe6015aac&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;(For application configuration I’m using &lt;a href=&quot;https://github.com/typesafehub/config&quot;&gt;Typesafe config&lt;/a&gt; with the &lt;code&gt;config.file&lt;/code&gt; parameter, and &lt;a href=&quot;http://logback.qos.ch/&quot;&gt;Logback&lt;/a&gt; with the &lt;code&gt;logback.configurationFile&lt;/code&gt; parameter for logging, but that shouldn’t matter at all. Customize as needed.)&lt;/p&gt;

&lt;p&gt;I usually like to place the &lt;code&gt;start&lt;/code&gt; script right next to the &lt;code&gt;BIN_DIR&lt;/code&gt; in a &lt;code&gt;script&lt;/code&gt; directory. Here’s my typical structure:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tree /opt/myapp
├── bin
│   ├── com.example.myapp-1.0.0.jar
│   └── ... &lt;span class=&quot;c&quot;&gt;# all your dependency jars&lt;/span&gt;
├── conf
│   ├── application.conf
│   └── logback.xml
└── script
    └── start&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All of these pieces are put in-place by the &lt;a href=&quot;http://www.ansible.com/home&quot;&gt;CM tool&lt;/a&gt;. Launching the &lt;code&gt;start&lt;/code&gt; script will run the application interactively in the logged in session, displaying &lt;code&gt;stdout&lt;/code&gt; in the terminal. This could be useful for debugging, but should generally be avoided – you should start the app from the &lt;code&gt;init.d&lt;/code&gt; script.&lt;/p&gt;

&lt;h3 id=&quot;initd-script&quot;&gt;Init.d Script&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;START_SCRIPT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={{&lt;/span&gt; start_script &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PID_FILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={{&lt;/span&gt; pid_file &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# ***********************************************&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ***********************************************&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;ARGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# optional start script arguments&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;DAEMON&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$START_SCRIPT&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# colors&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;red&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;\e[0;31m&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;green&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;\e[0;32m&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;yellow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;\e[0;33m&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;\e[0m&amp;#39;&lt;/span&gt;

echoRed&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;${red}$1${reset}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
echoGreen&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;${green}$1${reset}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
echoYellow&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;${yellow}$1${reset}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

start&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;PID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DAEMON&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ARGS&lt;/span&gt; &amp;gt; /dev/null 2&amp;gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$!&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;$1&amp;quot;&lt;/span&gt; in
start&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -f &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;PID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;cat &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -z &lt;span class=&quot;s2&quot;&gt;&amp;quot;`ps axf | grep -w ${PID} | grep -v grep`&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
            start
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            echoYellow &lt;span class=&quot;s2&quot;&gt;&amp;quot;Already running [$PID]&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;0
        &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        start
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -z &lt;span class=&quot;nv&quot;&gt;$PID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        echoRed &lt;span class=&quot;s2&quot;&gt;&amp;quot;Failed starting&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;3
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PID&lt;/span&gt; &amp;gt; &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt;
        echoGreen &lt;span class=&quot;s2&quot;&gt;&amp;quot;Started [$PID]&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;0
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;

status&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -f &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;PID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;cat &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -z &lt;span class=&quot;s2&quot;&gt;&amp;quot;`ps axf | grep -w ${PID} | grep -v grep`&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
            echoRed &lt;span class=&quot;s2&quot;&gt;&amp;quot;Not running (process dead but pidfile exists)&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            echoGreen &lt;span class=&quot;s2&quot;&gt;&amp;quot;Running [$PID]&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;0
        &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        echoRed &lt;span class=&quot;s2&quot;&gt;&amp;quot;Not running&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;3
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;

stop&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -f &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;PID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;cat &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; -z &lt;span class=&quot;s2&quot;&gt;&amp;quot;`ps axf | grep -w ${PID} | grep -v grep`&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
            echoRed &lt;span class=&quot;s2&quot;&gt;&amp;quot;Not running (process dead but pidfile exists)&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;PID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;cat &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;kill&lt;/span&gt; -HUP &lt;span class=&quot;nv&quot;&gt;$PID&lt;/span&gt;
            echoGreen &lt;span class=&quot;s2&quot;&gt;&amp;quot;Stopped [$PID]&amp;quot;&lt;/span&gt;
            rm -f &lt;span class=&quot;nv&quot;&gt;$PID_FILE&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;0
        &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        echoRed &lt;span class=&quot;s2&quot;&gt;&amp;quot;Not running (pid not found)&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;3
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;

restart&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; stop
    &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; start
&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;

*&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Usage: $0 {status|start|stop|restart}&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(Gist found &lt;a href=&quot;https://gist.github.com/orrsella/6ccaa03886bc857e00e4&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This script is a lot more complicated. Let’s break it down:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You would normally put this script in &lt;code&gt;/etc/init.d/myapp&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The script accepts the following commands: &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;start&lt;/code&gt;, &lt;code&gt;stop&lt;/code&gt; and &lt;code&gt;restart&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;START_SCRIPT&lt;/code&gt; should be the location of the &lt;code&gt;start&lt;/code&gt; script.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;PID_FILE&lt;/code&gt; is where you want your &lt;code&gt;pid&lt;/code&gt; file saved, usually: &lt;code&gt;/var/run/myapp.pid&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The script is intelligent enough not to let you start two instances of the app if it’s already running.&lt;/li&gt;
  &lt;li&gt;Standard script &lt;a href=&quot;http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html&quot;&gt;exit codes&lt;/a&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;0&lt;/code&gt; – program is running or service is OK&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;1&lt;/code&gt; – program is dead and /var/run pid file exists&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;3&lt;/code&gt; – program is not running&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Running each of the commands will output a colored status message with the result. For example:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sudo /etc/init.d/myapp start
Started &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;27882&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# &amp;lt;= trust me, this is green&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The combination of these two scripts offers a robust way to manage the lifecycle of the app. I think they provide a good separation of concerns, and allow the &lt;code&gt;init.d&lt;/code&gt; script to be reusable for multiple types of applications, provided that they have a &lt;code&gt;start&lt;/code&gt; script. Only the &lt;code&gt;start&lt;/code&gt; script intimately knows the app and that it’s is JVM-based, and it does not bother itself with environment concerns like process ids and such.&lt;/p&gt;

&lt;p&gt;If you’re interested in the rest of the deployment code I use for such server apps you can check out &lt;a href=&quot;https://github.com/orrsella/scala-e2e-testing/tree/master/ansible/roles/memento-finatra&quot;&gt;this Ansible&lt;/a&gt; role.&lt;/p&gt;

&lt;p&gt;Have a comment or a suggestion for a better way to do any of this? &lt;a href=&quot;https://twitter.com/orrsella&quot;&gt;Please let me know!&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 06 Nov 2014 00:00:00 -0800</pubDate>
        <link>https://orrsella.com/2014/11/06/initd-and-start-scripts-for-scala-java-server-apps/</link>
        <guid isPermaLink="true">https://orrsella.com/2014/11/06/initd-and-start-scripts-for-scala-java-server-apps/</guid>
        
        
      </item>
    
      <item>
        <title>Embedded Elasticsearch Server for Scala Integration Tests</title>
        <description>&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Integration_testing&quot;&gt;Integration tests&lt;/a&gt; are used to check how our code works against code we can’t change. As described in &lt;a href=&quot;http://www.growing-object-oriented-software.com/&quot;&gt;GOOS&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We use the term integration tests to refer to the tests that check how some of our code works with code from outside the team that we can’t change. It might be a public framework, such as a persistence mapper, or a library from another team within our organization. The distinction is that integration tests make sure that any abstractions we build over third-party code work as we expect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A classic example for an Integration Test is for a &lt;a href=&quot;http://en.wikipedia.org/wiki/Data_access_object&quot;&gt;&lt;code&gt;Dao&lt;/code&gt; class&lt;/a&gt;. Let’s assume that we have some abstract &lt;code&gt;PersonDao&lt;/code&gt; trait, that defines how we store, fetch, and search for &lt;code&gt;Person&lt;/code&gt;s. A hypothetical application could have an implementation of that trait: &lt;code&gt;ElasticsearchPersonDao&lt;/code&gt; which abstracts over &lt;a href=&quot;http://www.elasticsearch.org/&quot;&gt;Elasticsearch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To make sure that our &lt;code&gt;Dao&lt;/code&gt; implementation works with Elasticsearch as intended and that it fulfills the &lt;code&gt;PersonDao&lt;/code&gt; contract, we should have an Integration Test. During that test we want to run against an actual instance of Elasticsearch, as close to the real thing as possible. One way to achieve this is to have our test bring-up an embedded server version of Elasticsearch, have the &lt;code&gt;Dao&lt;/code&gt; work against that server, and then shut it down.&lt;/p&gt;

&lt;p&gt;Doing so for Elasticsearch is particularly easy since Elasticsearch is &lt;a href=&quot;http://www.elasticsearch.org/guide/en/elasticsearch/client/java-api/master/java-api.html&quot;&gt;written in Java&lt;/a&gt;. Let’s see how to do this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;k&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.example&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.nio.file.Files&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.apache.commons.io.FileUtils&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.elasticsearch.client.Client&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.elasticsearch.common.settings.ImmutableSettings&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.elasticsearch.node.NodeBuilder._&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ElasticsearchServer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clusterName&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;elasticsearch&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataDir&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Files&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;createTempDirectory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;elasticsearch_data_&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toFile&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ImmutableSettings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settingsBuilder&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;path.data&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataDir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;cluster.name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clusterName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nodeBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;FileUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;forceDelete&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataDir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// dataDir cleanup failed&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;createAndWaitForIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prepareCreate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actionGet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cluster&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prepareHealth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWaitForActiveShards&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actionGet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s see what’s going on here. First of all this code assumes that you have Elasticsearch as a &lt;a href=&quot;http://www.elasticsearch.org/guide/en/elasticsearch/client/java-api/master/_maven_repository.html&quot;&gt;dependency&lt;/a&gt; (which you probably do since you’re using it as your datastore…). It also uses apache  &lt;code&gt;commons-io&lt;/code&gt; &lt;code&gt;FileUtils&lt;/code&gt; (version 2.4) for performing directory cleanup. If this is a problem you can easily write this cleanup code yourself.&lt;/p&gt;

&lt;p&gt;After creating the settings, a &lt;code&gt;nodeBuilder&lt;/code&gt; is used to create a &lt;code&gt;local&lt;/code&gt; Elasticsearch &lt;code&gt;Node&lt;/code&gt;. A &lt;code&gt;Node&lt;/code&gt; can be used as a &lt;a href=&quot;http://www.elasticsearch.org/guide/en/elasticsearch/client/java-api/current/client.html&quot;&gt;way to connect&lt;/a&gt; to an existing Elasticsearch cluster, or it can form a cluster. To start the &lt;code&gt;Node&lt;/code&gt; we use the &lt;code&gt;start/stop&lt;/code&gt; methods. Notice that the &lt;code&gt;node&lt;/code&gt; is a &lt;code&gt;lazy val&lt;/code&gt;, which means it isn’t initialized until accessed. After starting the node, the &lt;code&gt;client&lt;/code&gt; can be passed to the &lt;code&gt;Dao&lt;/code&gt; object, which wouldn’t be able to tell if it’s talking to a remote cluster or a local node – exactly what we want.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createAndWaitForIndex&lt;/code&gt; convenience method helps us create the &lt;code&gt;index&lt;/code&gt; we’re going to use during the test setup, otherwise an &lt;code&gt;IndexMissingException&lt;/code&gt; will be thrown and fail the test.&lt;/p&gt;

&lt;p&gt;Let’s see how a test would use the &lt;code&gt;ElasticsearchServer&lt;/code&gt; to exercise the &lt;code&gt;Dao&lt;/code&gt; (this example uses the &lt;a href=&quot;http://etorreborre.github.io/specs2/&quot;&gt;specs2&lt;/a&gt; test library):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;k&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.example&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.UUID&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.specs2.mutable.Specification&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.specs2.specification.Scope&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ElasticsearchPersonDaoIntegrationTest&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Specification&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersonMatchers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ElasticsearchServer&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dao&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ElasticsearchPersonDao&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;createAndWaitForIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;persons&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;s&quot;&gt;&amp;quot;Elasticsearch person dao&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;quot;return None for a non-existing person&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dao&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randomUUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;must&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beNone&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;s&quot;&gt;&amp;quot;create and then return a person&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dao&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dao&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;must&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beSome&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;must&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;haveName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A few notes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We are using &lt;a href=&quot;http://etorreborre.github.io/specs2/guide/SPECS2-2.4.17/org.specs2.guide.Structure.html#Steps&quot;&gt;specs2’s &lt;code&gt;step&lt;/code&gt;s&lt;/a&gt; for bringing-up and tearing-down our embedded server.&lt;/li&gt;
  &lt;li&gt;The use of &lt;code&gt;Context&lt;/code&gt; provides us with variable isolation between every test case. A new &lt;code&gt;Dao&lt;/code&gt; object is created every time, but it always uses the same &lt;code&gt;client&lt;/code&gt; to connect to our &lt;code&gt;Node&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Our second test case checks both the &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;get&lt;/code&gt; functions of the &lt;code&gt;Dao&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;We’re using custom &lt;code&gt;PersonMatchers&lt;/code&gt; to make the second test assertion a little nicer. These could go a long way for complex/nested data objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s all you need to start creating Elasticsearch Integration Tests. All that’s left is implementing the &lt;code&gt;Dao&lt;/code&gt; itself. Having comprehensive datastore ITs will enable you seamlessly swipe out your datastore for another one, assuming your Integration Test passes for all of them. The exact same test could be used to test a hypothetical &lt;code&gt;MySqlPersonDao&lt;/code&gt;, only with a different embedded server. If such a scenario arises, you should make the test abstract and run it for both &lt;code&gt;Dao&lt;/code&gt;s.&lt;/p&gt;
</description>
        <pubDate>Tue, 28 Oct 2014 00:00:00 -0700</pubDate>
        <link>https://orrsella.com/2014/10/28/embedded-elasticsearch-server-for-scala-integration-tests/</link>
        <guid isPermaLink="true">https://orrsella.com/2014/10/28/embedded-elasticsearch-server-for-scala-integration-tests/</guid>
        
        
      </item>
    
      <item>
        <title>HTTP Request Diagnostics With cURL</title>
        <description>&lt;p&gt;I had recently needed to diagnose some HTTP requests to understand where time was spent, download speeds, etc. &lt;a href=&quot;https://josephscott.org/archives/2011/10/timing-details-with-curl/&quot;&gt;This great post&lt;/a&gt; by Joseph Scott shows how to get timing info for a request using curl. I expanded on it by adding all available curl &lt;code&gt;--write-out&lt;/code&gt; variables and HTTP headers (sample response below).&lt;/p&gt;

&lt;p&gt;Here’s what you need to do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Create a file for the curl formatting (named &lt;code&gt;curl-format&lt;/code&gt; in our case).&lt;/li&gt;
  &lt;li&gt;Add the following to &lt;code&gt;curl-format&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;\n\n
      content_type: %{content_type}\n
filename_effective: %{filename_effective}\n
    ftp_entry_path: %{ftp_entry_path}\n
         http_code: %{http_code}\n
      http_connect: %{http_connect}\n
          local_ip: %{local_ip}\n
        local_port: %{local_port}\n
      num_connects: %{num_connects}\n
     num_redirects: %{num_redirects}\n
      redirect_url: %{redirect_url}\n
         remote_ip: %{remote_ip}\n
       remote_port: %{remote_port}\n
     size_download: %{size_download}\n
       size_header: %{size_header}\n
      size_request: %{size_request}\n
       size_upload: %{size_upload}\n
    speed_download: %{speed_download}\n
      speed_upload: %{speed_upload}\n
 ssl_verify_result: %{ssl_verify_result}\n
     url_effective: %{url_effective}\n
\n\n
   time_namelookup: %{time_namelookup}\n
      time_connect: %{time_connect}\n
   time_appconnect: %{time_appconnect}\n
  time_pretransfer: %{time_pretransfer}\n
     time_redirect: %{time_redirect}\n
time_starttransfer: %{time_starttransfer}\n
                   -------\n
        time_total: %{time_total}\n
\n&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then make a request with the format file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl -v -w &lt;span class=&quot;s2&quot;&gt;&amp;quot;@curl-format&amp;quot;&lt;/span&gt; -o /dev/null -s http://www.orrsella.com&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Example response:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;* Adding handle: conn: 0x7f8b3b803600
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f8b3b803600) send_pipe: 1, recv_pipe: 0
* About to connect() to www.orrsella.com port 80 (#0)
*   Trying 104.131.121.209...
* Connected to www.orrsella.com (104.131.121.209) port 80 (#0)
&amp;gt; GET / HTTP/1.1
&amp;gt; User-Agent: curl/7.30.0
&amp;gt; Host: www.orrsella.com
&amp;gt; Accept: */*
&amp;gt;
&amp;lt; HTTP/1.1 301 Moved Permanently
* Server nginx/1.4.6 (Ubuntu) is not blacklisted
&amp;lt; Server: nginx/1.4.6 (Ubuntu)
&amp;lt; Date: Mon, 06 Oct 2014 13:42:42 GMT
&amp;lt; Content-Type: text/html
&amp;lt; Content-Length: 193
&amp;lt; Connection: keep-alive
&amp;lt; Location: http://orrsella.com/
&amp;lt;
{ [data not shown]
* Connection #0 to host www.orrsella.com left intact


      content_type: text/html
filename_effective: /dev/null
    ftp_entry_path:
         http_code: 301
      http_connect: 000
          local_ip: 192.168.28.249
        local_port: 58388
      num_connects: 1
     num_redirects: 0
      redirect_url: http://orrsella.com/
         remote_ip: 104.131.121.209
       remote_port: 80
     size_download: 193
       size_header: 203
      size_request: 80
       size_upload: 0
    speed_download: 689.000
      speed_upload: 0.000
 ssl_verify_result: 0
     url_effective: http://www.orrsella.com/


   time_namelookup: 0.001
      time_connect: 0.141
   time_appconnect: 0.000
  time_pretransfer: 0.141
     time_redirect: 0.000
time_starttransfer: 0.280
                   -------
        time_total: 0.280&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Check out the &lt;a href=&quot;http://curl.haxx.se/docs/manpage.html&quot;&gt;curl man page&lt;/a&gt; for a detailed explanation of each of the used &lt;code&gt;%{variable}&lt;/code&gt;s.&lt;/p&gt;
</description>
        <pubDate>Mon, 06 Oct 2014 00:00:00 -0700</pubDate>
        <link>https://orrsella.com/2014/10/06/http-request-diagnostics-with-curl/</link>
        <guid isPermaLink="true">https://orrsella.com/2014/10/06/http-request-diagnostics-with-curl/</guid>
        
        
      </item>
    
      <item>
        <title>True End-to-End Testing in Scala: Scalapeño 2014 Talk</title>
        <description>&lt;p&gt;Earlier this week I gave the following talk at &lt;a href=&quot;http://www.scalapeno.org.il/#!orr-sella/czmu&quot;&gt;Scalapeño 2014&lt;/a&gt;. Below are &lt;a href=&quot;https://speakerdeck.com/orrsella/true-end-to-end-testing-in-scala&quot;&gt;the slides&lt;/a&gt; for your convenience. The &lt;a href=&quot;https://www.parleys.com/tutorial/orr-sella-true-end-end-testing-scala&quot;&gt;video recording&lt;/a&gt; can be found on the conference’s Parleys channel. The talk is also accompanied by a very detailed &lt;a href=&quot;https://github.com/orrsella/scala-e2e-testing&quot;&gt;code example&lt;/a&gt; that shows how to implements all the discussed concepts.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In this talk we will show how we can take our unit/integration tests a step further, and see how to test our applications end-to-end. Scala is a prime candidate for end-to-end testing, having all the right pieces in place: an easily extendable build tool (SBT), fluent DSL testing libraries (Specs2/ScalaTest), and the power/tooling of the JVM behind it.&lt;/p&gt;

  &lt;p&gt;We will see how to approach testing our application from the outside, and touch on concepts such as: the Test Harness, abstracting our SUT (System Under Test) by using test Drivers, using Fakes for testing against external dependencies, and more. We will put everything together by using tools such as: SBT, Ansible and Vagrant.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;script async=&quot;&quot; class=&quot;speakerdeck-embed&quot; data-id=&quot;c27fd3803ec60132416222d5471c564c&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;https://orrsella.com//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

</description>
        <pubDate>Wed, 24 Sep 2014 00:00:00 -0700</pubDate>
        <link>https://orrsella.com/2014/09/24/true-end-to-end-testing-in-scala-scalapeno-2014-talk/</link>
        <guid isPermaLink="true">https://orrsella.com/2014/09/24/true-end-to-end-testing-in-scala-scalapeno-2014-talk/</guid>
        
        
      </item>
    
      <item>
        <title>Integration and End-to-End Test Configurations in SBT</title>
        <description>&lt;p&gt;It is common to have three levels of tests:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Unit Tests – Checking if your objects do the right thing, if they work correctly. Usually tests methods/classes/small clusters of classes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Integration Tests – Testing if your code works against code that you can’t change (3rd party or internal code that you can’t influence). Are your abstractions over that 3rd party code correct and used as intended?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;End-to-End Tests – Checking if the whole system works and composes correctly.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When developing using TDD, I find it very useful to be able to choose which type of tests to run. Each kind of testing has its own trade-offs, and I sometimes find myself wanting to run a specific group of tests (for example: only quickly running unit tests and not end-to-end tests, which take far longer to complete).&lt;/p&gt;

&lt;p&gt;To achieve this, here is how I like to structure my projects:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;src
├── e2e
├── it
├── main
├── test
└── ...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is the typical &lt;a href=&quot;http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html&quot;&gt;Maven directory layout &lt;/a&gt;, with the additional testing source roots. I place my unit tests under the &lt;code&gt;test/&lt;/code&gt; source directory and name them &lt;code&gt;*Test&lt;/code&gt;, my integration tests under &lt;code&gt;it/&lt;/code&gt; and named &lt;code&gt;*IntegrationTest&lt;/code&gt;, and – unsurprisingly – end-to-end tests under &lt;code&gt;e2e/&lt;/code&gt; and named &lt;code&gt;*EndToEndTest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This separation clearly divides the types of tests and allows granularity in running them. Here is how to configure this in SBT using &lt;code&gt;.scala&lt;/code&gt; &lt;a href=&quot;http://www.scala-sbt.org/0.13.5/docs/Getting-Started/Full-Def.html&quot;&gt;build configuration&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// project/Configs.scala&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sbt._&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Configs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntegrationTest&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;it&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Runtime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EndToEndTest&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;e2e&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Runtime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;IntegrationTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EndToEndTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// project/Testing.scala&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Testing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;testAll&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TaskKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;test-all&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itSettings&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;IntegrationTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Defaults&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;testSettings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntegrationTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;parallelExecution&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntegrationTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;scalaSource&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntegrationTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseDirectory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;src/it/scala&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e2eSettings&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;EndToEndTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Defaults&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;testSettings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EndToEndTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;parallelExecution&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EndToEndTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;scalaSource&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EndToEndTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseDirectory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;src/e2e/scala&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;itSettings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e2eSettings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;testAll&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EndToEndTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntegrationTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When defining your projects, add the new configs and settings:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sbt._&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sbt.Keys._&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TheBuild&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;root&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Configs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Testing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then to run only a specific test configuration (end-to-end for example):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sbt&amp;gt; e2e:test&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We also added the &lt;code&gt;testAll&lt;/code&gt; task, so we can run all tests together:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sbt&amp;gt; &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;-all&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you need more examples you can check out my &lt;a href=&quot;https://github.com/orrsella/scala-e2e-testing/tree/master/memento/project&quot;&gt;scala-e2e-testing&lt;/a&gt; sample project, which shows how to test your Scala apps end-to-end, and uses this project structure.&lt;/p&gt;
</description>
        <pubDate>Wed, 24 Sep 2014 00:00:00 -0700</pubDate>
        <link>https://orrsella.com/2014/09/24/integration-and-end-to-end-test-configurations-in-sbt-for-scala-java-projects/</link>
        <guid isPermaLink="true">https://orrsella.com/2014/09/24/integration-and-end-to-end-test-configurations-in-sbt-for-scala-java-projects/</guid>
        
        
      </item>
    
  </channel>
</rss>
