<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">>
  <channel>
    <title>Daniel Compton</title>
    <link>https://danielcompton.net/</link>
    <description>Recent content in Welcome on Daniel Compton</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 02 Sep 2024 18:19:32 +1300</lastBuildDate><atom:link href="https://danielcompton.net/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>How much do Datadog&#39;s distribution metrics cost?</title>
      <link>https://danielcompton.net/snippets/how-much-do-datadog-distribution-metrics-cost</link>
      <pubDate>Mon, 02 Sep 2024 18:19:32 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/how-much-do-datadog-distribution-metrics-cost</guid>
      <description>I&amp;rsquo;ve been looking at Datadog&amp;rsquo;s distribution metrics recently and found it a little bit tricky to understand how much they cost.
https://docs.datadoghq.com/account_management/billing/custom_metrics/?tab=distribution</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been looking at Datadog&rsquo;s distribution metrics recently and found it a little bit tricky to understand how much they cost.</p>
<p><a href="https://docs.datadoghq.com/account_management/billing/custom_metrics/?tab=distribution">https://docs.datadoghq.com/account_management/billing/custom_metrics/?tab=distribution</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Where are Datadog&#39;s sites located?</title>
      <link>https://danielcompton.net/snippets/where-are-datadog-regions</link>
      <pubDate>Wed, 28 Aug 2024 18:19:32 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/where-are-datadog-regions</guid>
      <description>Datadog has a number of sites (regions) you can choose. You can reduce bandwidth egress costs by making a direct connection to your Datadog site, but only if you are connecting from the same cloud provider. However, Datadog is weirdly silent about where each of the sites run. You can&amp;rsquo;t change the site you&amp;rsquo;re using after you sign up, so it&amp;rsquo;s important to get it right!
Here is a list of the available regions as of October 2025 and where they run:</description>
      <content:encoded><![CDATA[<p>Datadog has a number of <a href="https://docs.datadoghq.com/getting_started/site/">sites</a> (regions) you can choose. You can reduce bandwidth egress costs by making a <a href="https://docs.datadoghq.com/logs/guide/reduce_data_transfer_fees/">direct connection to your Datadog site</a>, but only if you are connecting from the same cloud provider. However, Datadog is weirdly silent about where each of the sites run. You can&rsquo;t change the site you&rsquo;re using after you sign up, so it&rsquo;s important to get it right!</p>
<p><img src="/media/2024/datadog-signup.png" alt="Datadog signup region picker"></p>
<p>Here is a list of the available regions as of October 2025 and where they run:</p>
<table>
<thead>
<tr>
<th>Site</th>
<th>Base domain</th>
<th>Cloud Provider</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>US1</td>
<td><code>datadoghq.com</code></td>
<td>AWS</td>
<td><code>us-east-1</code>, North Virginia, USA</td>
</tr>
<tr>
<td>US3</td>
<td><code>us3.datadoghq.com</code></td>
<td>Azure</td>
<td><code>westcentralus</code>, Wyoming, USA</td>
</tr>
<tr>
<td>US5</td>
<td><code>us5.datadoghq.com</code></td>
<td>Google Cloud</td>
<td><code>us-central1</code>, Iowa, USA (I think)</td>
</tr>
<tr>
<td>EU</td>
<td><code>datadoghq.eu</code></td>
<td>Google Cloud</td>
<td>Germany</td>
</tr>
<tr>
<td>US1-FED</td>
<td><code>ddog-gov.com</code></td>
<td>AWS</td>
<td><code>us-gov-west-1</code>, Oregon, USA</td>
</tr>
<tr>
<td>AP1</td>
<td><code>ap1.datadoghq.com</code></td>
<td>AWS</td>
<td><code>ap-northeast-1</code> (Tokyo, Japan) or <code>ap-northeast-3</code> (Osaka, Japan)</td>
</tr>
<tr>
<td>AP2</td>
<td><code>ap2.datadoghq.com</code></td>
<td>AWS</td>
<td><code>ap-southeast-2</code> (Sydney, Australia)</td>
</tr>
</tbody>
</table>
]]></content:encoded>
    </item>
    
    <item>
      <title>What went wrong with UniSuper and Google Cloud?</title>
      <link>https://danielcompton.net/google-cloud-unisuper</link>
      <pubDate>Wed, 15 May 2024 14:00:00 +1300</pubDate>
      
      <guid>https://danielcompton.net/google-cloud-unisuper</guid>
      <description>Update 2024-05-21: Miles Ward has an update with more details in this X thread:
UniSuper&amp;rsquo;s production Google Cloud VMware Engine (GCVE) private cloud was automatically deleted one year after it&amp;rsquo;s creation due to a misconfiguration in how it was created. When it was created, there was a bug in the creation script which passed a null value. This caused the private cloud to be created with a one year subscription, rather than a perpetual one.</description>
      <content:encoded><![CDATA[<p><strong>Update 2024-05-21:</strong> Miles Ward has an update with more details in this <a href="https://x.com/milesward/status/1792909048830214607">X thread</a>:</p>
<p>UniSuper&rsquo;s production Google Cloud VMware Engine (GCVE) private cloud was automatically deleted one year after it&rsquo;s creation due to a misconfiguration in how it was created. When it was created, there was a bug in the creation script which passed a null value. This caused the private cloud to be created with a one year subscription, rather than a perpetual one. After one year passed, Google Cloud dutifully deleted the private cloud.</p>
<p>The rest of this post is still relevant for more context, but it is now clear that this was indeed a Google Cloud bug. I remain puzzled why the communication over this incident was so bad. By their silence, Google Cloud let millions of people think that they had deleted a company&rsquo;s entire Google Cloud environment. I&rsquo;m also confused why this information came out via a non-employee on Twitter rather than through official channels.</p>
<hr>
<p><strong>Update 2:</strong> Google Cloud has <a href="https://cloud.google.com/blog/products/infrastructure/details-of-google-cloud-gcve-incident/">published a blog post</a> explaining exactly what happened. The details do bear out that this was entirely a Google Cloud issue from start to finish, with no fault on the part of UniSuper.</p>
<p>Over the past two weeks, UniSuper, an Australian superannuation fund, faced every cloud user&rsquo;s nightmare: their cloud provider deleted their data. From May 2nd to 13th, UniSuper experienced a major outage and in several updates <a href="https://www.unisuper.com.au/contact-us/outage-update">blamed Google Cloud</a> for the incident.</p>
<blockquote>
<p>The disruption of UniSuper services was caused by a combination of rare issues at Google Cloud that resulted in an inadvertent misconfiguration during the provisioning of UniSuper’s Private Cloud, which triggered a previously unknown software bug that impacted UniSuper’s systems. This was an unprecedented occurrence, and measures have been taken to ensure this issue does not happen again.</p>
</blockquote>
<p>This culminated in a <a href="https://www.unisuper.com.au/about-us/media-centre/2024/a-joint-statement-from-unisuper-and-google-cloud">press release</a>, jointly signed by Google Cloud CEO Thomas Kurian.</p>
<blockquote>
<p>Google Cloud CEO, Thomas Kurian has confirmed that the disruption arose from an unprecedented sequence of events whereby an inadvertent misconfiguration during provisioning of UniSuper’s Private Cloud services ultimately resulted in the deletion of UniSuper’s Private Cloud subscription.</p>
<p>This is an isolated, ‘one-of-a-kind occurrence’ that has never before occurred with any of Google Cloud’s clients globally. This should not have happened. Google Cloud has identified the events that led to this disruption and taken measures to ensure this does not happen again.</p>
<p>UniSuper had duplication in two geographies as a protection against outages and loss. However, when the deletion of UniSuper’s Private Cloud subscription occurred, it caused deletion across both of these geographies.</p>
<p>Restoring UniSuper’s Private Cloud instance has called for an incredible amount of focus, effort, and partnership between our teams to enable an extensive recovery of all the core systems. The dedication and collaboration between UniSuper and Google Cloud has led to an extensive recovery of our Private Cloud which includes hundreds of virtual machines, databases and applications.</p>
</blockquote>
<p>The press release uses vague language, obscuring the technical details of what happened. Given the lack of precision, I assumed this was written solely by UniSuper. Gergely Orosz <a href="https://x.com/GergelyOrosz/status/1788531368701346100">checked</a> with Google Cloud, and they confirmed that this was an official joint statement.</p>
<p>Given the few details provided, I did more research to try to understand what exactly happened.</p>
<h2 id="what-was-deleted">What was deleted?</h2>
<p>Google Cloud doesn&rsquo;t have a resource called a &ldquo;Subscription&rdquo;; the closest concept would probably be a &ldquo;Billing Account.&rdquo; While Google has a Virtual Private Cloud (VPC), you wouldn&rsquo;t describe it as an instance, and deleting a VPC doesn&rsquo;t seem like it would have the drastic effects described.</p>
<p>However, if you research UniSuper&rsquo;s Google Cloud migration, you will see that they use <a href="https://cloud.google.com/vmware-engine?hl=en">Google Cloud VMWare Engine</a> (GCVE). From <a href="https://www.itnews.com.au/news/unisuper-60-percent-complete-in-cloud-shift-596583">June 2023</a>:</p>
<blockquote>
<p>The superannuation fund has shifted almost all non-production workloads out of its data centres and into Google Cloud so far.</p>
<p><strong>UniSuper used the Google VMware Engine (GCVE) managed service</strong> and engaged partner Kasna to assist with the migration.</p>
</blockquote>
<p>GCVE has a resource called a <a href="https://cloud.google.com/vmware-engine/docs/concepts-private-cloud">private cloud</a>. A private cloud contains the hosts, management server, storage, and networking for a <a href="https://docs.vmware.com/en/VMware-Cloud-Provider-Stack/index.html">VMware stack</a>.</p>
<p>Let&rsquo;s look at the <a href="https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds/delete">API method</a> for <a href="https://cloud.google.com/vmware-engine/docs/private-clouds/howto-delete-private-cloud#delete_a_private_cloud">deleting a private cloud</a>:</p>
<blockquote>
<p>A PrivateCloud resource scheduled for deletion has PrivateCloud.state set to DELETED and expireTime set to the time when deletion is final and can no longer be reversed. The delete operation is marked as done as soon as the PrivateCloud is successfully scheduled for deletion (this also applies when delayHours is set to zero), and the operation is not kept in pending state until PrivateCloud is purged. PrivateCloud can be restored using privateClouds.undelete method before the expireTime elapses. <strong>When expireTime is reached, deletion is final and all private cloud resources are irreversibly removed and billing stops.</strong></p>
</blockquote>
<p>All private cloud resources being irreversibly removed sounds a lot like the outage that UniSuper had. Some people have said that Google deleted their entire Google Cloud account. This seems less likely to me because Google has a number of safeguards and delays when <a href="https://cloud.google.com/resource-manager/docs/creating-managing-projects#shutting_down_projects">deleting projects</a>:</p>
<blockquote>
<p>Warning: You can recover most resources if you restore a project within the 30-day period. Some services have delays in restoring and you might need to wait some time for services to be restored. Some resources, such as Cloud Storage or Pub/Sub resources, are deleted much sooner. These resources might not be fully recoverable even if you restore the project within the 30-day period.</p>
</blockquote>
<p><strong>Update:</strong> User smcwhtdtmc on HN <a href="https://news.ycombinator.com/item?id=40366867">pointed out</a> the Terraform resource for <code>vmwareengine_private_cloud</code> <a href="https://github.com/hashicorp/terraform-provider-google/blob/b956f357e58360a4d09372b4fe0fc83560b6e26f/google/services/vmwareengine/resource_vmwareengine_private_cloud.go#L631">hard-codes</a> the <code>delayHours</code> parameter to 0, i.e. immediate deletion. All private cloud resources being immediately irreversibly deleted sounds a lot like the outage that UniSuper had.</p>
<h2 id="how-did-everything-get-deleted">How did everything get deleted?</h2>
<p>UniSuper&rsquo;s press release says:</p>
<blockquote>
<p>UniSuper had duplication in two geographies as a protection against outages and loss. However, when the deletion of UniSuper’s Private Cloud subscription occurred, it caused deletion across both of these geographies.</p>
</blockquote>
<p>Again, the language here is frustratingly vague and passive but implies that Google Cloud deleted multiple independent private clouds in separate regions. Google Cloud doesn&rsquo;t have a &ldquo;geography&rdquo;; it has <a href="https://cloud.google.com/about/locations">zones and regions</a>. At first read, it sounds like they are describing a multi-region setup. Google Cloud has two Australian regions, Sydney and Melbourne, which would make sense.</p>
<p>Looking closer at the docs, though, GCVE offers two kinds of private clouds: a standard private cloud hosted in a single zone or a &ldquo;<a href="https://cloud.google.com/vmware-engine/docs/private-clouds/howto-create-stretched-private-cloud">stretched private cloud</a>&rdquo;. A stretched private cloud runs in a single region across two zones, with a third zone as a witness zone for failover. A close reading of the press release doesn&rsquo;t rule out UniSuper having a single stretched private cloud running in a single region.</p>
<p>So we either have a single stretched private cloud being deleted or two separate private clouds being deleted. A single stretched private cloud seems more likely to me, but I can&rsquo;t be definitive.</p>
<h2 id="how-was-it-deleted">How was it deleted?</h2>
<p>So we come to the big question: How were the private cloud(s) deleted? The press release makes heroic use of the passive voice to obscure the actors: &ldquo;an unprecedented sequence of events whereby an inadvertent misconfiguration during provisioning of UniSuper’s Private Cloud services ultimately resulted in the deletion of UniSuper’s Private Cloud subscription.&rdquo;</p>
<p><strong>Update: 2024-05-21</strong> Miles Ward has the details on what actually happened in this <a href="https://x.com/milesward/status/1792909048830214607">X thread</a>. My guesses were close, but not quite right.</p>
<p>Based on my experiences with Google Cloud&rsquo;s professional services team, they, and presumably their partners, recommend Terraform for defining infrastructure as code. This leads to several possible interpretations of this sentence:</p>
<ol>
<li>UniSuper ran a <code>terraform apply</code> with Terraform code that was &ldquo;misconfigured&rdquo;. This triggered a bug in Google Cloud, and Google Cloud accidentally deleted the private cloud.</li>
</ol>
<p>This is what UniSuper has implied or stated throughout the outage.</p>
<ol start="2">
<li>UniSuper ran a <code>terraform apply</code> with a bad configuration or perhaps a <code>terraform destroy</code> with the prod <a href="https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files">tfvar file</a>. The Terraform plan showed &ldquo;delete private cloud,&rdquo; and the operator approved it.</li>
</ol>
<p>Automation errors like this happen every day, although they aren&rsquo;t usually this catastrophic. This seems more plausible to me than a rare one-in-a-million bug that only affected UniSuper.</p>
<ol start="3">
<li>UniSuper ran an automation script provided by Google Cloud&rsquo;s professional services team with a bug. A misconfiguration caused the script to go off the rails. The operator was asked whether to delete the production private cloud, and they said yes.</li>
</ol>
<p>I find this less plausible, but it is one way to interpret Google Cloud as being at fault for what sounds like a customer error in automation.</p>
<h2 id="maybe-it-was-a-google-cloud-bug">Maybe it was a Google Cloud bug?</h2>
<p>There are a few holes in my theory that this was primarily UniSuper&rsquo;s fault:</p>
<ol>
<li>On <a href="https://www.unisuper.com.au/contact-us/outage-update">Tuesday, 7 May</a>, UniSuper attributed a statement to Google Cloud in which Google Cloud admitted fault for the outage:</li>
</ol>
<blockquote>
<p>The disruption of UniSuper services was caused by a combination of rare issues at Google Cloud that resulted in an inadvertent misconfiguration during the provisioning of UniSuper’s Private Cloud, which triggered a previously unknown software bug that impacted UniSuper’s systems. This was an unprecedented occurrence, and measures have been taken to ensure this issue does not happen again.</p>
</blockquote>
<ol start="2">
<li>
<p>Thomas Kurian (apparently) signed off on a joint statement with UniSuper. This statement is less accusatory than UniSuper&rsquo;s other statements but doesn&rsquo;t clarify which party was at fault.</p>
</li>
<li>
<p>Google Cloud hasn&rsquo;t released any pushback to the story, either directly or through proxies in the media.</p>
</li>
</ol>
<p>Why would Google Cloud not respond to this story if it was UniSuper&rsquo;s fault? It&rsquo;s hard to say, but putting out a competing statement blaming or contradicting your customer is a bad look with that customer and <a href="https://x.com/patio11/status/1789061633865597309">with all future customers</a>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Given how little detail was communicated, it is difficult to make a conclusive statement about what happened, though I personally suspect UniSuper operator error was a large factor. Hopefully, <a href="https://www.apra.gov.au">APRA</a>, Australia&rsquo;s superannuation regulator, will investigate further and release a public report with more details.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Using Apple Business Apple IDs with code signing</title>
      <link>https://danielcompton.net/snippets/developer-apple-id-business</link>
      <pubDate>Fri, 01 Mar 2024 07:19:32 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/developer-apple-id-business</guid>
      <description>Recently at work
create apple id &amp;ldquo;cannot find this person&amp;rdquo;
$ xcrun notarytool store-credentials &amp;#34;Whimsical Development&amp;#34; --apple-id &amp;#34;name@company.com&amp;#34; --team-id &amp;#34;2N6497CB83&amp;#34; --verbose [18:23:07.326Z] Debug [MAIN] Running notarytool version: 1.0.0 (32.0.1), date: 2024-02-29T18:23:07Z, command: /Applications/Xcode-15.2.0.app/Contents/Developer/usr/bin/notarytool store-credentials Whimsical Development --apple-id name@company.com --team-id 2N6497CB83 --verbose This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name. App-specific password for name@company.com: Validating your credentials... [18:23:21.756Z] Info [API] Initialized Notary API with base URL: https://appstoreconnect.</description>
      <content:encoded><![CDATA[<p>Recently at work</p>
<p>create apple id &ldquo;cannot find this person&rdquo;</p>
<pre tabindex="0"><code>$ xcrun notarytool store-credentials &#34;Whimsical Development&#34; --apple-id &#34;name@company.com&#34; --team-id &#34;2N6497CB83&#34; --verbose
[18:23:07.326Z] Debug [MAIN] Running notarytool version: 1.0.0 (32.0.1), date: 2024-02-29T18:23:07Z, command: /Applications/Xcode-15.2.0.app/Contents/Developer/usr/bin/notarytool store-credentials Whimsical Development --apple-id name@company.com --team-id 2N6497CB83 --verbose

This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.

App-specific password for name@company.com:
Validating your credentials...
[18:23:21.756Z] Info [API] Initialized Notary API with base URL: https://appstoreconnect.apple.com/notary/v2/
[18:23:21.756Z] Info [API] Preparing GET request to URL: https://appstoreconnect.apple.com/notary/v2/test?, Parameters: [:], Custom Headers: private&lt;Dictionary&lt;String, String&gt;&gt;
[18:23:21.757Z] Debug [AUTHENTICATION] Delaying current request to refresh app-specific password token.
[18:23:21.757Z] Info [API] Preparing GET request to URL: https://appstoreconnect.apple.com/notary/v2/asp?, Parameters: [:], Custom Headers: private&lt;Dictionary&lt;String, String&gt;&gt;
[18:23:21.757Z] Debug [AUTHENTICATION] Authenticating request to &#39;/notary/v2/asp&#39; with Basic Auth. Username: name@company.com, Password: private&lt;String&gt;, Team ID: 2N6497CB83
[18:23:21.758Z] Debug [TASKMANAGER] Starting Task Manager loop to wait for asynchronous HTTP calls.
[18:23:22.825Z] Debug [API] Received response status code: 401, message: unauthorized, URL: https://appstoreconnect.apple.com/notary/v2/asp?, Correlation Key: U7UUHDJOSFM5N7DWNJZMTALNYE
[18:23:22.826Z] Error [TASKMANAGER] Completed Task with ID 2 has encountered an error.
[18:23:22.826Z] Debug [TASKMANAGER] Ending Task Manager loop.
Error: HTTP status code: 401. Unable to authenticate. The application is not allowed for primary authentication. Ensure that all authentication arguments are correct.
</code></pre>]]></content:encoded>
    </item>
    
    <item>
      <title>Why does Google Cloud Storage need Turbo Replication?</title>
      <link>https://danielcompton.net/snippets/google-cloud-storage-turbo-replication</link>
      <pubDate>Wed, 08 Mar 2023 16:10:00 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/google-cloud-storage-turbo-replication</guid>
      <description>I was looking at the docs for Google Cloud Storage and came across Turbo Replication.
 Turbo replication is a Cloud Storage feature designed to asynchronously replicate newly written Cloud Storage objects associated with any insert, rewrite, copy, or compose operation—regardless of object size—to a separate region within a target of 15 minutes. Available for dual-region buckets, turbo replication offers a shorter, more predictable recovery point objective (RPO), helping to reduce data loss exposure.</description>
      <content:encoded><![CDATA[<p>I was looking at the docs for Google Cloud Storage and came across <a href="https://cloud.google.com/storage/docs/turbo-replication">Turbo Replication</a>.</p>
<blockquote>
<p>Turbo replication is a Cloud Storage feature designed to asynchronously replicate newly written Cloud Storage objects associated with any insert, rewrite, copy, or compose operation—regardless of object size—to a separate region within a target of 15 minutes. Available for dual-region buckets, turbo replication offers a shorter, more predictable recovery point objective (RPO), helping to reduce data loss exposure.</p>
</blockquote>
<p>I was a bit puzzled by this at first. Google Cloud&rsquo;s dual-regional buckets are already replicated across multiple regions, and can serve data from either region. Aren&rsquo;t all objects replicated at write time?</p>
<p>After reading the docs a few times, I realised what this paragraph was saying:</p>
<blockquote>
<p>Cloud Storage always understands the current state of the bucket and transparently serves objects from either region as required. As a result, dual-region buckets are designed to have a recovery time objective (RTO) of zero, and temporary regional failures are normally invisible to users; in the case of a regional outage, dual-region buckets automatically continue serving all data that has been replicated between the two regions.</p>
</blockquote>
<ol>
<li>Writes to a dual-region bucket are asynchronously replicated between the region pairs. This replication can be quite slow. Under standard replication, the target is for 99.9% of writes to be replicated within an hour.</li>
<li>If write replication is so slow, how can a multi-region bucket be useful when you need to read your writes immediately? Cloud Storage knows where each object has been replicated, and can route requests to the correct region if the object is only stored in one region.</li>
<li>If a Cloud Storage region goes down, a dual-region bucket can continue to serve objects from the other region. However, any unreplicated objects will be unavailable until the region comes back online.</li>
</ol>
<p>Therefore, if you need stronger guarantees around the freshnesss of data during a regional outage, you can turn on Turbo Replication for a bucket. This has an SLA of replicating 100% of writes to the other region within 15 minutes. This gives an upper bound (as long as the SLA isn&rsquo;t breached) of how much data might be unavailable during a regional outage. Note that once the outage is resolved, the data will be replicated to the other region.</p>
<p>Turbo Replication costs more than standard dual-region replication.</p>
<ul>
<li>For US and EU dual-region buckets, the cost goes from $0.02/GB to $0.04/GB</li>
<li>For Asia dual-region buckets, the cost goes from $0.08/GB to $0.11/GB</li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Fixing Chrome DevTools warning &#34;Using unsafe HTTP verb&#34;</title>
      <link>https://danielcompton.net/snippets/chrome-devtools-unsafe-http-verb</link>
      <pubDate>Fri, 09 Dec 2022 11:25:00 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/chrome-devtools-unsafe-http-verb</guid>
      <description>I was looking through our app logs recently and saw this warning message printed from our headless Chrome service:
[1208/221244.718990:ERROR:devtools_http_handler.cc(636)] Using unsafe HTTP verb GET to invoke /json/new. This action will stop supporting GET and POST verbs in future versions. After some searching, I found that the solution is to change the request to use PUT instead of GET. It appears as if the change is to prevent XSRF attacks against the DevTools HTTP server.</description>
      <content:encoded><![CDATA[<p>I was looking through our app logs recently and saw this warning message printed from our headless Chrome service:</p>
<pre tabindex="0"><code>[1208/221244.718990:ERROR:devtools_http_handler.cc(636)] Using unsafe HTTP verb GET to invoke /json/new. This action will stop supporting GET and POST verbs in future versions.
</code></pre><p>After some searching, I found that the solution is to change the request to use PUT instead of GET. It appears as if the change is to prevent XSRF attacks against the DevTools HTTP server.</p>
<p>I found this by using the <a href="https://source.chromium.org">Chromium code search tool</a> and looking at the <a href="https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_http_handler.cc;l=643-645;drc=304e25245af5f41fb5d9c0d61f7eb49dcb1030ec">source</a> of the warning. The blame led me to a <a href="https://chromium-review.googlesource.com/c/chromium/src/+/3595822/9/content/browser/devtools/devtools_http_handler.cc#638">discussion</a> with <a href="https://www.paulirish.com">Paul Irish</a> on what should be used instead. The consensus was to use PUT. An example of this change can be seen in the <a href="https://github.com/GoogleChrome/lighthouse/pull/14063">Lighthouse</a> project.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>What&#39;s the difference between http2and3 and http3 in Cloudfront?</title>
      <link>https://danielcompton.net/snippets/http2and3-cloudfront</link>
      <pubDate>Tue, 20 Sep 2022 20:30:00 +1200</pubDate>
      
      <guid>https://danielcompton.net/snippets/http2and3-cloudfront</guid>
      <description>CloudFront recently announced HTTP/3 support. I wanted to add it to the CloudFront distributions at work. I looked at the AWS Terraform Provider docs for setting the HTTP version. It said:
 The maximum HTTP version to support on the distribution. Allowed values are http1.1, http2, http2and3 and http3. The default is http2.
 I was confused about the difference between http2and3 and http3. I looked at the CloudFront API docs, which said pretty much the same thing as the Terraform docs.</description>
      <content:encoded><![CDATA[<p>CloudFront <a href="https://aws.amazon.com/blogs/aws/new-http-3-support-for-amazon-cloudfront/">recently announced</a> HTTP/3 support. I wanted to add it to the CloudFront distributions at <a href="https://whimsical.com/">work</a>. I looked at the <a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution#http_version">AWS Terraform Provider docs</a> for setting the HTTP version. It said:</p>
<blockquote>
<p>The maximum HTTP version to support on the distribution. Allowed values are <code>http1.1</code>, <code>http2</code>, <code>http2and3</code> and <code>http3</code>. The default is <code>http2</code>.</p>
</blockquote>
<p>I was confused about the difference between <code>http2and3</code> and <code>http3</code>. I looked at the <a href="https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html#cloudfront-UpdateDistribution-request-HttpVersion">CloudFront API docs</a>, which said pretty much the same thing as the Terraform docs.</p>
<p>I decided to look at the console to see what the options were:</p>
<img src="/media/2022/09/http2and3.png" width="550">
<p>After seeing this, it became a lot clearer what was going on. The documentation says &ldquo;The maximum HTTP version&rdquo;, but this is no longer accurate with the release of HTTP/3 support.</p>
<ul>
<li><code>http3</code> means means HTTP/3 and HTTP/1.1</li>
<li><code>http2</code> means HTTP/2 and HTTP/1.1</li>
<li><code>http2and3</code> means HTTP/3, HTTP/2, and HTTP/1.1.</li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Leiningen dependency commands in Clojure CLI</title>
      <link>https://danielcompton.net/snippets/leiningen-dependency-commands-clojure-cli</link>
      <pubDate>Mon, 25 Jul 2022 13:30:36 +1200</pubDate>
      
      <guid>https://danielcompton.net/snippets/leiningen-dependency-commands-clojure-cli</guid>
      <description>At work, we have recently converted our projects to the Clojure CLI and deps.edn. There were a few commands from Leiningen that I needed to find an equivalent for when working with dependencies.
Download all dependencies Often in a CI environment, you want to download all of the dependencies for a project before building the project. In Leiningen, you can use lein deps to do this.
You can use clojure -P to Prepare the project with the Clojure CLI.</description>
      <content:encoded><![CDATA[<p>At <a href="https://whimsical.com/">work</a>, we have recently converted our projects to the Clojure CLI and <code>deps.edn</code>. There were a few commands from Leiningen that I needed to find an equivalent for when working with dependencies.</p>
<h2 id="download-all-dependencies">Download all dependencies</h2>
<p>Often in a CI environment, you want to download all of the dependencies for a project before building the project. In Leiningen, you can use <code>lein deps</code> to do this.</p>
<p>You can use <code>clojure -P</code> to <strong>P</strong>repare the project with the Clojure CLI. This downloads libs and caches the classpath.</p>
<p>Note that you should avoid running <code>clojure -P</code> in parallel on new environments (like CI). When running <code>clojure -P</code> for the first time, it will set up files in <code>~/.clojure</code> and clone gitlibs. If you run multiple processes doing this simultaneously, you can get race conditions that throw errors.</p>
<h2 id="view-the-dependency-tree">View the dependency tree</h2>
<p>When debugging dependency issues, it&rsquo;s often helpful to see which library pulled in a transitive dependency.</p>
<p>Leiningen can print the dependency showing the resolved transitive dependencies.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ lein deps :tree
</span></span><span class="line"><span class="cl"> <span class="o">[</span>clansi <span class="s2">&#34;1.0.0&#34;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl"> <span class="o">[</span>clj-kondo <span class="s2">&#34;2022.03.09&#34;</span> :scope <span class="s2">&#34;test&#34;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl"> <span class="o">[</span>babashka/fs <span class="s2">&#34;0.1.2&#34;</span> :scope <span class="s2">&#34;test&#34;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl"> <span class="o">[</span>cheshire <span class="s2">&#34;5.10.2&#34;</span> :scope <span class="s2">&#34;test&#34;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl"> <span class="o">[</span>com.fasterxml.jackson.dataformat/jackson-dataformat-cbor <span class="s2">&#34;2.12.4&#34;</span> :scope <span class="s2">&#34;test&#34;</span> :exclusions <span class="o">[[</span>com.fasterxml.jackson.core/jackson-databind<span class="o">]]]</span>
</span></span><span class="line"><span class="cl"> <span class="o">[</span>com.fasterxml.jackson.dataformat/jackson-dataformat-smile <span class="s2">&#34;2.12.4&#34;</span> :scope <span class="s2">&#34;test&#34;</span> :exclusions <span class="o">[[</span>com.fasterxml.jackson.core/jackson-databind<span class="o">]]]</span>
</span></span><span class="line"><span class="cl"> <span class="o">[</span>tigris <span class="s2">&#34;0.1.2&#34;</span> :scope <span class="s2">&#34;test&#34;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl"> <span class="o">[</span>com.cognitect/transit-clj <span class="s2">&#34;1.0.324&#34;</span> :scope <span class="s2">&#34;test&#34;</span><span class="o">]</span>
</span></span><span class="line"><span class="cl"> <span class="c1"># ...</span>
</span></span></code></pre></div><p><code>clojure</code> has a similar command, though with a slightly different output. In contrast to Leiningen, <code>clojure</code> prints the entire dependency tree. Dependencies <code>clojure</code> didn&rsquo;t select get an <code>X</code> in front of them, and a short reason like <code>:older-version</code> or <code>:excluded</code>. These views can be helpful when debugging why you didn&rsquo;t get the version you expected.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ clojure -Stree
</span></span><span class="line"><span class="cl">org.clojure/clojure 1.11.0
</span></span><span class="line"><span class="cl"> . org.clojure/spec.alpha 0.3.218
</span></span><span class="line"><span class="cl"> . org.clojure/core.specs.alpha 0.2.62
</span></span><span class="line"><span class="cl">org.clojure/java.classpath 1.0.0
</span></span><span class="line"><span class="cl">clansi/clansi 1.0.0
</span></span><span class="line"><span class="cl">org.clojure/data.json 2.4.0
</span></span><span class="line"><span class="cl">org.slf4j/slf4j-simple 2.0.0-alpha1
</span></span><span class="line"><span class="cl"> . org.slf4j/slf4j-api 2.0.0-alpha1
</span></span><span class="line"><span class="cl">org.owasp/dependency-check-core 7.0.2
</span></span><span class="line"><span class="cl"> . us.springett/cpe-parser 2.0.2
</span></span><span class="line"><span class="cl"> X org.slf4j/slf4j-api 1.7.30 :older-version
</span></span><span class="line"><span class="cl"> . com.vdurmont/semver4j 3.1.0
</span></span><span class="line"><span class="cl"> X org.slf4j/slf4j-api 1.7.36 :older-version
</span></span></code></pre></div><h2 id="view-the-classpath">View the Classpath</h2>
<p>While dependency trees can help track down dependency problems, sometimes you need to see the actual classpath.</p>
<p>Tip: I like to use <code> | tr ':' '\n' | sort</code> to get a sorted list of the classpath entries.</p>
<p>You can do this in Leiningen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">lein classpath
</span></span><span class="line"><span class="cl"><span class="c1"># or</span>
</span></span><span class="line"><span class="cl">lein classpath <span class="p">|</span> tr <span class="s1">&#39;:&#39;</span> <span class="s1">&#39;\n&#39;</span> <span class="p">|</span> sort
</span></span></code></pre></div><p>With <code>clojure</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">clojure -Spath
</span></span></code></pre></div><p>Both Leiningen and <code>clojure</code> have more commands for dependencies; you can read more about them at <a href="https://clojure.org/reference/dep_expansion">Dep Expansion</a>, <a href="https://clojure.org/reference/deps_and_cli">Deps and CLI</a>, and <a href="https://github.com/technomancy/leiningen/blob/ee6b88beb8a82ae11605bc8f3e20c22f1a5ca886/src/leiningen/deps.clj#L109-L151">lein deps</a>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Using classifiers with deps.edn</title>
      <link>https://danielcompton.net/snippets/how-to-use-classifier-in-tools-deps</link>
      <pubDate>Tue, 19 Jul 2022 12:10:36 +1200</pubDate>
      
      <guid>https://danielcompton.net/snippets/how-to-use-classifier-in-tools-deps</guid>
      <description>One of Maven&amp;rsquo;s dependency management features is the classifier. Classifiers let you create multiple different artifacts from the same POM. You might use this to publish variations with native libraries for each OS, or to support different Java versions. This is also how sources and javadoc artifacts are created.
In Maven you can specify a dependency on a version with &amp;lt;classifier&amp;gt; like this:
&amp;lt;dependency&amp;gt; &amp;lt;groupId&amp;gt;io.netty&amp;lt;/groupId&amp;gt; &amp;lt;artifactId&amp;gt;netty-transport-native-epoll&amp;lt;/artifactId&amp;gt; &amp;lt;version&amp;gt;4.1.74&amp;lt;/version&amp;gt; &amp;lt;classifier&amp;gt;linux-x86_64&amp;lt;/classifier&amp;gt; &amp;lt;/dependency&amp;gt; To specify this dependency with Clojure&amp;rsquo;s deps.</description>
      <content:encoded><![CDATA[<p>One of Maven&rsquo;s dependency management features is the <a href="https://maven.apache.org/pom.html">classifier</a>. Classifiers let you create multiple different artifacts from the same POM. You might use this to publish variations with native libraries for each OS, or to support different Java versions. This is also how <code>sources</code> and <code>javadoc</code> artifacts are created.</p>
<p>In Maven you can specify a dependency on a version with <code>&lt;classifier&gt;</code> like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;dependency&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;groupId&gt;</span>io.netty<span class="nt">&lt;/groupId&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;artifactId&gt;</span>netty-transport-native-epoll<span class="nt">&lt;/artifactId&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;version&gt;</span>4.1.74<span class="nt">&lt;/version&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;classifier&gt;</span>linux-x86_64<span class="nt">&lt;/classifier&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/dependency&gt;</span>
</span></span></code></pre></div><p>To specify this dependency with Clojure&rsquo;s deps.edn, you need to use the <a href="https://clojure.org/reference/deps_and_cli#_dependencies">syntax</a> <code>&lt;group&gt;/&lt;artifact&gt;$&lt;classifier&gt;</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clj" data-lang="clj"><span class="line"><span class="cl"><span class="p">{</span><span class="ss">:deps</span> 
</span></span><span class="line"><span class="cl">  <span class="p">{</span><span class="nv">io.netty/netty-transport-native-epoll$linux-x86_64</span> 
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="ss">:mvn/version</span> <span class="s">&#34;4.1.74.Final&#34;</span><span class="p">}}}</span>
</span></span></code></pre></div>]]></content:encoded>
    </item>
    
    <item>
      <title>Excluding credits from your AWS Bill</title>
      <link>https://danielcompton.net/snippets/exclude-credits-from-aws-bill</link>
      <pubDate>Tue, 29 Mar 2022 21:32:36 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/exclude-credits-from-aws-bill</guid>
      <description>If you or your company ever receive AWS credits, your bill the next month will probably show a decrease in spending. This is great because you spent less money. However, at first glance, it can make comparing this month&amp;rsquo;s bill to the previous month difficult.
The trick is to use AWS Cost Explorer, and exclude the Credit and Tax Charge Types:
If you don&amp;rsquo;t see &amp;ldquo;Charge Type&amp;rdquo; in the Cost Explorer sidebar, you might need to expand Advanced Options.</description>
      <content:encoded><![CDATA[<p>If you or your company ever receive AWS credits, your bill the next month will probably show a decrease in spending. This is great because you spent less money. However, at first glance, it can make comparing this month&rsquo;s bill to the previous month difficult.</p>
<p>The trick is to use AWS Cost Explorer, and exclude the Credit <em>and</em> Tax Charge Types:</p>
<img src="/media/2022/03/aws-charge-type.png" alt="AWS Charge Type" width="318" />
<p>If you don&rsquo;t see &ldquo;Charge Type&rdquo; in the Cost Explorer sidebar, you might need to expand Advanced Options.</p>
<p>You want to exclude taxes because these aren&rsquo;t charged when you use credits. When you were paying for AWS services, you likely paid tax on that usage (depending on your location). Once you start paying for your AWS bill with credits, tax is not charged on the credit spend. Removing the tax Charge Type gives you a like-for-like comparison with previous months.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Penny Wise and Cloud Foolish</title>
      <link>https://danielcompton.net/penny-wise-cloud-foolish</link>
      <pubDate>Mon, 21 Mar 2022 20:37:50 +1300</pubDate>
      
      <guid>https://danielcompton.net/penny-wise-cloud-foolish</guid>
      <description>The two iron rules of cloud pricing introduced by AWS are:
 Prices never go up1 2. We will absolutely soak you on data transfer charges.  Last week Google Cloud published a post explaining how they were ignoring the first rule in favour of adopting the second.
The post was called &amp;ldquo;Unlock more choice with updates to Google Cloud’s infrastructure capabilities and pricing&amp;rdquo;, though the &amp;lt;title&amp;gt; was more straightforward: &amp;ldquo;Updates to Google Cloud’s Infrastructure pricing&amp;rdquo;.</description>
      <content:encoded><![CDATA[<p>The two iron rules of cloud pricing introduced by AWS are:</p>
<ol>
<li>Prices never go up<sup><a href="https://twitter.com/0xdabbad00/status/1503420432413724675">1</a></sup> <sup><a href="https://twitter.com/__steele/status/1506108007037374468">2</a></sup>.</li>
<li>We will absolutely soak you on data transfer charges.</li>
</ol>
<p>Last week Google Cloud published a <a href="https://cloud.google.com/blog/products/infrastructure/updates-to-google-clouds-infrastructure-pricing">post</a> explaining how they were ignoring the first rule in favour of adopting the second.</p>
<p>The post was called &ldquo;Unlock more choice with updates to Google Cloud’s infrastructure capabilities and pricing&rdquo;, though the <code>&lt;title&gt;</code> was more straightforward: &ldquo;Updates to Google Cloud’s Infrastructure pricing&rdquo;. The main announcements in the post were:</p>
<ul>
<li>Prices were being raised on Cloud Storage (some decreases on Storage too), Persistent Disk Snapshots, Cloud Load Balancing, Network Intelligence Center, and Cloud Ops Monitoring (Weirdly, the Monitoring price increase was only mentioned in customer emails, not in the blog post).</li>
<li>A new, cheaper archive snapshot option for persistent disks is coming later this year.</li>
<li>Storage Transfer Service will be free for the rest of the year to let customers move files into different buckets.</li>
</ul>
<p>The common theme with the price changes is the introduction of data transfer fees, an increase in fees for active storage tiers, and a decrease in archive storage cost.</p>
<blockquote>
<p>So, today, we are announcing we will adjust our infrastructure product and pricing structure &hellip; [These changes] are also designed to better align with how other leading cloud providers charge for similar products, so customers can more easily compare services between leading cloud providers.</p>
</blockquote>
<p>The main alignment here is Google adding data transfer charges to match AWS and breaking architectural promises they&rsquo;ve made to their customers in the process. This is an incredibly short-sighted move and will damage customer trust in Google Cloud for many years.</p>
<h2 id="cloud-cost-and-cloud-architecture">Cloud Cost and Cloud Architecture</h2>
<p>As Corey Quinn so eloquently put it, <a href="https://www.lastweekinaws.com/blog/the-key-to-unlock-the-aws-billing-puzzle-is-architecture/">&ldquo;all cloud cost is fundamentally about architecture&rdquo;</a>. When designing for the cloud, pricing is one of the most important signals to take into account. Pricing and quotas indicate how the Cloud provider has designed the product, how they want you to think about the product, and how you should use it.</p>
<p>The pricing changes Google is making strike at the heart of their customer&rsquo;s applications and will force many customers to rearchitect their applications, or pay a much larger amount to keep their existing architecture.</p>
<p>One of GCP&rsquo;s most differentiated features has been their <a href="https://cloud.google.com/docs/geography-and-regions">multi-region</a> and <a href="https://cloud.google.com/about/locations#global-products">global services</a> like <a href="https://cloud.google.com/load-balancing">Cloud Load Balancing</a>, <a href="https://cloud.google.com/storage/docs/locations">Cloud Storage</a>, <a href="https://cloud.google.com/bigquery/docs/locations">BigQuery</a>, <a href="https://cloud.google.com/blog/topics/developers-practitioners/demystifying-cloud-spanner-multi-region-configurations">Cloud Spanner</a>, and <a href="https://cloud.google.com/kms/docs/locations#global">Cloud KMS</a>. These let you operate on the same resources in multiple regions, giving you more resilience to an outage in a single region. As a bonus, Google&rsquo;s multi-region services often come with strong consistency across regions so customers don&rsquo;t have to deal with consistency at the application layer.</p>
<p>In contrast, most AWS services are region oriented, and when AWS provides multi-region services like <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html#V2globaltables_HowItWorks.conflict-resolution">DynamoDB Global Tables</a> and <a href="https://aws.amazon.com/premiumsupport/knowledge-center/s3-crr-replication-time/">S3 Cross-Region Replication</a>, you need to handle eventual consistency yourself.</p>
<p>Google&rsquo;s <a href="https://cloud.google.com/docs/geography-and-regions#application_deployment_considerations">message</a> was that multi-region services would give you higher availability. <em>You too can run like Google</em>. From the <a href="https://cloud.google.com/blog/products/storage-data-transfer/store-it-analyze-it-back-it-up-cloud-storage-updates-bring-new-replication-options">announcement</a> of dual-region buckets:</p>
<blockquote>
<p>With this new option, you write to a single dual-regional bucket without having to manually copy data between primary and secondary locations. No replication tool is needed to do this and <strong>there are no network charges associated with replicating the data</strong>, which means less overhead for you storage administrators out there. <strong>In the event of a region failure, we transparently handle the failover</strong> and ensure continuity for your users and applications accessing data in Cloud Storage.</p>
</blockquote>
<p>People can argue about whether Google&rsquo;s global/multi-regional control-plane provides more availability than AWS&rsquo;s region-first approach, but it was a distinctive set of features that only Google had.</p>
<h3 id="storage-changes">Storage changes</h3>
<p>The deepest architectural changes Google is making are to <a href="https://cloud.google.com/storage/pricing-announce">storage</a>:</p>
<ul>
<li>Increasing free internet egress from 1GB to 100GB per month. This matches AWS&rsquo; <a href="https://aws.amazon.com/blogs/aws/aws-free-tier-data-transfer-expansion-100-gb-from-regions-and-1-tb-from-amazon-">recent increase</a>, but is still a welcome change.</li>
<li>A mix of increases and decreases in multi-region pricing depending on the storage class and region (+50%, +25%, -40%, -25%). Standard storage pricing is unchanged.</li>
<li>A mix of increases and decreases in dual-region pricing, depending on the storage class and region. <code>nam4</code> (US) and <code>eur4</code> (Europe) are +22% on standard, +10% on nearline, -2% on coldline, and -44% on archive. <code>asia1</code> (Japan) is +10% for all storage classes except for -13% on archive storage.</li>
<li>Storage operation pricing changes have a lot of fine details, but at a high level the cost for Insert/Update/Delete operations in multi-region and dual-region buckets is doubling (100%).</li>
<li>Change in <a href="https://cloud.google.com/storage/pricing-announce#network">egress pricing</a>. If I&rsquo;m reading it correctly and the <a href="https://cloud.google.com/storage/pricing#network-pricing">existing exclusions</a> stay in place, it looks like a pretty large decrease in bucket egress for most uses. Previously 10TB of bucket egress (direct to the internet) would be charged at $0.11/GB to most of the world. Now that will be $0.02/GB from US buckets to the US, $0.05/GB to Europe, and $0.08/GB to Asia. This is a pretty large decrease, and I&rsquo;m surprised Google didn&rsquo;t make more of it in the announcement.</li>
<li>Changes to data replication pricing from <strong>$0.00 GB</strong> to <strong>$0.02/GB</strong> in <code>us</code>, <code>nam4</code>, <code>eu</code>, and <code>eur4</code>, and to <strong>$0.08/GB</strong> in <code>asia</code> and <code>asia1</code>. (These are the dual-region and multi-region bucket locations).</li>
<li><strong>Reading data from a multi-region bucket in the same continent will no longer be free</strong>, it will now be charged at the same rate as data replication. This will make many data-heavy workloads unviable with multi-region buckets.</li>
</ul>
<p>The last two changes in particular make dual-region and multi-region buckets a much less attractive offer and invalidate a lot of architectural assumptions developers will have made. Businesses that have built a high-availability architecture around multi-region buckets are now faced with the unappealing options of:</p>
<ol>
<li>Pay a lot more for replication + reading from their buckets.</li>
<li>Rearchitect their application and migrate to a single region, or perhaps a dual-region if they can make the data-replication pricing work.</li>
</ol>
<h3 id="load-balancing">Load balancing</h3>
<p>Google is also <a href="https://cloud.google.com/vpc/network-pricing#lb">increasing prices</a> on Cloud Load Balancing, adding a $0.008-$0.012/GB charge for outbound data processing.</p>
<blockquote>
<p>Starting October 1, 2022, we’ll apply an outbound data processing charge of $0.008 - $0.012 per GB (based on region) to all Cloud Load Balancing products in order to maintain consistency and alignment with the variable costs of the services across our Cloud Load Balancing portfolio.</p>
</blockquote>
<p>Depending on your <a href="https://cloud.google.com/vpc/network-pricing#internet_egress">egress rates</a> and network tier, this will amount to a 5-10% increase on internet egress, and an added cost for most kinds of internal load balancing.</p>
<h3 id="persistent-disks">Persistent disks</h3>
<p>Persistent disk snapshot pricing is <a href="https://cloud.google.com/compute/pricing-announce">also changing</a>.
I suspect this won&rsquo;t be as big a deal for most customers as the previous changes.</p>
<ul>
<li>Regional snapshots are increasing from $0.026 to $0.050 (92% increase).</li>
<li>Multi-region snapshots are increasing from $0.026 to $0.065 (150% increase).</li>
</ul>
<p>The price changes mention a &ldquo;<code>us-central1</code> baseline&rdquo; and &ldquo;United States multi-region baseline&rdquo;. This makes me think that prices in all other regions will be going up by an equivalent percentage.</p>
<p>Google also plans to introduce an archive snapshot tier later this year which will be priced at $0.019/GB/month, but with a minimum billing period of 90 days.</p>
<p>As with Cloud Storage, <strong>previously free data transfer for creation and restoration of multi-region snapshots will now be charged at inter-region rates</strong>. Restoring a 100GB multi-region snapshot will now cost $1 in the US and Europe, and more in other regions. Depending on your architecture, these charges could add up!</p>
<h2 id="why-now">Why now?</h2>
<p>On March 7th, 2022 <em>The Information</em> published <a href="https://www.theinformation.com/articles/why-aws-makes-money-and-google-cloud-doesnt">Why AWS Makes Money and Google Cloud Doesn’t</a></p>
<blockquote>
<p>[..] In a positive sign, Google Cloud CEO Thomas Kurian last month told colleagues during an internal all-hands meeting that he expects the cloud unit to be profitable later this year, according to a person who viewed the event.</p>
</blockquote>
<blockquote>
<p>Another issue is that Google Cloud has fewer high-margin services—such as cloud database and analytics software—to sell to customers than AWS does. [&hellip;] Former employees say AWS relies on these offerings for a large portion of its operating profit.</p>
</blockquote>
<p><em>The Information</em> doesn&rsquo;t mention it here, but the highest margin product AWS sells is bandwidth. Charging for data transfer is as close as you can get to pure profit in the cloud. As Cloudflare has previously <a href="https://blog.cloudflare.com/aws-egregious-egress/">demonstrated</a>, AWS likely marks up egress bandwidth by up to 8,000%, and it wouldn&rsquo;t surprise me if inter-AZ and inter-region charges were also in that vicinity.</p>
<p>If Google Cloud wants to get to profitability by the end of the year, then introducing data transfer pricing makes a lot of sense. The extra revenue from data transfer will be nearly 100% profit and go straight to Google Cloud&rsquo;s bottom line. It will be difficult for existing customers to rearchitect their applications, and most customers will probably just pay the extra charges.</p>
<p>However, if Google Cloud is trying to build the <a href="https://www.theinformation.com/articles/google-brass-set-2023-as-deadline-to-beat-amazon-microsoft-in-cloud?utm_source=hackernews&amp;utm_medium=unlock&amp;rc=ldxq7z">number two</a> cloud business behind AWS, this move is an unforced error that will damage their credibility for years.</p>
<h2 id="killed-by-google">Killed By Google</h2>
<p>Google has developed a <a href="https://killedbygoogle.com">reputation</a> for killing consumer products, and even Google Cloud has made several price increases which have changed architecture invariants, along with <a href="https://steve-yegge.medium.com/dear-google-cloud-your-deprecation-policy-is-killing-you-ee7525dc05dc">numerous deprecations</a>:</p>
<ul>
<li>2011 - <a href="http://highscalability.com/blog/2011/9/7/what-google-app-engine-price-changes-say-about-the-future-of.html">Increasing App Engine pricing</a> by 2x-10x</li>
<li>2018 - <a href="https://cloud.google.com/blog/products/maps-platform/introducing-google-maps-platform">Increasing Google Maps API pricing</a> by up to 1400%</li>
<li>2020 - <a href="https://www.theregister.com/2020/03/05/google_reintroduces_management_fee_for_kubernetes_clusters/">Reintroducing management fees for Kubernetes clusters</a></li>
<li>2020 - <a href="https://techcrunch.com/2019/08/27/google-will-kill-off-google-hire-in-2020/">Google Hire shut down</a></li>
</ul>
<p>These changes have damaged Google&rsquo;s credibility for many customers and undermined their commitment to building GCP to be an equal to AWS and Azure. Google has been trying to build customer trust with their <a href="https://cloud.google.com/blog/topics/inside-google-cloud/new-api-stability-tenets-govern-google-enterprise-apis">Enterprise API stability promise</a>, and signing many <a href="https://redmonk.com/jgovernor/2020/07/31/google-clouds-expanding-enterprise-footprint-and-the-rise-of-the-10-year-deal/">10-year deals</a> with large enterprises like Deutsche Bank, Mayo Clinic, and Sabre.</p>
<p>However the last few months have seen several shortsighted decisions:</p>
<ol>
<li><a href="https://9to5google.com/2022/01/19/g-suite-legacy-free-edition/">Charging for personal Google Workspace accounts</a> (Google Workspace comes under Google Cloud). Many of the people affected by this will be decision makers for Google Cloud purchasing decisions, and not people you want to remind about Google&rsquo;s reputation for shutting down products.</li>
<li><a href="https://www.datacenterdynamics.com/en/news/google-restructuring-and-laying-off-google-cloud-support-staff-as-it-buys-mandiant-for-54-billion/">Laying</a> <a href="https://www.reddit.com/r/googlecloud/comments/t5jp48/google_cloud_just_laid_off_its_entire_us_support/">off</a> some Cloud technical support staff and outsourcing support to third-party vendors.</li>
<li>Last week&rsquo;s Cloud price increases.</li>
</ol>
<p>Put together, it paints a picture of an organisation myopically focused on short-term profitability over long-term strategy. These changes show they don&rsquo;t understand customer perceptions of Google Cloud, and the &ldquo;rules&rdquo; of cloud pricing.</p>
<p>These changes are hard to even understand as a business strategy. Raising prices on locked-in customers feels like a move you&rsquo;d see from Oracle, not from the <a href="https://siliconangle.com/2020/07/13/google-cloud-rides-wave-remains-distant-third-place/">third-ranked</a> competitor in a rapidly expanding market.</p>
<p>My best guess as to why Google is doing this now is that Google Cloud set (or had set for them) an <a href="https://rework.withgoogle.com/guides/set-goals-with-okrs/steps/introduction/">OKR</a> to reach profitability. All of the teams are trying to increase profits, regardless of the long-term costs.</p>
<h2 id="a-different-future">A different future</h2>
<p>Google Cloud&rsquo;s strength has always been its technology. It has fewer products than AWS, but those products are more flexible and cohesive. Their IAM model is far simpler than AWS&rsquo;, and as previously outlined, Google&rsquo;s global infrastructure has offered many unique, differentiated products.</p>
<p>At a time when it&rsquo;s hard to even keep track of <a href="https://www.wiz.io/blog/chaosdb-explained-azures-cosmos-db-vulnerability-walkthrough/">Azure&rsquo;s</a> <a href="https://www.netspi.com/blog/technical/cloud-penetration-testing/azure-cloud-vulnerability-credmanifest/">many</a> <a href="https://unit42.paloaltonetworks.com/azure-container-instances/">multi-tenant</a> <a href="https://orca.security/resources/blog/autowarp-microsoft-azure-automation-service-vulnerability/">security</a> <a href="https://www.wiz.io/blog/secret-agent-exposes-azure-customers-to-unauthorized-code-execution/">vulnerabilities</a>, and multiple <a href="https://www.zdnet.com/article/aws-suffers-third-outage-of-the-month/">AWS outages</a> still in recent memory, Google Cloud should have been pressing their advantages.</p>
<p>Instead of raising prices, I think a better strategy would have been to cut prices on data transfer to nearby regions and lean into multi-region services. Google owns massive amounts of <a href="https://cloud.google.com/blog/products/networking/google-cloud-networking-in-depth-cloud-cdn">dark-fibre</a> and <a href="https://cloud.google.com/blog/products/infrastructure/learn-about-googles-subsea-cables">under-sea cables</a> connecting their data centres and could afford to lower their prices. Once inter-region transfer is cheaper, many more applications become feasible to run in high-availability, multi-region configurations. This would be a strong offering to sell, and one that is hard for Amazon and Microsoft to replicate. Customers running compute in multiple regions and using higher-margin services like <a href="https://cloud.google.com/spanner">Spanner</a> would help make back some of the revenue lost from lowering inter-region data transfer.</p>
<p>This would have been a compelling, differentiated offering, playing to Google&rsquo;s strengths. Instead, Google has altered the deal. Their customers will now be praying that they don&rsquo;t alter it further.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Reviewing DisplayLink for macOS and the ALogic DX3</title>
      <link>https://danielcompton.net/displaylink-alogic-dx3-review</link>
      <pubDate>Tue, 19 Oct 2021 11:39:23 +1300</pubDate>
      
      <guid>https://danielcompton.net/displaylink-alogic-dx3-review</guid>
      <description>I recently was looking at how to get more than one display connected to my new M1 MacBook Air. DisplayLink technology had a lot of limitations but was the only option I could see. I looked at different docks and ended up purchasing the ALogic DX3.
These are my thoughts after a few months use. I&amp;rsquo;ve split the review into DisplayLink and ALogic DX3 sections. Most of my complaints are about DisplayLink and I think would be the same no matter which dock/USB adapter you choose.</description>
      <content:encoded><![CDATA[<p>I <a href="/2021/07/28/apple-m1-displaylink-multiple-display">recently</a> was looking at how to get more than one display connected to my new M1 MacBook Air. DisplayLink technology had a lot of limitations but was the only option I could see. I looked at different docks and ended up purchasing the <a href="https://www.alogic.co/alogic-triple-4k-display-universal-docking-station-dx3-with-100w-power-delivery.html">ALogic DX3</a>.</p>
<p>These are my thoughts after a few months use. I&rsquo;ve split the review into DisplayLink and ALogic DX3 sections. Most of my complaints are about DisplayLink and I think would be the same no matter which dock/USB adapter you choose.</p>
<h2 id="alogic-dx3">Alogic DX3</h2>
<ul>
<li>The DX3 has 3 DisplayPort ports, but only two of them are DisplayLink compatible. The third one uses Alternate Mode (I think?) over USB-C to pass the DisplayPort signal directly to the monitor. This was good for me as I could make my center display DisplayPort and use DisplayLink on the peripheral display.</li>
<li>The dock comes with a hefty external power supply almost the size and weight of the dock. The dock has a power button on the front which I thought was unnecessary at first but came in handy as I often need to restart the dock for the Mac to detect one or both of the displays. I&rsquo;ve had this issue on a 2019 Intel Macbook Pro with directly connected DisplayPort cables so I suspect this may be more of a macOS problem. Having the power button on the front is much more convenient than unplugging the displays or turning the displays off and on.</li>
<li>I haven&rsquo;t had any issues with the USB ports. I haven&rsquo;t pushed them very hard, but I also haven&rsquo;t noticed anything &ldquo;wonky&rdquo; about them either. I have a 10-port USB hub that I plug into the dock and it seems to work fine including for an audio interface.</li>
</ul>
<h2 id="displaylink">DisplayLink</h2>
<ul>
<li>With a 4K display, macOS will let you choose a higher resolution to render at, which it will then downscale to the 4K pixels that are actually on the display. When I first bought the DX3, DisplayLink version 1.4 wouldn&rsquo;t allow you to do this, the maximum resolution you could pick was 1920x1080 points at 2k (native 4K resolution). When writing this article, I went back to the <a href="https://support.displaylink.com/forums/287786-displaylink-feature-suggestions/suggestions/42222769-macos-bigsur-m1-support-works-great-but-it-wou">feature request</a> and found that they had released version 1.5 which was meant to fix this issue. It lets you choose 2560x1440 points but also renders at 2560x1440 pixels, instead of 5120x2880 pixels, downscaled to 4K. The good news is that it looks like they are continuing to work on the software and addressing limitations so hopefully this will be fixed in a future update.</li>
<li>DisplayLink 1.4 was doing something which prevented you from using Apple Watch to unlock your computer. I discovered that it also stopped you from using your Watch as an admin password. However, the 1.5 update has a checkbox to &ldquo;Use Apple Watch to unlock on login screen&rdquo;. When you check that, the Watch unlock appears to work at the login screen and in everywhere else Watch unlock would work. I&rsquo;m not sure why that wouldn&rsquo;t just be a default setting?</li>
<li>Note that you can&rsquo;t evaluate DisplayLink CPU usage just by looking at the &ldquo;DisplayLinkUserAgent&rdquo; process. You also need to look at the WindowServer process, as DisplayLink causes work to be done there when rendering to the virtual display.</li>
<li>The DisplayLink software could do with more diagnostics on what is happening. Currently you can&rsquo;t see which displays are controlled by DisplayLink and which are directly connected.</li>
<li>The DisplayLink software doesn&rsquo;t seem to have any way to automatically update or even notify you of updates so you&rsquo;ll need to check the website yourself.</li>
<li>I haven&rsquo;t noticed any latency from the compression/decompression signal transfer, but I&rsquo;m only using the displays for writing code and web browsing so I wouldn&rsquo;t expect many problems.</li>
</ul>
<h2 id="other">Other</h2>
<ul>
<li>I&rsquo;ve had a weird bug where sometimes the MacBook display won&rsquo;t turn on for 10-60 seconds after opening the laptop, even when I&rsquo;ve been using it only a few minutes prior. I&rsquo;m not sure if this is related to DisplayLink software or just a macOS bug.</li>
</ul>
<h2 id="summary">Summary</h2>
<p>Overall, the ALogic DX3 dock serves it&rsquo;s purpose well. If you had any other option, I wouldn&rsquo;t recommend choosing DisplayLink technology, but with an M1 Mac this your best (and only) option. However, I&rsquo;m encouraged that DisplayLink are continuing to improve the Mac user experience. When I upgrade to a new MacBook Pro, I&rsquo;ll either use the DX3 without DisplayLink (if that will work), or sell it and purchase a standard Thunderbolt 4 dock.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Understanding DisplayLink, multiple displays, and M1 Macs</title>
      <link>https://danielcompton.net/apple-m1-displaylink-multiple-display</link>
      <pubDate>Wed, 28 Jul 2021 23:35:44 +1300</pubDate>
      
      <guid>https://danielcompton.net/apple-m1-displaylink-multiple-display</guid>
      <description>Introduction I needed to buy a new Mac recently. I couldn&amp;rsquo;t bring myself to buy a legacy Intel Mac, but the new M1 Macs only support up to two displays. For the MacBook Air, MacBook Pro, and iMac that means you can connect one additional display along with the built-in display. For the Mac Mini, you can add two displays. I wanted a MacBook Air and already had two external displays which I wanted to keep using.</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>I needed to buy a new Mac recently. I couldn&rsquo;t bring myself to buy a legacy Intel Mac, but the new M1 Macs only support up to two displays. For the MacBook Air, MacBook Pro, and iMac that means you can connect one additional display along with the built-in display. For the Mac Mini, you can add two displays. I wanted a MacBook Air and already had two external displays which I wanted to keep using.</p>
<p><strong>Update:</strong> I ended up purchasing the ALogic DX3 and wrote a <a href="/2021/10/19/displaylink-alogic-dx3-review">follow-up post</a> about my experiences with it.</p>
<h2 id="displaylink">DisplayLink</h2>
<p>What are your options if you want to run more than two displays? Enter <a href="https://www.displaylink.com">DisplayLink</a>. DisplayLink (not to be confused with DisplayPort) is the name of a technology created by a company also named DisplayLink. It lets you send a video signal to a display over USB or Wi-Fi instead of via DisplayPort or HDMI. DisplayLink technology was first used in laptop docking stations but can now be found in <a href="https://www.displaylink.com/products">other video-related products</a> including adapter cables and monitors.</p>
<p>DisplayLink has two components - a software driver installed on your computer and a hardware chip in the dock or adapter. The software driver presents itself as one or more displays to the computer. The computer sends pixel data to the software driver, which then compresses the data and sends it over USB. The DisplayLink chip decompresses the data and sends the display signal to the (real) display.</p>
<p>I was pleasantly surprised to see that <a href="https://www.displaylink.com/downloads/macos">DisplayLink&rsquo;s drivers</a> have been updated for Apple Silicon and don&rsquo;t require a kernel extension. From what I can tell, DisplayLink seems to be publishing regular updates to their drivers and is actively working on new features.</p>
<h2 id="displaylink-limitations">DisplayLink Limitations</h2>
<p>Sending compressed video over USB is a pretty neat trick! However, DisplayLink has quite a few downsides to be aware of.</p>
<p>An uncompressed 4K60 video signal requires 12 Gbps of bandwidth. The latest <a href="https://www.displaylink.com/integrated-chipsets/dl-6000">DisplayLink chips</a> run over USB 3.0 which has a bandwidth of 5 Gbps. Even a single 4K signal is too big, let alone multiple displays. This is why DisplayLink needs to compress the captured screen.</p>
<p>For desktop browsing, email, software development, and other general computer tasks where the display doesn&rsquo;t change much from frame to frame, DisplayLink compression can be very efficient and is unlikely to be noticeable. DisplayLink <a href="https://www.displaylink.com/integrated-chipsets/dl-6000">claims</a> &ldquo;Pixel-perfect graphics&rdquo;, and &ldquo;Compression tuned for video content and high-quality graphics&rdquo; on their newer chipsets. If you&rsquo;re a video/photo/graphics professional, you&rsquo;d probably want to check and see if this works for you.</p>
<p>It doesn&rsquo;t sound like it will be as good for <a href="https://www.displaylink.com/small-office/faq#headingTwelve">gaming though</a>:</p>
<blockquote>
<p>While DisplayLink technology is targeted primarily to productivity and video applications, it is suitable for the casual gamer. If you&rsquo;re a &ldquo;power gamer&rdquo;, looking for every edge possible over your opponents, you might want to go another route.</p>
</blockquote>
<p>Another downside to DisplayLink is that you need to install an optional <a href="https://support.displaylink.com/knowledgebase/articles/1932214-displaylink-manager-app-for-macos-introduction-in">program</a> to show the Lock Screen on a DisplayLink monitor. Otherwise, the Lock Screen will only show up on the built-in display.</p>
<p>Unlock with Apple Watch <a href="https://support.displaylink.com/forums/287786-displaylink-feature-suggestions/suggestions/35524279-support-for-unlock-with-apple-watch">doesn&rsquo;t work</a> when using DisplayLink. Apple disables Unlock with Apple Watch with the message &ldquo;Unlocking with Apple Watch is not available while your screen is being shared&rdquo;.</p>
<p>DisplayLink has a few other limitations on Macs: HDCP is not supported so you may not be able to watch Netflix, Hulu, iTunes Movies, etc.; only 4 external displays are supported; screen rotation is not supported; Clamshell mode is <a href="https://support.displaylink.com/knowledgebase/articles/1963276">partially supported</a>. Manufacturers publish <a href="https://us.targus.com/blogs/discover-targus/targus-validates-displaylink-manager-release-1-3-for-big-sur-catalina-and-m1-macbooks">blog posts</a> announcing that new DisplayLink drivers are validated with their hardware, it&rsquo;s probably good to check with your manufacturer before updating.</p>
<p>There are quite a few limitations to using DisplayLink to extend your displays. However, it&rsquo;s also currently the only way to run more than two displays on a Mac, so if you need that then you&rsquo;ll need to look at a DisplayLink powered Dock.</p>
<h2 id="choosing-a-dock">Choosing a Dock</h2>
<p>If you already have a dock without DisplayLink, your cheapest option may be to purchase a DisplayLink USB adapter. You could connect your monitor to the adapter, and then the adapter to a free USB port. DisplayLink keeps a list of <a href="https://www.displaylink.com/products/usb-adapters">USB adapters</a> you can purchase. Check compatibility as not all adapters list support for macOS, although sometimes the reviews will mention that they do still work.</p>
<p>DisplayLink sells chipsets to dock manufacturers. The chipset has their DisplayLink hardware, along with other ports like USB, Ethernet, Audio. This means that products from different manufacturers like Targus, Dell, Alogic, Plugable, Kensington can end up with very similar capabilities because they are all using the same electronics.</p>
<p>Unfortunately, all of the M1 compatible docks I saw had a maximum of one USB-C port. If you have a lot of USB-C devices you&rsquo;ll either need to purchase USB-A-&gt;USB-C adapters or buy a non-DisplayLink dock and a DisplayLink adapter.</p>
<p>If you&rsquo;re investigating docks, you may see reference to <a href="https://blog.startech.com/post/tech-talk-using-usb-c-and-displayport-over-alt-mode/">USB-C Alternate Mode</a>. This is a way for a USB-C port to run non-USB signals over it like DisplayPort and Thunderbolt(!). Alternate Mode doesn&rsquo;t let you run any more displays than you could otherwise do natively.</p>
<h2 id="dock-options">Dock Options</h2>
<p>If you&rsquo;re looking for a list of DisplayLink docks, DisplayLink has a <a href="https://www.displaylink.com/products/universal-docking-stations">list</a> of DisplayLink docks. Here&rsquo;s a list of docks that the manufacturers have said are supported on M1 Macs as a starting point:</p>
<p><strong><a href="https://plugable.com/blogs/news/we-ve-tested-the-new-m1-powered-macbooks-here-s-the-compatibility-info-users-need-to-know">Plugable</a></strong> has a few options:</p>
<ul>
<li><a href="https://plugable.com/products/ud-3900pdz/">UD-3900PDZ</a>, $160 - 3 HDMI ports, 1 supports 4K30, the other 2 only support 1080p/60Hz. 60W Power Delivery, 6 USB-A 3.0 ports, 3.5mm audio jack.</li>
<li><a href="https://plugable.com/products/ud-ultc4k/">UD-ULTC4k</a>, $220 on <a href="https://www.amazon.com/dp/B0779K9DG2?ref_=maas_adg_48E4E5794A8CD3A8AE8DAFFE8060A81C_afap_abs">Amazon</a> - 2 DisplayPort ports that support 4K60 over DisplayLink, 1 HDMI port that supports 4K30. 60W Power Delivery, 4 USB-A 3.0 ports, 1 downstream USB Type-C port, 3.5mm audio jack.</li>
</ul>
<p>Note that Plugable mentioned that their Ethernet ports are limited to 300Mbps on macOS due to driver issues. I&rsquo;m unsure if that extends to all DisplayLink docks.</p>
<p><strong><a href="https://www.alogic.co/business/blog/post/understanding-dual-triple-external-displays-with-apple-s-m1-macs">Alogic</a></strong> also has a few options:</p>
<ul>
<li><a href="https://www.alogic.co/alogic-triple-4k-display-universal-docking-station-dx3-with-100w-power-delivery.html">DX3</a>, $250 on <a href="https://www.amazon.com/ALOGIC-Universal-Charging-DisplayPort-Ethernet/dp/B0924789ZC">Amazon</a> - 3 DisplayPort ports with DisplayLink, 100W Power Delivery, 3 USB-A ports, 1 USB-C port, Micro SD and SD card reader, Gigabit Ethernet port, 3.5mm audio jack.</li>
<li><a href="https://www.alogic.co/dual-4k-display-universal-docking-station-dx2-with-65w-power-delivery.html">DX2</a> - 2X DisplayPort ports, 65W Power Delivery, 3 USB-A ports, 1 USB-C port, Micro SD and SD card reader, Gigabit Ethernet port, 3.5mm audio jack.</li>
<li><a href="https://www.alogic.co/product-solutions/browse-by-category/usb-c-products/usb-c-docking-stations-2/alogic-universal-twin-hd-docking-station-with-usb-c-usb-a-compatibility-dual-display-1080pat60hz.html">Universal Twin HD</a></li>
</ul>
<p><strong><a href="https://us.targus.com/blogs/discover-targus/displays-for-m1-macbook">Targus</a></strong> has several docks with DisplayLink:</p>
<ul>
<li><a href="https://us.targus.com/products/usb-c-universal-dv4k-docking-station-with-100w-power-dock190usz">DOCK190</a>, $310 - 2 DisplayPort/HDMI ports (only 2 video ports can be used at the same time), 100W Power Delivery, 4 USB-A, 1 USB-C, Gigabit Ethernet, 3.5mm audio jack. Thunderbolt alt mode is supported.</li>
<li><a href="https://us.targus.com/products/usb-c-universal-quad-4k-docking-station-100-watt-power-delivery-dock570usz">DOCK570</a>, $415 - 4 DisplayPort/HDMI Ports, 4 USB-A, 1 USB-C, Gigabit Ethernet, 3.5mm audio jack. Thunderbolt alt mode is supported.</li>
</ul>
<p><strong><a href="https://www.kensington.com/en-nz/news-index-blogs-press-center/docking-connectivity-blog/how-to-connect-more-than-one-display-to-an-apple-m1-macbook/">Kensington</a></strong> has four docks with DisplayLink:</p>
<ul>
<li><a href="https://www.kensington.com/p/products/device-docking-connectivity-products/laptop-docks-usb-accessories/sd4700p-usb-c-usb-a-5gbps-dual-2k-hybrid-dock-60w-pd-dp-hdmi-winmac-taa/">SD4700P</a>, $250 - 1 DisplayPort, 1 HDMI port (both limited to 2K resolution), 60W Power Delivery, 5 USB-A, 1 USB-C, 1 Gigabit Ethernet, 3.5mm audio jack. Supports up to 5Gbps.</li>
<li><a href="https://www.kensington.com/p/products/device-docking-connectivity-products/laptop-docks-usb-accessories/sd4750p-usb-c-usb-a-dual-4k-hybrid-docking-station-w-85w-pd-dp-hdmi-winmac/">SD4750P</a>, $290 - 2 DisplayPort/HDMI ports up to 4K60, 85W Power Delivery, 5 USB-A, 1 USB-C, 1 Gigabit Ethernet, 3.5mm audio jack. Supports up to 5Gbps.</li>
<li><a href="https://www.kensington.com/en-nz/p/products/connectivity/universal-laptop-docking-stations/sd4780p-usb-c-usb-a-10gbps-dual-4k-hybrid-docking-station-w-100w-pd-dphdmi-winmacchrome/">SD4780P</a> - 2 DisplayPort/HDMI ports up to 4K60, 100W Power Delivery, 5 USB-A, 1 USB-C, 1 Gigabit Ethernet, 3.5mm audio jack. Supports up to 10Gbps.</li>
<li><a href="https://www.kensington.com/p/products/device-docking-connectivity-products/laptop-docks-usb-accessories/sd4900p-usb-c-and-usb-a-10gbps-triple-4k-hybrid-dock-60w-pd-dp-hdmi-winmacchrome/">SD4900P</a> $320 - 3 DisplayPort/HDMI ports up to 4K60, 60W Power Delivery, 5 USB-A, 1 USB-C, 1 Gigabit Ethernet, 3.5mm audio jack. Supports up to 10Gbps.</li>
</ul>
<p><a href="https://blog.startech.com/post/apple-m1-silicon-fully-compatible-with-startech-com-products/">StarTech</a> has 4 docks with DisplayLink:</p>
<ul>
<li><a href="https://www.startech.com/en-us/cards-adapters/dk30ch2dep">DK30CH2DEP</a> - 2 DisplayPort (4K60), 1 HDMI port (4K30), 100W Power Delivery, 4 USB-A, 1 USB-C, 1 Gigabit Ethernet, 3.5mm audio jack.</li>
<li><a href="https://www.startech.com/en-us/cards-adapters/dk30c2dpep">DK30C2DPEP</a> - 2 DisplayPort/HDMI (4K60), 100W Power Delivery, 3 USB-A, 1 USB-C, 1 Gigabit Ethernet, 3.5mm audio jack.</li>
<li><a href="https://www.startech.com/en-us/cards-adapters/dk30c2dppd">DK30C2DPPD</a> - 2 DisplayPort/HDMI (4K60), 60W Power Delivery, 3 USB-A, 1 USB-C, 1 Gigabit Ethernet, 3.5mm audio jack.</li>
<li><a href="https://www.startech.com/en-us/cards-adapters/dk30chddppd">DK30CHDDPPD</a> - 1 DisplayPort (4K30), 1 HDMI (4K30), 60W Power Delivery, 4 USB-A, 1 USB-C, SD Card slot, 1 Gigabit Ethernet, 3.5mm audio jack.</li>
</ul>
<p>Dell has some docks with DisplayLink technology, but they don&rsquo;t list compatibility with Macs, so probably safest to avoid them unless you&rsquo;re able to try them first.</p>
<p><a href="https://www.caldigit.com/docks/">Caldigit docks</a> are highly regarded but don&rsquo;t contain DisplayLink chips. This means <a href="https://www.caldigit.com/apple-silicon-mac-and-caldigit-dock-compatibility/">you can&rsquo;t run multiple displays</a> on them. However, they seem to work if you only need a single external display on an M1 Mac, or purchase a USB display adapter.  There is a <a href="https://www.youtube.com/watch?v=Kq_FyjcAULA">video</a> of someone using a Caldigit TS3 Thunderbolt dock with 4 DisplayLink USB adapters.</p>
<h2 id="disclaimer">Disclaimer</h2>
<p>I&rsquo;m not an expert on any of this, I&rsquo;ve just read a lot and compiled it into one place. Please let me know if I&rsquo;ve missed something or if you have any suggestions.</p>
<h2 id="summary">Summary</h2>
<p>There are lots of moving parts involved with picking a USB-C dock, let alone one also running DisplayLink. You need one which:</p>
<ul>
<li>Supports DisplayLink.</li>
<li>Supports the number of displays you have, at the resolution and refresh rate you want.</li>
<li>Has enough USB ports to support other peripherals, or is reliable enough to add a USB hub.</li>
<li>Supports USB Power Delivery with your laptop, with enough wattage.</li>
<li>Has enough bandwidth for all your devices.</li>
<li>Doesn&rsquo;t have audible fan noise.</li>
<li>Works reliably and doesn&rsquo;t cause other issues.</li>
</ul>
<p>As you can tell from the number of limitations mentioned throughout this post, picking a dock that works with your setup is far from a simple task. I recommend checking the specs closely, checking out reviews, and ideally trying it out at home before committing.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Building Stable Foundations - Heart of Clojure 2019 talk</title>
      <link>https://danielcompton.net/building-stable-foundations-heart-of-clojure-2019</link>
      <pubDate>Sun, 21 Feb 2021 12:30:26 +1300</pubDate>
      
      <guid>https://danielcompton.net/building-stable-foundations-heart-of-clojure-2019</guid>
      <description>This was a talk I gave at the first Heart of Clojure in 2019. I wrote more about why I enjoyed it so much at the time.
You can also see the talk on Youtube.
Good morning. I was going to ask if everyone&amp;rsquo;s feeling awake, but I think after that karaoke, I think everyone&amp;rsquo;s pretty well awake by now.
This talk is called Building Stable Foundations, and it&amp;rsquo;s about building stable long lasting foundations for the Clojure community.</description>
      <content:encoded><![CDATA[<p>This was a <a href="https://heartofclojure.eu/speakers#daniel-compton">talk</a> I gave at the first <a href="https://heartofclojure.eu">Heart of Clojure</a> in 2019. I wrote more about why I enjoyed it so much <a href="https://danielcompton.net/2019/08/24/heart-of-clojure">at the time</a>.</p>
<p>You can also see the talk on <a href="https://www.youtube.com/watch?v=z_q6nVeD_K4">Youtube</a>.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-001.png" alt=""></p>
<p>Good morning. I was going to ask if everyone&rsquo;s feeling awake, but I think after that karaoke, I think everyone&rsquo;s pretty well awake by now.</p>
<p>This talk is called Building Stable Foundations, and it&rsquo;s about building stable long lasting foundations for the Clojure community.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-002.png" alt=""></p>
<p>[00:00:30] Bozhidar has already introduced me slightly, but I&rsquo;ll go back over it. My name&rsquo;s Daniel Compton, I&rsquo;m an open-source project maintainer. I am an administrator at Clojars. I write and record a Clojure podcast and newsletter at therepl.net, and I am working at a startup called Falcon.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-003.png" alt=""></p>
<p>Falcon is hiring for Clojure developers, remote Clojure developers. If you&rsquo;re sort of in the U.S.-ish region, or you can work [00:01:00] on a similar kind of time zone, check out <a href="https://falconproj.com">falconproj.com</a> [Ed: Falcon shut down 😢] or come and talk to me, and I can tell you more about what we&rsquo;re working on.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-004.png" alt=""></p>
<p>The other thing that you may know me from is an organization called Clojurists Together. With the help of our members, we fund and support open-source Clojure projects. The question is, well, why is that important? Firstly, who has heard of Clojurists Together?</p>
<p>Great. All right. Just about everyone, and who [00:01:30] here is a member or your company is a member of Clojurists Together. Great. The reason why Clojurists Together is important, or I think it&rsquo;s important, is that Clojure is foundational, and open-source Clojure is foundational to what we work on. Of course, the Clojure language is open-source, but the vast majority of tools, and libraries, and services, that we all use as day-to-day Clojure programmers come from open-source software.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-005.png" alt=""></p>
<p>It&rsquo;s important, not just for [00:02:00] us as a community, but open-source Clojure is really foundational for businesses too. Businesses are investing lots and lots of money into the Clojure ecosystem, and they&rsquo;re relying on these investments lasting a long amount of time. I think it&rsquo;s really important to sort of remember that context of the money being invested into Clojure and making sure that that is well-spent and it&rsquo;s going to be [00:02:30] a long lasting investment.</p>
<p>Who here is lucky enough to get paid to work with Clojure? All right. Of those of you who had your hands up, who uses open-source Clojure code in your day job? It&rsquo;s a bit of a silly question, isn&rsquo;t it? That the idea that as a working Clojure programmer you wouldn&rsquo;t be using a significant amount of open-source code as part of your work. Maybe there are some people. I suspect there are a couple, but for most of us a lot of the work we do is built on top of these really important open-source foundations. Open-source creates an incredible amount of value for everybody that gets to use it. It&rsquo;s the shared resource that doesn&rsquo;t run out when somebody uses it, that doesn&rsquo;t mean that anyone else can use less of it. This is a really amazing property of software and open-source software.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-006.png" alt=""></p>
<p>But a few years ago, I started to notice [00:03:30] developers talking about burning out. In the Clojure community and also outside of the Clojure community, and this was kind of worrying to me, because a lot of these people were really important to the Clojure community. They were doing really important work.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-007.png" alt=""></p>
<p>I started to see these kinds of things being said. People saying things like, <strong>&ldquo;Any tips for a post burnout return to open-source? I&rsquo;m exhausted, but want to keep going.&rdquo;</strong></p>
<p>This [00:04:00] really broke my heart to see these people who I cared about, many friends and that they were not feeling supported. They were thinking of leaving, and I was really worried about this. We have this problem that the foundations of our community are perhaps not as strong as they could be, or they&rsquo;re not being as supported as they could be.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-008.png" alt=""></p>
<p>Before we talk more about our open-source foundations, I think we can learn some things from building [00:04:30] foundations. This is what a building site looks like before you start building on it itself. The first thing you have to do when you&rsquo;re building is to prepare these foundations, everything else goes on top of them. So you have to get this right first.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-009.png" alt=""></p>
<p>When you&rsquo;re building foundations, there&rsquo;s a few things you need to do. The first thing you need to do is survey the land. You need to find out, do you have the rights to work on this land that you think you own and is the structure that you&rsquo;re going to [00:05:00] be building allowed to be built on this land. This is really important to get right, because if you get it wrong, you might invest all of this money into building something which you then need to take back down again.</p>
<p>Next thing you need to do is check under the ground. What is going on underneath the surface? You can see what&rsquo;s on top of the ground, but it&rsquo;s really important to find out what&rsquo;s going on underneath there before you start building, so that you don&rsquo;t end up being surprised by things later on. The last thing, and this is the most important thing and [00:05:30] what we most often think of when we&rsquo;re thinking of building foundations is reinforcing the ground. A fully built house can weigh 50 to a hundred tons or more, and that&rsquo;s a lot of weight to be putting into the ground, and so you really want to make sure that those foundations are going to be able to hold up to that kind of weight.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-010.png" alt=""></p>
<p>This is quite similar to what we do when we&rsquo;re picking dependencies. The first thing we do is we&rsquo;ve got to check the license. I hope we check the license and [00:06:00] we also will usually want to review the codebase. Is it well-written Clojure? Does it have tests? Is it actively maintained? These are all important things to be aware of before you pick a library, and the last thing, if this is going to be used in the critical path of your production software, you probably want to test it, find out how fast is it. Can it stand up to the full weight of production? Are there memory leaks, that sort of thing?</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-011.png" alt=""></p>
<p>Foundations are really important [00:06:30] to building a house, but it turns out that they&rsquo;re actually pretty cheap. In the U.S. on a $400,000 house build. They cost about $10,000, two and a half percent, so not really that much of the cost of the build. This is because it&rsquo;s a very well understood process. It&rsquo;s been done many times every day, and for the most part, it goes pretty smoothly.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-013.png" alt=""></p>
<p>Has anyone ever seen a house like this before?
[00:07:00] What&rsquo;s happening here is that the foundation on this house wasn&rsquo;t built correctly the first time. It&rsquo;s a little bit hard to tell, but this house has been lifted right up off the ground, quite a few meters up. Stacked up on these Jenga blocks so they could fit machinery underneath to repair the foundations, and then they&rsquo;re going to slowly lower that house back down.</p>
<p>If you look closely, I&rsquo;m not sure if it&rsquo;s going to come through very well here, but there are some people standing underneath this house, [00:07:30] very brave people. Does anyone relate to this picture? Has anyone had to fix the foundational dependency in your codebase and feel like there&rsquo;s a lot of things bearing down on top of you? As you can imagine, this is not a cheap process. It can cost $20,000 to $100,000 to do this kind of repair, which is two to 10 times more than the cost of building the foundations correctly in the first place</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-014.png" alt=""></p>
<p>[00:08:00] Yesterday, Tiago talked to us about resilience, and I&rsquo;m glad he really dug into this, because I don&rsquo;t need to go too deeply, but we&rsquo;ll remember resilience as the ability to recover from a stress or a change. This is what you&rsquo;re going for when you&rsquo;re building foundations, you want the foundations to be able to stand up to the elements and all of the things that a house is going to face over a hundred year lifetime. What we can see here is there&rsquo;s two houses, on the left&hellip; If you look at them, superficially they kind of look the same. They&rsquo;re [00:08:30] both held up by wooden poles. They&rsquo;ve both got thatch kind of roofs. They&rsquo;re both orangy. They&rsquo;re both roughly the same size, but the one on the left is not very resilient at all, and the one on the right is incredibly resilient, even though it&rsquo;s over the water.</p>
<p>This house on the right is, well, it&rsquo;s a community. Firstly, it&rsquo;s a community of houses. It&rsquo;s not just a single house, and it&rsquo;s also held up by many stilts, so that even if you lost one, or two or even a dozen of these stilts, [00:09:00] the whole structure would still be sound. Whereas on the left, you&rsquo;ve got just two poles holding this house up. And if one of those two goes down, the whole thing is coming down. If you agree with me that open-source software is the foundation of the Clojure community, then we need to be asking this question, how resilient are our foundations? A few years ago, as I was looking around the Clojure community, it seemed to me that we were perhaps closer to the left-hand side than [00:09:30] the right-hand side.</p>
<p>We had a few people doing a tremendous amount of work for the Clojure community. People were depending on their work every day, they were using it. It was really important, but they were feeling unappreciated, perhaps burnt out, and there was this refrain of, &ldquo;I&rsquo;m exhausted, but want to keep going.&rdquo; I thought they were at severe risk of burning out. If we lost these people, this would be somewhat equivalent to that house we saw, having to be lifted up on the blocks, [00:10:00] and there would be a huge investment. We would lose a huge amount if we lost some of these people, and it would cost us a lot of time and effort to regain that knowledge and hard won wisdom.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-016.png" alt=""></p>
<p>This led me and others to create this organization called Clojurists Together. We have a very simple mission. We want to fund and support open-source software, infrastructure, and documentation that&rsquo;s important to the Clojure and Clojure script community.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-017.png" alt=""></p>
<p>We [00:10:30] fund three kinds of projects. The first kind of project is maintenance projects, and these are projects that are often not very interesting to fund. Maybe they&rsquo;re very stable, used by lots of people, but over time, software needs maintenance, and if people aren&rsquo;t being paid, or aren&rsquo;t getting dedicated time to work on it these maintenance things can pile up over time. So this is a place where I think Clojurists Together is really well suited to help these projects, [00:11:00] because it&rsquo;s work that sometimes wouldn&rsquo;t get done otherwise, or it would take a lot longer. We really liked being able to fund these kinds of low-level boring kind of work, but these are really important improvements to make.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-018.png" alt=""></p>
<p>The next kind of work we like to fund is new development. This might be a project that is already well understood and used by many people, and they have an idea for a new feature, or a new release, or something that they would like to do, and they need some dedicated [00:11:30] time to work on it. We also take and fund projects who do this kind of work.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-019.png" alt=""></p>
<p>The last kind of project is new fledgling of projects, and we fund a few of these kinds of projects where someone comes to us with a seed of an idea, and perhaps they&rsquo;ve already created proved out that this is an idea, but they would like some funding to go to the next level with it, and we&rsquo;ve been able to fund some of these projects, and they have [00:12:00] really surpassed my expectations. You&rsquo;ve done amazing work, so this is another kind of project we like to fund.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-020.png" alt=""></p>
<p>We launched in October 2017, and in 2018 and 2019, we&rsquo;ve funded 11 projects.</p>
<ul>
<li>We&rsquo;ve funded Bozhidar on CIDER.</li>
<li>We funded Tim Pope to work on Fireplace, which is a Vim Clojure plugin.</li>
<li>We funded Arne Brasseur, also here, to work on Kaocha, which is a next generation test runner for Clojure.</li>
<li>We funded Mike Fikes to work [00:12:30] on ClojureScript and the ClojureScript compiler.</li>
<li>We funded Nikita Prokotov to work on Datascript.</li>
<li>We funded Thomas Heller to work on Shadow CLJS, which is a ClojureScript and JavaScript build tool.</li>
<li>We funded Lee Hinman to work on clj-http. This is a HTTP client that&rsquo;s used by many projects directly. I think it&rsquo;s one of the most downloaded projects on Clojars, but it&rsquo;s also used as the foundation for many of these other API clients. You may not even be aware that you&rsquo;re using it, [00:13:00] but improvements to clj-http benefit a large part of the Clojure community.</li>
<li>We also funded Aleph. This is a Netty based web server for Clojure.</li>
<li>We funded Dragan Djuric to work on Neanderthal, and then he worked on documentation for Neanderthal and wrote 150 pages of documentation about deep learning and Clojure from scratch. It&rsquo;s a really interesting read if you&rsquo;ve been wanting to understand deep learning. [00:13:30] I&rsquo;d really recommend checking that out. It&rsquo;s really good.</li>
<li>We also funded Martin Klepsch to work on cljdoc. Cljdoc automatically builds the documentation for you every time you push to Clojars. This is really nice, because it means that the maintainer of the project doesn&rsquo;t need to remember to update the API documentation every time they do a deploy. It just happens automatically, and you can look back at older versions of the API documentation, and there&rsquo;s all sorts of other good things that have come from [00:14:00] having a shared platform that we can all use to improve.</li>
<li>The last project we funded was Bruce Hauman to work on Figwheel. Figwheel is a really key tool for the ClojureScript community. It&rsquo;s had a lot of influence outside of the Clojure community as well. It&rsquo;s been cited by many other environments. I&rsquo;ve seen its influence, and the influence of things that came before it too, spreading across the entire community. Live reloading is one of ClojureScript&rsquo;s [00:14:30] secret weapons, or perhaps not so secret anymore.</li>
</ul>
<p>Who in the audience has used one of these projects? All right. What about three projects. Who&rsquo;s used three or more of these projects? Wow. Okay. Who&rsquo;s used five or more of these projects? Great.
All right. Is there anybody here who has not [00:15:00] used a single one of these projects?</p>
<p>All right. Well, that&rsquo;s really good to see. [Nobody put their hand up]. I&rsquo;m glad that this has benefited people.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-021.png" alt=""></p>
<p>I&rsquo;m really excited to be able to announce today, this Heart of Clojure conference has been timed really well to be able to announce on stage the next funding round. We&rsquo;re going to be funding four projects, $9,000 over the next three months.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-022.png" alt=""></p>
<p>The first project we are funding [00:15:30] is Calva. Calva is a VS Code extension for Clojure. VS Code has been gaining in popularity hugely over the last few years. I think it&rsquo;s one of the sort of surprise sleeper hits of the programming community, so we&rsquo;re really excited to be able to fund Calva.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-023.png" alt=""></p>
<p>We&rsquo;re also funding Thomas Heller to work on Shadow CLJS again. He&rsquo;s been doing incredible work for the Clojure and ClojureScript community on Shadow CLJS. I hear lots of people talking about it and using [00:16:00] it, and it&rsquo;s a really great tool, and those improvements are benefiting lots of people.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-024.png" alt=""></p>
<p>Another project we are funding is Meander. Meander is a really interesting Clojure, ClojureScript, data transformation library. I probably can&rsquo;t do it justice here, but Michiel Borkent [Ed: this was Timothy Pratley, sorry Michiel!] wrote a <a href="http://timothypratley.blogspot.com/2019/01/meander-answer-to-map-fatigue.html?m=1">really great blog post</a> about this, so if you find him here at the conference, ask him to tell you more about Meander, because it&rsquo;s a really cool project, transforming data and maps, which [00:16:30] we do every day.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-025.png" alt=""></p>
<p>The last project is CIDER. I would say CIDER needs no introduction as well, because many, many people use CIDER and many more people also use Bozhidar&rsquo;s work on the Orchard and in REPL and all of these other foundational things that sit beneath CIDER that we as a community get to take advantage of. I&rsquo;m really excited to be able to fund these four projects, thanks to the [00:17:00] support of our members.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-026.png" alt=""></p>
<p>The way Clojurists Together works is that we have members sign up throughout the year, and then every quarter we will go to them and say, &ldquo;Hey, what do you think we should be working on? What&rsquo;s interesting to you, what do you think is useful? What areas do you think need support?&rdquo; Then we take that information and we create a call for proposals. We say to the wider Clojure community, &ldquo;Hey, here&rsquo;s what our members would like us to fund. Please [00:17:30] give us some proposals,&rdquo; and every quarter we get an amazing amount of proposals, more than we could pick. The quality of these submissions is really high. Then the committee members vote on the projects that we want to fund, and then we&rsquo;ll fund those projects for three months. At the end of those three months, we turn around and do it all again, so it&rsquo;s pretty straightforward.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-027.png" alt=""></p>
<p>Clojurists Together has been getting noticed and has influenced beyond [00:18:00] just the Clojure community. This is my friend, Devon, who works at GitHub, and she&rsquo;s talking at GitHub Satellite earlier this year about GitHub Sponsors. Clojurists Together was mentioned as an influence on GitHub Sponsors. GitHub Sponsors is a project for where you can fund directly the projects that you use on GitHub. I&rsquo;m really excited to see this. I think GitHub has a really wide reach, clearly, in the development community, and they&rsquo;re helping to [00:18:30] change attitudes around open-source funding for both, in the Clojure community, but also, in the wider community. This is something I&rsquo;m really looking forward to.
<img src="/media/2021/02/heart-of-clojure/building-stable-foundations-028.png" alt=""></p>
<p>Devon has this quote, &ldquo;Our goal is for open-source to be a serious career path people can set up.&rdquo;</p>
<p>This is kind of the, I think, the next frontier for the Clojure community too. That we have a bunch of projects that are really important, that people are using, and I would really like to see [00:19:00] people be able to be funded to work full-time or nearly full-time on these projects for the good of the community. Clojurists Together, can&rsquo;t do it all. We&rsquo;re set up to do a particular kind of funding, and so what I&rsquo;d like to see is that the community as a whole starts to build this open-source middle class of single or small teams being funded in a meaningful way, and being appreciated by the community so that they can do this [00:19:30] work that benefits everybody.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-030.png" alt=""></p>
<p>Part of this is that we&rsquo;ve just launched a page on our site called <a href="https://www.clojuriststogether.org/beyond/">Beyond Clojurists Together</a>, where we are collecting Clojure projects and Clojure programmers who are accepting money from Patreon, Open Collective, GitHub Sponsors, or whatever other tools they have, to be funded directly. If you&rsquo;re interested in funding projects and you don&rsquo;t really know where to start, this could be a really good place for you to go start looking and finding [00:20:00] some of the dependencies that maybe you or your company is using to fund them directly.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-032.png" alt=""></p>
<p>How do we get there? How do we get to this glorious future where all of our dependencies are supported and maintained? It needs two things, time and money. Sometimes people and companies have capabilities for one or the other. We have a lot of people investing, people in companies too, investing in open-source [00:20:30] projects, open-sourcing internal things or maintaining projects. Other times companies don&rsquo;t really have the time or the capacity to be directly working on open-source projects, but they have some money available that they could put into maintaining them instead.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-033.png" alt=""></p>
<p>The other side of the equation is money, and companies spend money on lots of things. They spend it on our salaries, software licenses, cloud hosting, hopefully [00:21:00] green cloud hosting after that talk yesterday, and offices and snacks.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-035.png" alt=""></p>
<p>Companies are used to spending money on lots of things, but I think open-source projects often aren&rsquo;t shaped very well for companies to give money to, and companies need these two things. They need value. They need to be able to say to the decision-makers, to the finance department, &ldquo;We are getting something of value when we are giving money to this project.&rdquo; That doesn&rsquo;t mean [00:21:30] that you need to sell out to the man. There&rsquo;s lots of different ways that you can provide value to projects, to companies that are both valuable to the companies, that fit with the skills and capacity of what you have, but most importantly, still meet the values that you hold as a person and the values of your project.</p>
<p>This could be things like consulting, feature development, long-term support, maintenance, [00:22:00] and these are things that oftentimes you may be doing anyway, but if you&rsquo;re able to sell it, and sell this to companies in a way that they are able to understand, and sell onto their decision holders, this can be a really powerful thing.</p>
<p>The other thing that companies need is invoices, and not just invoices, but all of the other financial infrastructure that goes along with things. Companies are not used to using PayPal [00:22:30] donation links to pay for their office rent. They pay money to a bank account, and so this is something where open-source projects, again, aren&rsquo;t often shaped very well to accept this money.</p>
<p>This is where I&rsquo;m really excited to see platforms like Open Collective, Patreon, GitHub Sponsors who are providing the shared common infrastructure for projects to be able to work, to be able to provide the kinds of things that companies [00:23:00] need to be able to give money to.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-036.png" alt=""></p>
<p>The question now is, are we investing in stable foundations? Are we building stable, resilient foundations that are going to last us the test of time? To answer that question, we need to sort of answer, well, compared to what? The main input to open-source projects is labor, people spending their time on it. I thought perhaps a good comparison to [00:23:30] this will be, how much are we spending on Clojure developer salaries and businesses. To answer that we need two numbers. We need how many Clojures developers there are, and how much they&rsquo;re getting paid.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-037.png" alt=""></p>
<p>Estimates vary from perhaps 20,000 to 50,000 working Clojure developers. We want to be conservative here, so we will just take 20,000, and then we need to figure out how much they&rsquo;re getting paid. The Stack Overflow Survey for 2019, put the average Clojure developer salary, worldwide, [00:24:00] at 90,000 U.S. dollars. Clojure&rsquo;s been at the top for the last three years, which is pretty good, but I&rsquo;ve heard people quibble with this number, say that maybe it&rsquo;s a bit inflated or unrepresentative in some way, so let&rsquo;s just take it back a bit more to still be really conservative, and we would just say $80,000 a year.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-038.png" alt=""></p>
<p>If you multiply these two numbers together, you end up with $1.6 billion a year being spent on Clojure developers.
This doesn&rsquo;t even include all [00:24:30] of the other expenses that go around Clojure that you need to run a business, and it doesn&rsquo;t even include the full cost of hiring an employee, but I think this is a really good number to compare to and to think about.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-039.png" alt=""></p>
<p>If we were to spend a relatively small percentage of what we spend on Clojure developers, on supporting the foundations, that could be a meaningful amount of money, say two and a half percent of 1.6 billion would be $ [00:25:00] 40 million a year. I think, I can&rsquo;t even really imagine quite what that would look like. It&rsquo;s just such a long way away from where we are currently that it would&hellip; Yeah, I can&rsquo;t imagine quite that what that would look like, but what I&rsquo;ve seen from funding projects, even at a very small level far below this, is that the return on investment there has been incredible.</p>
<p>I think we would see some really exciting things start to happen, even more than they are currently, [00:25:30] if we were to be able to even approach this level of funding, which itself is, I think, very small compared to the value that we as a community get from these open-source foundations.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-040.png" alt=""></p>
<p>We come back to this image of the houses on the water, and this image really appeals to me, because I see some similarities here with the Clojure community. These are not always the most pretty houses, some of [00:26:00] those stilts down below look a little bit rickety, but together as a whole, these come together to form a really solid stable foundation. This is what I&rsquo;m hoping that we can build together for the Clojure community, and to be clear, this is already happening, well before Clojurists Together. This is still a really strong community before this, and I&rsquo;m excited to see kind of where we can go in the future.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-041.png" alt=""></p>
<p>If this idea appeals to you, here&rsquo;s some things that you could [00:26:30] do.</p>
<ul>
<li>First thing is support your dependencies. You can go have a look at that page on Clojurists Together, Beyond Clojurists Together, where you can find some projects that you are using, which you might not even be aware. We&rsquo;re accepting donations.</li>
<li>Another thing you can do is commit engineering time to maintaining the dependencies that you work on. This is a really key thing to do, and I know many companies already do this, so I really want to recognize that and thank them for their work they&rsquo;re already doing here.</li>
<li>Another interesting [00:27:00] thing you can do is ask when you are next looking for work, ask the companies that you&rsquo;re talking to, do you support in some way, the open-source dependencies that you use? I think this is a really interesting question, because sort of below just your funding open-source, I think the primary barrier to that is changing mindset and expectations around what [00:27:30] it means to use open-source, and the potential benefits for the community as a whole to fund it. If you ask companies, when you&rsquo;re looking for work, &ldquo;Do you do this?&rdquo; Companies are looking to stand out to you, and so I think we might start to see the answer more and more become, &ldquo;Yes.&rdquo;</li>
<li>Another thing you can do is stand for Clojurists Together elections. We have a board of seven people and every year in November, we have elections, so if you would like to be directly involved in helping us plan where we [00:28:00] go into the future you can stand for these elections.</li>
<li>The last thing you can do is join Clojurists Together. I see many people already in the room are Clojurists Together members, and I really appreciate that. You can sign up as a company, or a developer, as an individual. The choice is yours there.</li>
</ul>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-042.png" alt=""></p>
<p>I want to acknowledge many people here. Firstly, Heart of Clojure, Ana and Martin, they&rsquo;ve put on a really great conference here, so I really appreciate them bringing me along to speak.</p>
<p>[00:28:30] I&rsquo;d also like to thank Ruby Together, and André Arko in particular. Ruby Together is the organization that we modeled ourselves afterwards. They&rsquo;ve done a lot of trailblazing work here and André Arko, in particular, has given us a lot of time so that we can learn from some of the things that they&rsquo;ve done.</p>
<p>I&rsquo;d also like to thank the Software Freedom Conservancy. I saw someone here had a [00:29:00] Software Freedom Conservancy shirt on yesterday. The Software Freedom Conservancy, if you&rsquo;re not aware is our non-profit parent. They handle all of the accounting, and payments, and financial, and legal things that go on that companies need, and that we need to have happen, but that we can rely on them to provide for us. They&rsquo;ve done an amazing amount of work for us, and so I really appreciate them.</p>
<p>Next group of people I&rsquo;d like to think is [00:29:30] the projects that have applied. We have more projects apply every quarter than we could fund, and as I read over the applications, I&rsquo;m really excited, because there&rsquo;s so many good projects out there, and so I&rsquo;d like to thank everyone who has applied.</p>
<p>I&rsquo;d also like to thank the projects that we funded. Sometimes today in the talk, I might&rsquo;ve slipped and said that we did this work and <em>I</em> wasn&rsquo;t programming on CIDER, Bozhidar was, so I&rsquo;d like to thank the projects that we funded, that have done this work. I know that often they&rsquo;ve taken [00:30:00] time off paid work, or taken holiday time. While we&rsquo;ve been able to fund them to a certain level, I know often that still means a pay cut for them to be able to do this work, so I really appreciate that.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-043.png" alt=""></p>
<p>Also, I&rsquo;d like to thank the rest of the <a href="https://www.clojuriststogether.org/team/">Clojurists Together team</a>. We have these board members.</p>
<p>On the left we have Maria Geller, Daniel Solano Gómez, Larry Staton Jr., Nola Stowe, Fumiko Hanreich, and Laurens Van Houtven. These are all current board members. We also have [00:30:30] board members from the past, Bridget Hillyer, Toby Crawley, Devin Walters, and Rachel Magruder. [inaudible 00:30:36]is our admin assistant. If you&rsquo;re a Clojurists Together member, you might&rsquo;ve got some stickers from us recently, and if you&rsquo;re wondering, why did this come from Spain? It&rsquo;s because Rachel, our admin assistant lives in Spain.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-044.png" alt=""></p>
<p>I&rsquo;d also like to thank our members. We&rsquo;ve seen many of these names around the conference already. Pitch, Nubank, JUXT, Metosin, Adgoji, and Funding Circle. [00:31:00] These companies have all been a huge help to Clojurists Together, and have funded us in a really big way that have let us do all of the work that we&rsquo;ve been able to do.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-045.png" alt=""></p>
<p>Also, I&rsquo;d like to think these other company members, I don&rsquo;t have time to go over all of their names, but many of these names are going to be familiar to you, and some of them are at the conference as well.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-046.png" alt=""></p>
<p>This is probably my favorite slide at the talk, because this is the names of the 200 members, developer members in the Clojure, [00:31:30] Clojurists Together that are members of Clojurists Together. Yeah, there&rsquo;s far too many here to name them all. I tried to make the text bigger, so that you could even read the names, but then it just went on for slides, and slides, and slides.</p>
<p>I can&rsquo;t name them all, but I&rsquo;d really like to say thanks to the 204 developer members, the 34 company members, and also to the rest of the Clojure community.</p>
<p><img src="/media/2021/02/heart-of-clojure/building-stable-foundations-048.png" alt=""></p>
<p>The Clojure community is a [00:32:00] really special place. It&rsquo;s warm. It&rsquo;s very small, and I think we punch above our weight in terms of the impact that we can have, in terms of the tooling and libraries that we create. That&rsquo;s in large part due to the contributions of all of the Clojure community coming together to build things for everybody. I think a good chunk of the Clojurists Together members are here at this conference, and so again, I especially want to say thanks to you for your support.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Staff</title>
      <link>https://danielcompton.net/staff</link>
      <pubDate>Thu, 28 May 2020 12:04:45 +1300</pubDate>
      
      <guid>https://danielcompton.net/staff</guid>
      <description>I’m thriled to announce that I have finally attained the coveted blue GitHub &amp;ldquo;Staff&amp;rdquo; badge!

I&amp;rsquo;m joining the Social Coding team at GitHub as a product manager. For the last six years I’ve been writing Clojure professionally; product management is going to be quite different, but I’m looking forward to it. There are a few reasons why I&amp;rsquo;m looking forward to working at GitHub:
 Over the last few years working on Clojurists Together I’ve been looking at how to fund open source software that is in the community good.</description>
      <content:encoded><![CDATA[<p>I’m thriled to announce that I have finally attained the coveted blue GitHub &ldquo;Staff&rdquo; badge!</p>
<p><a href="https://github.com/danielcompton"><img src="/media/2020/05/staff.png" alt="GitHub staff badge for @danielcompton" width="325px"></a></p>
<p>I&rsquo;m joining the Social Coding team at GitHub as a product manager. For the last six years I’ve been writing Clojure professionally; product management is going to be quite different, but I’m looking forward to it. There are a few reasons why I&rsquo;m looking forward to working at GitHub:</p>
<ul>
<li>Over the last few years working on <a href="https://www.clojuriststogether.org">Clojurists Together</a> I’ve been looking at how to fund open source software that is in the community good. One of the best parts of the role has been talking to open source maintainers to help design funding programs that serve their needs, and the needs of the community. In my new role I’ll get to talk to even more open source maintainers, contributors, and users about their experiences with open source and GitHub.</li>
<li>GitHub is a remote friendly company and the majority of their employees were remote pre-COVID. I’ve only worked in small remote teams and I’m looking forward to seeing how remote work scales to a large organisation.</li>
<li>GitHub has been on a tear in the last few years, releasing many features and products. I’m excited to experience this from the inside.</li>
<li>Im also looking forward to be working for Devon Zuegel. I met Devon 18 months ago when she was doing research for <a href="https://github.com/sponsors">GitHub Sponsors</a>, and I’ve been impressed with the work she and the rest of the GitHub Sponsors team has done since then.</li>
</ul>
<p>GitHub is the worlds most important social network for developers, and I&rsquo;m thankful for the opportunity to help build it.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Deciphering IRD&#39;s new acronyms - IIT return and ITN return</title>
      <link>https://danielcompton.net/snippets/deciphering-irds-iit-itn-acronym</link>
      <pubDate>Tue, 26 Nov 2019 06:29:58 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/deciphering-irds-iit-itn-acronym</guid>
      <description>This tax season I got an email from IRD reminding me I had to file my return. This happens every year and is usually not a surprise. However this year, the returns were slightly different. They said:
 The 31 March 2019 IIT return for {person} is due 8 July 2019.
 and
 The 31 March 2019 ITN return for {company} is due 8 July 2019.
 I&amp;rsquo;d never heard of an IIT return or an ITN return.</description>
      <content:encoded><![CDATA[<p>This tax season I got an email from <a href="https://ird.govt.nz">IRD</a> reminding me I had to file my return. This happens every year and is usually not a surprise. However this year, the returns were slightly different. They said:</p>
<blockquote>
<p>The 31 March 2019 IIT return for {person} is due 8 July 2019.</p>
</blockquote>
<p>and</p>
<blockquote>
<p>The 31 March 2019 ITN return for {company} is due 8 July 2019.</p>
</blockquote>
<p>I&rsquo;d never heard of an IIT return or an ITN return. I searched around and couldn&rsquo;t get any results on Google or IRD&rsquo;s website search. However, my best guess at the acronyms is:</p>
<ul>
<li>IIT Return: IR3 - Individual Income Tax Return</li>
<li>ITN Return: IR4 - can’t think of a good explanation for this acronym</li>
</ul>
<p>I think IRD has renamed these in their recent <a href="https://www.newshub.co.nz/home/money/2019/04/inland-revenue-about-to-close-for-eight-days-to-instigate-1-6-billion-upgrade.html">system upgrades</a> and I suspect they&rsquo;ve renamed all of their returns. If you come across any other acronyms, let me know and I&rsquo;ll add them here to help others out.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Improving videoconferencing audio quality for remote workers</title>
      <link>https://danielcompton.net/improving-audio-quality-remote-working</link>
      <pubDate>Sat, 21 Sep 2019 16:18:16 +1300</pubDate>
      
      <guid>https://danielcompton.net/improving-audio-quality-remote-working</guid>
      <description>I&amp;rsquo;ve been working remotely for about five years full-time. Over that time I&amp;rsquo;ve talked with colleagues pretty much every work day, so being able to communicate clearly by audio has been crucial. Bad quality audio can quickly turn a good conversation into a frustrating one when you struggle to hear the speaker, or keep needing to ask them to repeat themselves. Videoconferencing is lower bandwidth than in-person communication; I&amp;rsquo;ve tried to get as good quality when videoconferencing so I can catch as much of what the other person is communicating.</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been working remotely for about five years full-time. Over that time I&rsquo;ve talked with colleagues pretty much every work day, so being able to communicate clearly by audio has been crucial. Bad quality audio can quickly turn a good conversation into a frustrating one when you struggle to hear the speaker, or keep needing to ask them to repeat themselves. Videoconferencing is lower bandwidth than in-person communication; I&rsquo;ve tried to get as good quality when videoconferencing so I can catch as much of what the other person is communicating.</p>
<p>I studied as a musician, and accumulated several pieces of audio gear and knowledge about working with audio which have been very useful for working remotely. A friend asked me for advice about getting some audio gear so I sent him an email. That turned into a post on our company wiki, and now I&rsquo;m posting it here publicly.</p>
<p>In my experience, for remote videoconferencing to work well, the following things are very beneficial:</p>
<ul>
<li>A fast, stable, and reliable internet connection</li>
<li>A quiet space free of distractions, and without too much echo</li>
<li>A space you&rsquo;re able to comfortably talk in during work hours</li>
<li>A good microphone close to your mouth and a set of headphones - Hearing yourself echo on someone else&rsquo;s call makes it hard to have a conversation.</li>
</ul>
<h3 id="improving-audio-quality-when-video-conferencing">Improving audio quality when video conferencing</h3>
<p>Here are some tips in rough order of importance for improving audio quality when videoconferencing. You can keep going down the list with diminishing returns of audio quality, stop whenever you and/or your team is happy with the quality you&rsquo;re getting.</p>
<ul>
<li>Get really close to the mic. It should be no more than an inch or two from your lips. Having a mic far away from your mouth makes everything else more difficult. A stand on a desk is better if it goes up to your face, having the mic at desk level will pick up lots of other noises and echoes.</li>
<li>Plug your computer in with Ethernet, or make sure you have really strong Wi-Fi. I always prefer to use a cable to remove a potential weak link.</li>
<li>Find a quiet room to talk in. If you can&rsquo;t find a quiet room, or you are on a call with more than 3 participants, I&rsquo;d recommend muting yourself when you&rsquo;re not talking.</li>
<li>Find a room that doesn’t echo. Clapping your hands will help you spot echo quickly. You especially want to avoid sitting in any spot where you hear ringing after a clap. Blankets, couches, other soft surfaces help deaden echo.</li>
<li>Get a decent mic. You should be able to get something fine for $70-$200 USD. Your first choice is whether to use an XLR mic + USB audio interface or a USB mic. An XLR mic will last a long time, especially in office use. My mic is about 10 years old now and still running fine. I’d personally steer clear of mics with a built in USB connection. Because they combine active electronics with the mic, the electronics may break or become obsolete even when the mic is still good. However, they don&rsquo;t require an extra audio interface which is one less moving part and they will still sound fine. Getting a USB mic wouldn’t be a ‘wrong’ decision, this comes down to your comfort with audio gear and how much stuff you want on your desk. Marco Arment has <a href="https://marco.org/podcasting-microphones">a good overview of mics</a>. Microphones have different <a href="https://www.shure.eu/musicians/discover/educational/polar-patterns">polar patterns</a> which control where they pick sound up from. If you want to be able to play meeting audio through speakers instead of wearing headphones, then look for a mic with a cardioid polar pattern to only pickup sound from the front of the mic. <a href="https://en.wikipedia.org/wiki/Microphone#Dynamic">Dynamic microphones</a> are often in a cardiod pattern. <a href="https://en.wikipedia.org/wiki/Microphone#Condenser">Condenser microphones</a> are often bidirectional and pick up equally well front and back, which will not work well when combined with speakers.</li>
<li>If you have an audio interface or USB mic, watch that you&rsquo;ve set the input levels correctly. If the gain is set too high, you will get terrible sounding digital clipping. If your interface has lights, watch them while talking loudly and make sure they don&rsquo;t turn red. You can also look at the input levels on your computer and make sure they aren&rsquo;t hitting the very top of the input scale as this may also indicate clipping. When in doubt, set the gain levels a little lower; video conferencing software usually has some gain leveling built-in to match you with the other speakers.</li>
<li>Get a pop filter, this takes the plosives out of your speech, a mic picks these up much more than a person does.</li>
<li>If you don’t get a USB mic you’ll need a separate audio interface. <a href="https://marco.org/podcasting-microphones#interfaces">https://marco.org/podcasting-microphones#interfaces</a> has some suggestions. Anything over $80 USD will be fine. You only need a 1 input audio interface, but often 2 input interfaces will be about the same price. Look for one with a USB connection, you don’t need Thunderbolt for single channel recording. USB-C and/or USB 3.0 would be ideal for longevity, but they cost a little bit more, and USB 2.0 is just fine for a single recording channel.</li>
<li>Once you&rsquo;ve got echo in your room under control, you can look at treating it with acoustic panels to &ldquo;deaden&rdquo; the room further. You can make these yourself, or purchase them from lots of places online. My office has a wooden floor, and drywall roof and walls which created lots of unpleasant echoes. The person I bought my foam panels off suggested I target ceiling/floor reflections first, I mounted four panels on my roof, and this was enough for me. Acoustic treatment is a whole science in itself and is very room dependendent, so do some research for your space.</li>
<li>If you&rsquo;re not able to avoid echoey or noisy room environments, then you can look at processing your sound with noise removal software. I have used <a href="https://www.rogueamoeba.com/soundsource">SoundSource</a> (disclosure: a friend made it) and <a href="https://www.plugin-alliance.com/en/products/spl_de-verb_plus.html">SPL De-Verb Plus</a> to remove room noise on the other end of calls which turned them from painful to tolerable. I also tried <a href="https://krisp.ai">Krisp</a> but didn&rsquo;t get great results from it. Your mileage may vary though.</li>
<li><a href="https://sixcolors.com/post/2016/11/a-podcast-studio-for-under-100/">https://sixcolors.com/post/2016/11/a-podcast-studio-for-under-100/</a> has more general gear tips.</li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Why Heart of Clojure was special</title>
      <link>https://danielcompton.net/heart-of-clojure</link>
      <pubDate>Sat, 24 Aug 2019 20:54:05 +1300</pubDate>
      
      <guid>https://danielcompton.net/heart-of-clojure</guid>
      <description>A few weeks ago I got to attend and speak at Heart of Clojure. I met lots of online friends in person for the first time, and made some new ones too. I&amp;rsquo;ve thought a lot about how to describe it since then, and every time I come back to the word special.
Others have also posted their thoughts on Heart of Clojure: Fork This Conference, The people’s conference, The hallway track conference, Community with lots of heart, and A courageous conference?</description>
      <content:encoded><![CDATA[<p>A few weeks ago I got to attend and speak at <a href="https://heartofclojure.eu">Heart of Clojure</a>. I met lots of online friends in person for the first time, and made some new ones too. I&rsquo;ve thought a lot about how to describe it since then, and every time I come back to the word special.</p>
<p>Others have also posted their thoughts on Heart of Clojure: <a href="https://lambdaisland.com/blog/2019-08-09-fork-this-conference">Fork This Conference</a>, <a href="http://manuel-uberti.github.io//clojure/2019/08/04/clojure-heart/">The people’s conference</a>, <a href="https://quanttype.net/posts/2019-08-12-hallway-track-conference.html">The hallway track conference</a>, <a href="http://www.saskialindner.com/blog/2019-08-16-community-with-heart/">Community with lots of heart</a>, and <a href="https://mallozup.github.io/posts/heartofclojure/">A courageous conference?</a>.</p>
<p>Here were some things that I think made Heart of Clojure so special. If you&rsquo;re running a conference, consider stealing some of these ideas.</p>
<ul>
<li>There was an <a href="https://activities.heartofclojure.eu">site</a> which listed activities around the event. Anyone could host an activity and others could join. Having it on a website meant everyone knew what was happening around the conference. I felt like this helped Heart of Clojure feel very welcoming to all of the conference goers, especially those who were less outgoing.</li>
<li>One of the nights I joined an activity for an adventurous dinner. People got split into groups of 6-8 with a reservation at a restaraunt in Leuven. This broke up friend groups and introduced me to a bunch of new people. The restaurant we went to had their own brewery, and I got to try the flavours of a beer soup, beer stew, and beer crème brûlée!</li>
<li>Yulia Startsev&rsquo;s talk <a href="https://www.youtube.com/watch?v=-IGViUlbemo&amp;feature=youtu.be">To loosen up, to put together</a> set the tone for the conference and captured the spirit of mixing technology and the humanities. Many of the talks and conversations referenced her talk throughout the rest of the event.</li>
<li>Leuven was a perfect town to have the conference. It was large enough to have a good nightlife, but small enough that you could walk between the conference venue, the bars, restauruants, and hotels in 10-15 minutes.</li>
<li>In the months before the conference, <a href="https://www.janstepien.com">Jan Stępień</a> paired up new speakers with more experienced speakers. This was my first conference talk, and I got paired up with Tiago Luchini. Tiago was a very experienced public speaker and gave me great feedback on my talk. Having to show someone my presentation helped me get it into shape well before the conference. I think Jan&rsquo;s work here contributed to the high quality of the talks at the conference.</li>
<li>I&rsquo;m not a vegeterian, but I really appreciated that all of the breakfast and lunches were vegeterian. I can imagine it would have made things very easy for vegeterians. The food was delicious and healthy tasting.</li>
<li>There was ample time left around the talks so that you didn&rsquo;t need to choose between the &lsquo;hallway track&rsquo; and the conference track. On the Saturday there was a siesta break between 12pm and 4pm. You could do one of the activities, take a nap, or just chat with others. I was a bit skeptical before the conference that this was going to be too long, but it worked out really well.</li>
<li>The lightning talks on Saturday broke up the afternoon and left space for serendipity to strike. Connie&rsquo;s <a href="https://www.youtube.com/watch?v=qyhjok21Y3o&amp;list=PLhYmIiHOMWoEgJEvgkmUe8D0agxy_T2vR&amp;index=16&amp;t=0s">talk</a> on waffles, Vim, and building her own language captured the audience.</li>
<li>On the Saturday evening after the conference ended, lots of people stayed behind to help pack down the auditorium. This made the job much easier.</li>
<li>There was a large contingent of people from Berlin, and they were all incredible. Berlin feels like it has a really vibrant community, one day I&rsquo;d like to visit it.</li>
</ul>
<p>Heart of Clojure was a very special event. I can&rsquo;t imagine how much work it was for Arne Brasseur, Martin Klepsch, and all of the other helpers before, during, and after the event but it paid off. Heart of Clojure felt like a very polished event, not something being put on for the first time. Thanks to everyone who organised, helped out, spoke, sponsored, and attended the conference. I hope there is another Heart of Clojure in the future, if you get a chance to go, I highly recommend it.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>What do :project/dev and :profiles/dev mean in a Leiningen project?</title>
      <link>https://danielcompton.net/snippets/what-do-project-dev-profiles-dev-mean-leiningen</link>
      <pubDate>Fri, 23 Aug 2019 07:23:48 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/what-do-project-dev-profiles-dev-mean-leiningen</guid>
      <description>A few years ago I came across a Leiningen project that defined profiles for :project/dev, :profiles/dev, :project/test, and :profiles/test. It took me a little bit of digging, but eventually I discovered what was happening. This is a convention that I think originated with James Reeves. I&amp;rsquo;m reposting my issue comment here, so it can be more accessible for searchers.
If you see profiles like this in a project.clj, here is what is happening:</description>
      <content:encoded><![CDATA[<p>A few years ago I came across a Leiningen project that defined profiles for <code>:project/dev</code>, <code>:profiles/dev</code>, <code>:project/test</code>, and <code>:profiles/test</code>. It took me a little bit of digging, but eventually I discovered what was happening. This is a convention that I think originated with <a href="https://github.com/weavejester">James Reeves</a>. I&rsquo;m reposting my <a href="https://github.com/weavejester/environ/issues/15#issuecomment-293144253">issue comment</a> here, so it can be more accessible for searchers.</p>
<p>If you see profiles like this in a <code>project.clj</code>, here is what is happening:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-clojure" data-lang="clojure"><span class="line"><span class="cl"><span class="ss">:dev</span>  <span class="p">[</span><span class="ss">:project/dev</span>  <span class="ss">:profiles/dev</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="ss">:test</span> <span class="p">[</span><span class="ss">:project/test</span> <span class="ss">:profiles/test</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="ss">:profiles/dev</span>  <span class="p">{}</span>
</span></span><span class="line"><span class="cl"><span class="ss">:profiles/test</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl"><span class="ss">:project/dev</span>  <span class="p">{</span> <span class="nv">...</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="ss">:project/test</span> <span class="p">{</span> <span class="nv">...</span> <span class="p">}</span>
</span></span></code></pre></div><p>Leiningen has a feature called <a href="https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md#composite-profiles">Composite Profiles</a>. On startup, if Leiningen sees a vector of keywords for a profile, it will lookup each keyword as a profile, and merge them together. For the <code>:dev</code> profile, Leiningen will merge the values of <code>:project/dev</code> and <code>:profiles/dev</code>.</p>
<p>If you want to add any custom settings or dependencies for your own use, you can place them into the <code>:profiles/dev</code> or <code>:profiles/test</code> in your <code>~/.lein/profiles.clj</code>. If either of these are set in the user&rsquo;s <code>profiles.clj</code>, they will override the empty <code>:profiles/dev</code> map specified in the <code>project.clj</code>. You need an empty map for <code>:profiles/dev {}</code> in the <code>project.clj</code>, because otherwise Leiningen will complain about a missing profile.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Playing Apple Music from multiple devices on the same Apple ID with a family subscription</title>
      <link>https://danielcompton.net/snippets/apple-music-same-apple-id-family-subscription</link>
      <pubDate>Thu, 27 Jun 2019 09:33:41 +1300</pubDate>
      
      <guid>https://danielcompton.net/snippets/apple-music-same-apple-id-family-subscription</guid>
      <description>When I first started using Apple Music I signed up for a solo subscription. During the day, I would listen to music on my Mac, and my family would listen to music on the iPad. If we listened at the same time, we would get the error:
 &amp;ldquo;Looks like you&amp;rsquo;re listening to music on another device.&amp;rdquo;
 Eventually this error became too annoying and I looked at upgrading to a Family subscription.</description>
      <content:encoded><![CDATA[<p>When I first started using Apple Music I signed up for a solo subscription. During the day, I would listen to music on my Mac, and my family would listen to music on the iPad. If we listened at the same time, we would get the error:</p>
<blockquote>
<p>&ldquo;Looks like you&rsquo;re listening to music on another device.&rdquo;</p>
</blockquote>
<p>Eventually this error became too annoying and I looked at upgrading to a Family subscription. The <a href="https://support.apple.com/en-us/HT205595">Apple Music Family subscription</a> allows up to six people that are part of the same <a href="https://www.apple.com/family-sharing/">Family Sharing</a> group to play music at the same time.</p>
<p>It sounded like this was probably what I needed, but in all of the documentation I read, it wasn&rsquo;t clear whether two devices that were logged into the <em>same</em> Apple ID would be able to play music at the same time. I talked with Apple&rsquo;s support team and it still was unclear so I went ahead and upgraded to try it for myself.</p>
<p>After upgrading I tested playing on multiple devices, and it worked fine. <strong>If you have an Apple Music Family subscription, you&rsquo;re able to play on multiple devices that are logged into the same Apple ID.</strong></p>
<p><strong>Update:</strong> More context from Benjamin Mayo on <a href="https://www.reddit.com/r/apple/comments/7xo8m6/apple_music_can_be_playing_simultaneously_on/dua2n01/">Reddit</a>:</p>
<blockquote>
<p>If you have the Apple Music family plan, multiple concurrent device streams increases to 6 rather than 1. HomePod and Apple TV usage do not count toward this limit.</p>
</blockquote>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
