Share something you learned (October)


#1

Rules:
1/ Reply with:

a sentence
a paragraph
some code
some notes
OR a link to a blog post, Github repo, or codepen
… describing something you learned, or featuring something you accomplished
2/ Share something regularly!

3/ Anyone can participate

4/ You can post new learnings throughout the month.


#2

It’s Hacktoberfest month and I tagged a couple of issues in some of my repos. The results have been mixed, but on the whole a positive experience, three merged contributions:

Back to the more mundane, I tripped myself up by defining infinity as math.MaxInt64, the largest value you can store in an int. This is fine until you do infinity + 1 and assume the result will be a large positive number. Overflow causes the result to be negative, resulting in strange behaviour.


#3

Today I learned about git rebase. I’m still not fully sure I understand when it should/shouldn’t be used. One of the rules seems to be “don’t rebase after raising a PR”. This seems to contradict with common practice which seems to be to ask people to “rebase onto master” after a PR has been raised.

Either way, I performed my first rebase today, next time it’ll be interactive.

This was a useful reference: Learn Git with Bitbucket Cloud


#4

I’m kind of dying to post something here so I will post prematurely for the day. I just finished Chapter 2 of Beginning Ruby by Peter Cooper. It offers a great overview of the Ruby language and its core concepts. A couple things I was happy to review include…

  1. The Kernel is like the core module of Ruby. Methods like puts could be called using Kernel.puts, but that’s generally unnecessary for that specific method. The Kernel object supplies many “built-in” utilities for use in our programs.

  2. Functions created outside a class definition in Ruby are typically referred to as subroutines.

  3. There is a distinction between parameters and arguments, and I do know what that distinction is, but it doesn’t really matter in practice and so I’m going to let that go. xD


#5

Today’s Ruby Learnings…

  1. I learned about p which when given an object prints obj.inspect and a newline to the output. inspect gives you a “textual representation of the object,” showing you information or how you might create the object yourself. This is apparently a great experimentation and debugging tool (and I can see why) even though it may not be very useful in production. Here is the documentation.

  2. In Ruby, case statements act a little differently than in C-like languages. The case will only match once, and won’t continue down a list of execution, and therefore no “break” is necessary.

  3. lambda can be used to store a code block within a variable, such as…

print_parameters_twice = lambda { |x| puts x * 2 }
print_parameters_twice.call("abc")
  => abcabc

#6

Today I was stuck on something regex-y involving carriage returns in a string, then eventually solved the bug with a non-regex solution (a simple while loop and splice).


#7

I learned how to run rubocop on the command line to lint my ruby files. Then I was able to lint a simple ruby file to learn how it worked, and I even learned that single quotes are prefered for simple strings like 'hello' that don’t require any fancy features like string interpolation "like #{this}", all because rubocop saw my code and told me so!


#8

I always fall back on https://regexr.com to get me through regex challenges. Have recently switched to https://regex101.com as it generates Go syntax as well.

I’d put basic regular expressions high up on the list of things everyone should learn.


#9

Today I did something different and spent the day at Google Cloud Next with a mentee. I tried to go anonymously (not on behalf of a company) but that fell apart. I managed to go to a couple of good sessions and, if you apply a brand filter to the event, my key lessons were:

  • istio experience will be important (I’m going to find tutorials)
  • metrics need more prominence in dev priorities
  • don’t bet against Serverless, the solutions may look complex but people are building some impressive stuff (cost scales to zero which is neat)
  • Java still dominates but silently so
  • There is a lot of vendor hype and we need to educate people in how to navigate it
  • developers are expected to be cloud native which is so much more than just deploying code in the cloud
  • There appears to be little in the way of a structured approach to gaining that experience

#10

Today I spent a bit of time playing with AWS X-Ray to try and get some visibility into what happens with each request to BuddyBot. This was more fiddly than I expected, but I’ve started to make some progress on tracing various function calls.

This shows the timing of the first message to BuddyBot following a deployment. This shows what I would expect in that the first message that gets sent takes slightly longer than the subsequent two messages (look at the queue spans). It also shows that most of the work is in the construction of the message for the admins channel as this requires making several calls to the Slack API.

The second message that gets flagged is a little quicker, but not much. The overall response time for this function is dominated by the calls out to the Slack API.


#11

Today I learned that if a function fails to process a message from an Amazon Queue (SQS), the default behaviour is to retry the same message over and over again. This happens at quite a pace, each attempt to reprocess the message racking up cost.

One approach to handle this is to set the message expiry (defaults to 4 days). Another is to set-up a dead-letter queue. This takes messages that have failed processing a configurable number of times and drops them on a separate queue, removing them from the normal data flow. It is possible to set-up alerts or monitoring on the dead-letter queue.

I had originally configured my BuddyBot functions to return success even if they were unable to process the messages in the hope that I could avoid handling errors properly. This turned out to be a mistake as for a brief period yesterday I deployed Mac OSX binaries instead of Linux binaries. This caused all message processing to fail and build up a fairly rapid retry storm. What I should have done was configure the queue correctly to handle failure scenarios appropriate for the context.

I made the following changes:

  • messages now time out after 10 minutes
  • failed messages will be sent to the dead-letter queue after 2 failed attempts

I’ve pushed the changes through to production so hopefully won’t be seeing anymore infinite retries. An interesting reminder in the essentials for using queues in a system.


#12

To see differences with git in staged files (“What did I just add, again?”) git diff --cached or git diff --staged.

To see differences between branches, git diff branch1 branch2.


#13

This has saved me many hours of manual copy-pasting


#14

Today I learned that OS X has an additional way of managing PATH variables. I was confused as to how there were non standard locations on my PATH so I went digging.

MacBook:~ bill$ cat /etc/paths
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

These look like the standard locations. But there is also a folder /etc/paths.d/ inside here you can set custom PATH locations. I have the following:

MacBook:~ bill$ cat /etc/paths.d/go
/usr/local/go/bin

I think I’m still going to make my customisations in .bash_profile but this is the first time I’ve come across the use of /etc/paths to manage the PATH variable.