My current $JOB uses JIRA to manage issues and Github as the forge. I use Jujutsu and create remote branches using jj git push -c @. However, the Engineering Standard at work requires that the branch be named in an identifiable way. In practice, every branch is the slug of the commit description. After doing creating a jj bookmark manually a few times, I decided to automate it.| Herman J. Radtke III Blog
My dotfiles setup is very simple: I version control my $HOME directory using git. I ignore everything by default to avoid accidentally adding files I do not want to track. This avoids the need for any scripts or frameworks. Lately, I have been using Jujutsu for more personal projects and decided to use jj to manage my dotfiles.| Herman J. Radtke III
Ruby on Rails defined the ethos of the web development community for many years. I have observed people trying to replicate "Rails" in other languages with very mixed results. I consider Laravel, ASP.NET and Phoenix successful rails-like frameworks. Python already has Django. Sadly Java, Kotlin, Scala, Node.js, Go and Rust all lack a widely adopted rails-like experience.| Herman J. Radtke III Blog
Hyper supports sending HTTP/1.1 Chunked Trailer Fields as of v1.1.0. The http-body is now at v1.0 as well and uses frames to allow a stream to return data and trailers.| Herman J. Radtke III Blog
I was reading How fast is your shell? and it got me thinking about the difference types of speed developers prioritize. A lot of articles and advice focus on initial startup, which can be thought of as acceleration. We should also consider, what happens after we are done accelerating, how easy it is to maintain our velocity.| Herman J. Radtke III
I saw this statement in an accepted answer on Stack Overflow: Retrieving the value of an environment variable will incur a system call. source This answer surprised me as I did not think this was the case. There is an edit farther down that has links to other Stack Overflow posts saying get getenv does not make a syscall. Let us prove it ourselves.| Herman J. Radtke III
At work, I lead a team responsible for a Node.js service that serves a lot of GraphQL queries. We recently noticed some servers in the cluster were running much slower than others. We had used 0x in the past to profile Node.js services locally. In this case, we could not identify the problem locally and needed a solution to profile Node.js in production to identify the cause of the slowdown.| Herman J. Radtke III
Hyper is designed to support streaming bodies. The current version of axum, v0.6, supports streaming a response. If we want to include trailers (sometimes called "trailing headers") then we need to implement our own custom body.| Herman J. Radtke III Blog
I have been familiar with the concept of Command Query Responsibility Segregation (CQRS) for a while, but did not truly understand its practical application until I read The Log: What every software engineer should know about real-time data's unifying abstraction by Jay Kreps.| Herman J. Radtke III
A webhooks allow two applications to communicate events. It is relatively simple to get started using webhooks using HTTP and JSON. However, there a number of failure scenarios that developers should be aware of in order to make their webhook implementation robust.| Herman J. Radtke III
At work, I recently inherited a node service that was sending metrics to DataDog using the brightcove/hot-shots StatsD client. While investigating some issues with dns.lookup, I noticed other people had run into this same issue but there was no one sharing what a solution might look like.| Herman J. Radtke III
A company often has a landing page for first time visitors that is optimized for describing and educating that person on what product or service the company is offering. This page is usually not useful for people already familiar with the company. Ideally, a new user would see the marketing landing page and the returning user would see a more functional page. There are two common approaches to solving this problem that both have pitfalls. I want to explore a third option using Fastly's Comput...| Herman J. Radtke III
When writing tests, we do not want to hit the external API each time we run our tests. If we are coming from a dynamic language, such as Node.JS, we may want to a solution like fetch-mock which will patch the implementation of fetch at runtime. This is not practical in Rust. There are some attempts, like the hotpatch crate, but we will use a different strategy.| Herman J. Radtke III
Lucet is Fastly's native WebAssembly compiler and runtime. Using the Lucet runtime and Rust's wasm32-unknown-wasi target, we can create a WASM program that runs on the server.| Herman J. Radtke III
Lucet is Fastly's native WebAssembly compiler and runtime. I am a big fan of Rust, Fastly and WASM. Especially WASM on the server via WASI. I jumped right in and tried to get my own lucet program running, but the setup is a rather long process. My plan was to introduce lucet to some colleagues at my local Rust meetup. I am a huge fan of Rust, but the compile times are an issue. Spending 30 minutes on setup was a non-starter. I was excited when I saw that Fastly published a Docker container:| Herman J. Radtke III
I started writing mob, an multi-echo server using mio, in 2015. I coded mob into a mostly working state and then left it mostly alone, only updating it to work with the latest stable mio. Recently, I started looking at the code again and had the urge to improve it. In a previous post, I talked about managing the state of connections in mob. In this post, I will walk through what I did to remove the need to track connection state. I wanted to remove the state because the implementation require...| Herman J. Radtke III
I was looking to use the mspc queue that comes in the future crate in weldr. Weldr uses hyper (which uses tokio), so it makes sense to use tokio's Core as the executor. I did not have a good understanding of how this futures based mpsc queue worked. It has some subtle differences from the mpsc queue in the std library. I spent some time reading the documentation on https://tokio.rs/, a lot of source code and finally ended up writing a small example program. I have written a decent amount of i...| Herman J. Radtke III
Note: This project was originally named alacrity.| Herman J. Radtke III
If you have spent any amount of time learning Rust, you quickly become accustomed to Option and Result types. It is through these two core types that we make our programs reliable. My background is with C and dynamic languages. I found it easiest to use the match keyword when working with these types. There are also combinator functions like map and and_then which allow a set of computations to be chained together. I like to chain combinators together so error logic is separated from the main...| Herman J. Radtke III
This is an introduction to a parsing library called nom. The nom crate is written by Geoffrey Couprie, aka Geal, and is a remarkably complete and powerful library for building parsers. I recently did a lot of parsing of bytes on the wire for my carp library and it was a lot of work. I wish I had come across the nom library before I had done all of that.| Herman J. Radtke III
Note: This blog post does not work with rustc 1.19.0 or later due to a regression in rust 1.19.0. Use the following to set rust 1.18.0 up:| Herman J. Radtke III
In this post I am going to walk through the creation of a webservice in Rust. This is a Getting Started post that will serve as a foundation for future posts. The webservice will return a static json response to start. There are a few different options for web frameworks in Rust, but practically all of them use the underlying HTTP library called hyper. I am most familiar with nickel, so we will be using that. Once the code is complete, we will be creating a release build that is a completely ...| Herman J. Radtke III
When building a foreign function interface to C code, we will inevitably run into a struct that has a union. Rust has no built-in support for unions, so we must come up with a strategy on our own. A union is a type in C that stores different data types in the same memory location. There are a number of reasons why someone may want to choose a union, including: converting between binary representations of integers and floats, implementing pseudo-polymorphism and direct access to bits. I am goi...| Herman J. Radtke III
I was writing some Rust with a colleague when they asked me about the cases where Rust deferences types for us automatically. I said that Rust will automatically dereference pointers when making method calls, but otherwise there was no compiler magic. This conflicted with their experience with Rust and presented an example like this:| Herman J. Radtke III
I would wager most people who choose mio to solve their async IO problems are expecting more abstraction in the library. The oft repeated question of Why doesn't mio have callbacks? is evidence of this. In fact, it is a design goal of mio to add only as much abstraction necessary to provide a consistent API for the various OS async IO implementations. A consequence of this design decision is that there are subtle behavioral differences between platforms. It may be tempting to let mio manage t...| Herman J. Radtke III
Tested on Rust 1.3| Herman J. Radtke III
This post is going to walk through establishing a simple protocol when using mio.| Herman J. Radtke III
I use a MacBook Air as my main laptop. I have been using Vagrant to test rust programs on linux. This feels a little heavy to me though as I have to create a Vagrant machine for each repository. The up and halt phases of the Vagrant box are a little slow and each machine eats away at my available hard drive space. I do not need an entire virutalized operating system, just a place to test my programs. This seems like a good use case for Docker.| Herman J. Radtke III
I am going to walk through the creation of a PHP extension that works with a Rust library. I have a working example here. I also created a PHP extension for my Rust selecta port. Both examples use the same foreign function interface (ffi). I made sure to pick an example that uses strings because strings add additional complexity that numbers do not introduce.| Herman J. Radtke III
This is my second blog post in a series about async IO. You may want to read first blog post if you are not familar with mio or epoll/kqueue implementations.| Herman J. Radtke III
I really like _with style functions that accept a FnOnce callback. The scoping rules work out really well when using these functions. I was working with the slab crate recently and used the Slab#insert_with function. This function takes a callback where an object is supposed to be allocated before being inserted into the slab. The function returns an Option type. I was trying to figure out to drop the newly created object if the function returned None (meaning the insertion failed). After a f...| Herman J. Radtke III
I needed async IO for a Rust project I was working on. My server needs to read some bytes from a client and then send those bytes back to all registered clients. I decided to use mio, the Rust async IO library, to build a server. All the examples I found showcased reading from a socket and then writing back to that same socket. Also, many of the examples had caveats about unhandled edge cases and used a lot of unwrap. Over the next three posts, I am going to walk through everything I learned ...| Herman J. Radtke III
In Rust, you quickly learn that vector and slice types are not iterable themselves. Depending on which tutorial or example you see first, you call .iter() or .into_iter(). If you do not realize both of these functions exist or that they do different things, you may find yourself fighting with the compiler to get your code to work. Let us take a journey through the world of iterators and figure out the differences between iter() and into_iter() in Rust.| Herman J. Radtke III
The rules around references and borrowing in Rust are fairly straight-forward. Given an owned variable, we are allowed to have as many immutable references to that variable as we want. Rust defaults to immutability, so even functions like trim are written in such a way that the result is a reference to the original string:| Herman J. Radtke III
Russian Translation| Herman J. Radtke III
Russian Translation| Herman J. Radtke III
I listened to the Changelog podcast on Rust recently and loved the remark about enabling web developers to get into systems programming. I have been thinking about the way we design code in the web world versus the way we design code in Rust. In the web world, we often use a hash/dict/map to hide hard-coded values behind a nicer interface. Consider an example where you would want to write a function to create the escape sequence for colors in a TTY terminal. You might write something like thi...| Herman J. Radtke III
As soon as I started writing implementations for structs in Rust I started fighting with the compiler. Writing what seemed like a simple getter function caused me a lot of frustration. The self parameter can really throw me off in Rust. I reflexively treat it like this in C++, which has no concept of & or &mut. I do this because I think of impl Person as defining methods on a class as I would do in C++. This can be really misleading.| Herman J. Radtke III
I was writing some code in Rust and wanted to get the size of my terminal. This is currently not implemented in Rust though. I decided to read up on The Foreign Function Interface Guide to figure out how to do it myself. The Foreign Function Interface (FFI) is how Rust code interfaces with native C code. I also found a great Stack Overflow post that showed me how to write native C to get the terminal size. Based on my research, I needed to do three things in order to get my terminal size:| Herman J. Radtke III
The nickel.rs Web Application Framework for Rust is inspired by the popular node.js express framework. The stated goal of the nickel.rs framework is to show people that it can be easy to write web servers using a sytems language like Rust. I have been using the framework to create hypermredia examples using my hal-rs library.| Herman J. Radtke III
My notes from Emberconf.| Herman J. Radtke III
The Mink extension to behat makes it really easy to test the contents of a page. I can use the assertElementContainsText feature to assert that some text exists within a certain element:| Herman J. Radtke III
This blog post is in response to the discussion started by the tweet below:| Herman J. Radtke III
Dave Ramsey has a famous quote: "The only ship that won't sail is a partnership" (source). I believe the context is in regards to two friends starting a business together. I recently heard this together and wondered how many succesful startups were partnerships.| Herman J. Radtke III
The principle of Don't Repeat Yourself (DRY) is more than just grouping common code together. When trying to apply the DRY principle, it is easy to start making a mess of a class interface. I recently had to write some code to generate Flickr image URLs from an API response. I needed to generate two types of URLs: a thumbnail and a normal image. Here is one version of code reuse:| Herman J. Radtke III
I think the Object Oriented (OO) principle of Don't Repeat Yourself (DRY) is often misunderstood. In particular, the word "repeat" is troublesome. It has nothing to do with minimizing the amount of code you write. It is also not about merging similar methods together into a super-method. The DRY principle is about preserving a single source of truth in a system. When a there are multiple sources of truth in a system we have to write more code to manually keep all the truths in sync with each ...| Herman J. Radtke III
I have always wondered why the MySQL datetime type only has second precision. Developers will happily put a datetime type in a unique index though. They justify that decision by telling themselves, "Two rows inserted within the same second will never happen". That same developer just got done reading the latest MongoDB article that benchmarked a gazillion inserts a second. They tweeted it too. I suggest that we use a bigint and store a timestamp with greater precision if we are to use it as a...| Herman J. Radtke III
I think the SQL is Agile post by Armin Ronacher is a little short sighted. Disclaimer: I rarely use MongoDB or other NoSQL offerings. There are plenty of good reasons to use MongoDB in production. Many people and companies have shown it to be successful. More importantly we should not be afraid of trying out new things, especially for side projects. We should be cautious of trying new things for important projects. By "important", I mean those projects that need to be reliable or where there ...| Herman J. Radtke III
This blog post is inspired by Douglas Crockford's book JavaScript: The Good Parts.| Herman J. Radtke III