We are using AWS Auora to manager our databases and I want to setup automatic rotation of database passwords. I start by storing them in AWS Secrets Manager. AWS actually releases publicly usable rotations for PostgreSQL, but I want to add the extra fields
host_ro so clients can directly pull both the read only Auora DNS and a full PostgreSQL connection string.
I decided to fork AWS’s example code and deploy my own Lambda.
I already have automation around Terraform/CircleCI and would prefer to continue to use them. I also would prefer to continue to use the pattern…
An unambiguous best practice for systems is to codify your infrastructure in a repeatable text format, rather than clicks in a UI. The common name for this is Infrastructure as Code. By far, the two most popular ways to do this, especially in AWS, are Terraform and CloudFormation.
I used Terraform for about 3 years at a startup before working for Twitch (AKA Amazon Jr) where I used Terraform very heavily before the company pushed hard to switch to all things Amazon, including CloudFormation. I tried very hard to develop best practices around both and used each for very complicated…
Table driven tests are a popular model for testing in Go and a clear improvement to traditional testing of one function per case. However, there’s an alternative style that can often be clearer than table driven tests that relies on function closures.
I’ll reference the example code on Dave Cheney’s post Prefer table driven tests for my examples.
The code we want to test is a function that splits strings.
The original way to test code like this was to create different test functions for each case. …
Histograms are an important part of metrics and monitoring. Unfortunately, it is computationally expensive to accurately calculate a histogram or quantile value. A workaround is to use an approximation and a great one to use is t-digest. Unfortunately again, there’s no such thing as an accurate approximation. There are various t-digest implementations in Go but they do things slightly differently and there’s no way to track how accurate their approximations are over time and no great way for consumers of quantile approximation libraries to benchmark them against each other.
Luckily, Go 1.13’s new ReportMetric API allows us to write traditional…
A recent vulnerability in the go-redis library allowed correctly configured clients to return the results of other redis commands in the event of redis failures. While all code is subject to bugs, this one could have been prevented if proper care was taken when creating and using interfaces.
Most clients reuse TCP connections between RPC calls to eliminate the delay of TCP connection overhead. TCP connections have both an input and output stream. Redis operates on a request/response pattern where commands are shared on the same socket by sending multiple requests and expecting multiple responses. Most of the time responses…
You have a constructor function that creates an object with a background goroutine. You want the object to garbage collect itself even if people don’t explicitly close it. This isn’t possible since since the background goroutine is always running and pointing to your created object.
Wrap the returned object and use a finalizer on the returned object to shut down the background goroutine.
Consider the Go statsd client go-statsd-client. The code to create a new buffered sender is below.
Start function spawns a goroutine to periodically flush the buffering sender.
Let’s now create and use a buffered…
You’ve written an object or class. It’s somewhat complex and you want to iterate ways to better abstract your code but are unsure how to start. There exists documentation about what good abstraction looks like, but no concrete iterative steps.
Being deep inside your own code can make you blind to obvious alternatives.
Assume you’re designing a video game with a space ship. Space ships are circles that have some amount of health they…
I commonly see bugs appending to slices in Go in a way that is not thread safe. A simple example is the unit tests below. This test has two goroutines append to the same slice. If you run this test with the
-race flag, it works just fine.
Now, let’s change the code just slightly to create the
x slice with more spare capacity. The only thing that changed was line 9.
If we run this test with the
-race flag, we will notice a race condition.
< go test -race .==================WARNING: DATA RACEWrite at…
I had an integration test that was very complex (most are, sadly) and took too long to start. I was able to diagnose why using new features of Go’s 1.10 trace tool. This post describes my workflow and what led me there.
The example code I’m using for this post is at https://github.com/cep21/trace-110. My integration test was a bit more complex, but generally had startup that was slow due to a single goroutine out of many that did lots of different things. In this example, takeIO is similar to the “startup” part of my integration test.
In general, when given two reasonable ways to do something, defer to the option that does not violate these rules. Bend these rules only with a strong explanation why.
Use git tags to version your library. Semantic versioning is a reasonable system. If you care enough to disagree with semantic versioning, then you’re not the target here :)