<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Distributed-Systems on traviscj/blog</title>
    <link>https://traviscj.com/blog/tags/distributed-systems/</link>
    <description>Recent content in Distributed-Systems on traviscj/blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 24 Jun 2025 19:47:52 -0500</lastBuildDate>
    <atom:link href="https://traviscj.com/blog/tags/distributed-systems/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Evolution of a Get Endpoint</title>
      <link>https://traviscj.com/blog/post/2025-06-24-evolution-of-a-get-endpoint/</link>
      <pubDate>Tue, 24 Jun 2025 19:47:52 -0500</pubDate>
      <guid>https://traviscj.com/blog/post/2025-06-24-evolution-of-a-get-endpoint/</guid>
      <description>&lt;p&gt;My work project started pretty simple: there was a simple &lt;code&gt;GetXyz&lt;/code&gt; endpoint that just looked up the &lt;code&gt;xyz&lt;/code&gt; record in the database by a unique key &amp;amp; returned it.&#xA;How complicated could it be?&lt;/p&gt;&#xA;&lt;p&gt;It was a straightforward generalization of an old &lt;code&gt;GetAbc&lt;/code&gt; functionality, it was really only used by oncall engineers through an admin console, it shouldn&amp;rsquo;t have been too big of a deal.&lt;/p&gt;&#xA;&lt;p&gt;Ok, but then it outgrew its original datastore, so a separate service had to be created.&#xA;We thought about migrating clients, but at the time it seemed faster to just implement once on our side &amp;amp; have clients continue calling us; essentially encapsulating the separate service as an implementation detail.&#xA;But as part of the traffic swing, we figured it should support either the &lt;code&gt;local&lt;/code&gt; or the &lt;code&gt;remote&lt;/code&gt; read path.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Transacter and Intent/Result</title>
      <link>https://traviscj.com/blog/post/2022-06-15-transacter-and-intent-result/</link>
      <pubDate>Wed, 15 Jun 2022 08:07:47 -0500</pubDate>
      <guid>https://traviscj.com/blog/post/2022-06-15-transacter-and-intent-result/</guid>
      <description>&lt;p&gt;At SQ, we had a family of &lt;code&gt;Transacter&lt;/code&gt; interfaces:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Transacter&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;transaction&lt;/span&gt;(Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Session, Void&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; session);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Session&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    DSLContext &lt;span style=&#34;color:#a6e22e&#34;&gt;dsl&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;where &lt;code&gt;DSLContext&lt;/code&gt; is a &lt;a href=&#34;https://www.jooq.org/javadoc/latest/org.jooq/org/jooq/DSLContext.html&#34;&gt;jOOQ concept&lt;/a&gt; &amp;amp; is the handle for doing work against the database.&#xA;Then this would be used in some class like&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;KvDao&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;@Inject&lt;/span&gt; Transacter transacter;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;put&lt;/span&gt;(String ns, String k, String v) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    transacter.&lt;span style=&#34;color:#a6e22e&#34;&gt;transaction&lt;/span&gt;(session &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        KvRecord record &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; KvRecord(ns, k, v);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        session.&lt;span style=&#34;color:#a6e22e&#34;&gt;dsl&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;insertInto&lt;/span&gt;(KV).&lt;span style=&#34;color:#a6e22e&#34;&gt;set&lt;/span&gt;(record).&lt;span style=&#34;color:#a6e22e&#34;&gt;execute&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The parameters &lt;code&gt;ns&lt;/code&gt;, &lt;code&gt;k&lt;/code&gt;, and &lt;code&gt;v&lt;/code&gt; are shorthand for &lt;code&gt;namespace&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt;, and &lt;code&gt;value&lt;/code&gt;, respectively.&#xA;We&amp;rsquo;ll show how these might be used together shortly!&lt;/p&gt;</description>
    </item>
    <item>
      <title>feeds justification</title>
      <link>https://traviscj.com/blog/post/2019-06-11-feeds_justification/</link>
      <pubDate>Tue, 11 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2019-06-11-feeds_justification/</guid>
      <description>&lt;p&gt;I realized I&amp;rsquo;ve left out a major part from my &lt;a href=&#34;https://traviscj.com/blog/post/2019-01-08-feed_sequences/&#34;&gt;sequence&lt;/a&gt; of &lt;a href=&#34;https://traviscj.com/blog/post/2018-10-03-feeds_as_cache_invalidation_mechanism/&#34;&gt;previous&lt;/a&gt; &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;feed&lt;/a&gt;-&lt;a href=&#34;https://traviscj.com/blog/post/2018-07-10-cross-dc-sync-with-feed-published_kv/&#34;&gt;related&lt;/a&gt; &lt;a href=&#34;https://traviscj.com/blog/post/2018-10-29-sharded_feeds/&#34;&gt;posts&lt;/a&gt;: a justification for why we should bother with a separate &lt;code&gt;feed_sync_id&lt;/code&gt;.&#xA;So let&amp;rsquo;s give it a shot!&#xA;The fundamental problem is:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;AUTO_INCREMENT&lt;/code&gt; ids are &lt;em&gt;assigned&lt;/em&gt; in &lt;strong&gt;insertion&lt;/strong&gt; order, but become visible to other threads in &lt;strong&gt;commit&lt;/strong&gt; order.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;To see how this causes a problem, consider the interactions and visibilities between three transactions to the same database:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;t0: TRX0: BEGIN; INSERT INTO kv (ns, k, v) VALUES (&amp;quot;-&amp;quot;, &amp;quot;k0&amp;quot;, &amp;quot;v0&amp;quot;); COMMIT;&#xA;t1: TRX1: BEGIN; INSERT INTO kv (ns, k, v) VALUES (&amp;quot;-&amp;quot;, &amp;quot;k1&amp;quot;, &amp;quot;v1&amp;quot;);&#xA;t2: TRX2: BEGIN; INSERT INTO kv (ns, k, v) VALUES (&amp;quot;-&amp;quot;, &amp;quot;k2&amp;quot;, &amp;quot;v2&amp;quot;);&#xA;t3: TRX0: SELECT MAX(id) FROM kv;&#xA;t4: TRX2: COMMIT;&#xA;t5: TRX0: SELECT MAX(id) FROM kv;&#xA;t6: TRX1: COMMIT;&#xA;t7: TRX0: SELECT MAX(id) FROM kv;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Here, we have two transactions that both insert a new &lt;code&gt;kv&lt;/code&gt; record.&#xA;The database &lt;em&gt;has&lt;/em&gt; to assign an &lt;code&gt;id&lt;/code&gt; value to each of those records, because we might be creating other associations to those records in our application code.&#xA;But other threads &amp;ndash; &lt;code&gt;TRX0&lt;/code&gt; in this case &amp;ndash; shouldn&amp;rsquo;t be able to see those records until we &lt;code&gt;COMMIT&lt;/code&gt;, and so indeed the &lt;code&gt;SELECT&lt;/code&gt; at &lt;code&gt;t=t3&lt;/code&gt; might return &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>absolutely minimal OLTP to OLAP pipeline</title>
      <link>https://traviscj.com/blog/post/2019-04-25-oltp_to_olap/</link>
      <pubDate>Thu, 25 Apr 2019 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2019-04-25-oltp_to_olap/</guid>
      <description>&lt;p&gt;Suppose we have some data in a production OLTP database, and we need to send it to some OLAP database.&#xA;This post describes one of the simplest approaches, and how to make it productional enough to rely on.&lt;/p&gt;&#xA;&lt;p&gt;For every table &lt;code&gt;t&lt;/code&gt;, we need to:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;introduce a new field, &lt;code&gt;updated_at&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;introduce a new index on that field, so we can get the records that changed after a certain &lt;code&gt;updated_at&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For example,&lt;/p&gt;</description>
    </item>
    <item>
      <title>feed sequences</title>
      <link>https://traviscj.com/blog/post/2019-01-08-feed_sequences/</link>
      <pubDate>Tue, 08 Jan 2019 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2019-01-08-feed_sequences/</guid>
      <description>&lt;p&gt;In the &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;mysql feeds&lt;/a&gt; post, I mentioned that the publisher could do&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;(feed_sync_id)&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; kv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to find the next &lt;code&gt;feed_sync_id&lt;/code&gt; during the publishing process, but&#xA;&lt;strong&gt;this is actually a really bad idea.&lt;/strong&gt;&#xA;(And I knew it at the time, so forgive me for selling lies&amp;hellip;)&lt;/p&gt;&#xA;&lt;h2 id=&#34;republishing&#34;&gt;Republishing&lt;/h2&gt;&#xA;&lt;p&gt;Before we jump into the problematic scenario, I&amp;rsquo;d like to motivate it with a tiny bit of background.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;republish&lt;/em&gt; operation is extremely useful when consumers need to receive updates.&#xA;It is also extremely simple!&#xA;A query like&lt;/p&gt;</description>
    </item>
    <item>
      <title>tradeoffs</title>
      <link>https://traviscj.com/blog/post/2019-01-01-tradeoffs/</link>
      <pubDate>Tue, 01 Jan 2019 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2019-01-01-tradeoffs/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;Life is (just) a series of tradeoffs.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;DawnAnn &amp;ldquo;Mom&amp;rdquo; Johnson&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I heard this so many times growing up that I think I actually &lt;em&gt;stopped&lt;/em&gt; hearing it.&#xA;But recently, I realized that it&amp;rsquo;s never been more pertinent than to my current day-to-day life as a software engineer.&lt;/p&gt;&#xA;&lt;p&gt;The fundamental tradeoff we make on the Risk Systems team is trading off between&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;how much fraud we catch (and symmetrically, miss!)&lt;/li&gt;&#xA;&lt;li&gt;how many false positives we incur to catch that much fraud&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Those false positives running rampant can inhibit growth (in terms of interested customers) of the product we&amp;rsquo;re trying to protect,&#xA;but letting too much fraud through can make a product too expensive (and even liable to be shut down!)&lt;/p&gt;</description>
    </item>
    <item>
      <title>sharded feeds</title>
      <link>https://traviscj.com/blog/post/2018-10-29-sharded_feeds/</link>
      <pubDate>Mon, 29 Oct 2018 18:30:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-10-29-sharded_feeds/</guid>
      <description>&lt;p&gt;Suppose that:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;our humble &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;KV feed&lt;/a&gt; sees &lt;em&gt;a lot&lt;/em&gt; of traffic.&lt;/li&gt;&#xA;&lt;li&gt;someone needs to consume our &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;KV feed&lt;/a&gt; with multiple threads.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;data&#34;&gt;data&lt;/h3&gt;&#xA;&lt;p&gt;The first step is to introduce a notion of &amp;ldquo;shards&amp;rdquo; into our data model:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;kv&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;COLUMN&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;shard&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; INT(&lt;span style=&#34;color:#ae81ff&#34;&gt;11&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;DEFAULT&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;ADD&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INDEX&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;k_fsi_s&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;feed_sync_id&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;shard&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;publishing&#34;&gt;publishing&lt;/h3&gt;&#xA;&lt;p&gt;We don&amp;rsquo;t need to alter the publishing until the publishing &lt;em&gt;itself&lt;/em&gt; is too slow to work with a single thread, but this introduces a &lt;em&gt;lot&lt;/em&gt; of complications, so let&amp;rsquo;s just hold off for now.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Feeds as cache invalidation mechanism</title>
      <link>https://traviscj.com/blog/post/2018-10-03-feeds_as_cache_invalidation_mechanism/</link>
      <pubDate>Wed, 03 Oct 2018 02:31:43 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-10-03-feeds_as_cache_invalidation_mechanism/</guid>
      <description>&lt;p&gt;One really cool use of &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;feeds&lt;/a&gt; we&amp;rsquo;ve realized is that it gives a very efficient mechanism for application code to load the most recent versions of a table into memory.&#xA;The basic idea is:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Set it up as a usual feed published table with an appropriate index on &lt;code&gt;feed_sync_id&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Either alongside or within the cache, represent the latest loaded &lt;code&gt;feed_sync_id&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Set up a cronjob/etc that reads the latest &lt;code&gt;feed_sync_id&lt;/code&gt; and compares it to the cache&amp;rsquo;s &lt;code&gt;feed_sync_id&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If they differ, reload the cache.&lt;/li&gt;&#xA;&lt;li&gt;Ensure that all changes set &lt;code&gt;feed_sync_id&lt;/code&gt; to null!&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;This works really well because the &lt;code&gt;feed_sync_id&lt;/code&gt; in the database only gets updated on changes, so the reload cronjob mostly is a no-op.&#xA;This means we can reload very frequently!&lt;/p&gt;</description>
    </item>
    <item>
      <title>cross-dc sync with feed published KV</title>
      <link>https://traviscj.com/blog/post/2018-07-10-cross-dc-sync-with-feed-published_kv/</link>
      <pubDate>Tue, 10 Jul 2018 11:34:39 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-07-10-cross-dc-sync-with-feed-published_kv/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s been fun describing the &lt;a href=&#34;https://traviscj.com/blog/post/2018-06-29-mysql_feeds/&#34;&gt;feeds&lt;/a&gt; framework we use at Square.&#xA;Today we&amp;rsquo;ll dive into a concrete problem:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We&amp;rsquo;ll stick with the feed-published &lt;code&gt;kv&lt;/code&gt; table again.&lt;/li&gt;&#xA;&lt;li&gt;We want two instances of some application code to bidirectionally synchronize the writes that happened on their instance to the other.&lt;/li&gt;&#xA;&lt;li&gt;Eventually consistent is ok.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;First, a bit of justification, though:&#xA;I use this KV table to remember things I might have to look up without usual context, like my motorcycle&amp;rsquo;s license plate number, or that one weird python snippet I can never remember.&#xA;I also have a whole slew of them at work &amp;ndash; a bunch of random representative IDs for a bunch of things in our systems that I use from time to time.&#xA;I &lt;em&gt;also&lt;/em&gt; use a bunch of these as todo items at work, but that happens to work differently and is a topic for a future blog post :-)&lt;/p&gt;</description>
    </item>
    <item>
      <title>mysql feeds</title>
      <link>https://traviscj.com/blog/post/2018-06-29-mysql_feeds/</link>
      <pubDate>Fri, 29 Jun 2018 00:00:00 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2018-06-29-mysql_feeds/</guid>
      <description>&lt;p&gt;At work, we use a pattern called &lt;em&gt;feeds&lt;/em&gt; that gets an incredible amount of work done.&#xA;I&amp;rsquo;ve been wanting to describe it here for quite a while, and now seems as good of time as any.&lt;/p&gt;&#xA;&lt;p&gt;The basic premise is: You have a service A with some data that other &amp;ldquo;consuming&amp;rdquo; services B, C, and D want to find out about.&#xA;Maybe the data is payments, maybe it&amp;rsquo;s support cases, maybe it&amp;rsquo;s password changes&amp;hellip; whatever.&#xA;The other services might include your data warehouse, some event listeners, whatever.&lt;/p&gt;</description>
    </item>
    <item>
      <title>CBCL: The Common Business Communication Language</title>
      <link>https://traviscj.com/blog/post/2016-12-12-cbcl/</link>
      <pubDate>Mon, 12 Dec 2016 23:05:28 +0000</pubDate>
      <guid>https://traviscj.com/blog/post/2016-12-12-cbcl/</guid>
      <description>&lt;p&gt;I recently came across McCarthy&amp;rsquo;s &lt;a href=&#34;http://www-formal.stanford.edu/jmc/cbcl2.pdf&#34;&gt;CBCL&lt;/a&gt; paper on Hacker News.&#xA;He presents a Lisp notation as a format for sharing requests between different software on different computers.&#xA;He calls out&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;(PLEASE-RESERVE (EPSILON (x) &#xA;  (AND&#xA;    (IS-FLIGHT x) &#xA;    (DEPARTS MONDAY) &#xA;    (ARRIVES (BEFORE WEDNESDAY)))))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;where $\epsilon x$ is an operator maps a predicate to &lt;em&gt;a value&lt;/em&gt; matching the predicate, and considers it an improvement on the &amp;ldquo;iota&amp;rdquo; &lt;a href=&#34;https://en.wikipedia.org/wiki/Definite_description#Mathematical_logic&#34;&gt;definite description&lt;/a&gt; operator, which seems to be an operator that returns &lt;em&gt;the unique value&lt;/em&gt; matching the predicate.&#xA;It seems interesting to me that the unique match operator is not considered as useful as the arbitrary match operator &amp;ndash; unique keys actually seem critical to a lot of my work with data models.&#xA;Even more fascinating, though, is that this &lt;em&gt;looks&lt;/em&gt; like an anonymous function!&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
