On The Unsuitability of The Candidates

The UK faces the prospect of a new Prime Minister selected from a list that is packed with entirely unsuitable candidates:

CandidateReason
Boris JohnsonMr Johnson is facing a private prosecution
over claims he deliberately lied during
the Referendum campaign.

 Mr Johnson is reported to
have replied: “Fuck business.”
Michael GoveI think the people in this country have
had enough of experts.
Stabbed Boris Johnson in the front during the previous
leadership campaign.
Jeremy HuntMessed up security contracts at the Olympics.
Hated by the NHS.
Can’t remember which country his wife is from.
Andrea Leadsom“Being a mother gives me an edge on May”
Withdrew from ballot versus May
Ester McVeyMisled parliament over the new Universal Credit 
scheme
Dominic RaabSurprised that Britain is an island

There are other candidates (and more will appear over the next few days).

Handling a Headless CMS

This is a general outline for using a headless CMS (such as Contentful).

There are other ways to do this but this is fast given a suitable size delta, and will recover from failure better than webhooks:

This has the headless CMS being polled by a Static Site Generator.

The Static Site Generator knows the current state of the site and only regenerates changed items. This may require it to keep a map of dependencies between nodes. Sometimes you may need to go 3 or 4 levels deep. Store the output in S3. Serve the website from S3, which allows some customisation of the data. Use a CDN to back the website to reduce load. Purge the pages of the site that have changed after they have been written.

We managed to use a single Heroku node for the SSG and another one for the webserver.

Groovy Closures

Some of my team have been impressed with Groovy’s support for closures:

Here is a simple closure:

def time(String message, Closure body) {
  def start = Instant.now()
  def result = body.call()
  def finish = Instant.now()
  Duration duration = Duration.between(start, finish)
  log.info("$message took $duration")
  result
}

This would allow you to go from:

def value = complexDatabaseQuery(1, 2, 3)

to

def msg = "Complex query 1, 2, 3"
def value = time(msg, {complexDatabaseQuery(1, 2, 3)})

This provides a simple decorating wrapper that records the time that the database call took without making the code less readable.

This could be made more sophisticated using:

def warnSlow(String message, def max_duration_in_seconds = 5, Closure body) {
def start = Instant.now()
def result = body.call()
def finish = Instant.now()
Duration duration = Duration.between(start, finish)
if (duration.getSeconds() > max_duration_in_seconds) {
warn “$message is slow, it took $duration which is longer than the threshold of $max_duration_in_seconds”
}
result
}

This permits simple performance checks to be added to code with minimal disruption.

Replacing a MongoDB with a Lambda

The project that I currently work on uses a number of microservices. Several of these microservices use MongoDB. The platform provider that we are using to host these databases (compose.io) has announced that they are going to stop supporting Mongo in about two months time.

This has resulted in a thorough investigation of the mongo databases that we are using.

Several of the services use the following architecture:

This has three instances of an application that periodically poll a website before performing sending the result to rabbitmq. They use the mongodb as a lock so that only one of the three perform the operation.

The alternative design was to add an external scheduler to trigger the nodes. The load balancer would pick one of the nodes to perform the work. One of my colleagues pointed out that we could use a lambda to do this. Lambdas are (typically) javascript functions that are cloud hosted.

It it is possible to deploy a lambda with a schedule of how frequently it should be invoked, either with a given frequency or via a CRON-like specification. The lambdas invoke methods on the nodes that asynchronously trigger the process.

Here is a diagram of the replacement:

This has allowed us to replace three MongoDB’s in each of four environments with a much simpler lambda function.

In addition we have been able to remove the mongodb database driver and the internal cron scheduling components. This greatly simplifies these services. There is now less to maintain (less PR’s from dependabot). It is also far easier to test code that is called from an endpoint than one from a scheduled event.

We do still need to replace the remaining MongoDB’s which contain real data but this is a much more manageable job.

We also learned that AWS still uses Node 8 LTS for Lambda.

This is a great starting point for serverless functions.

Announcing About

Last weekend I wrote and released the Elixir package called “about”.

This adds About topics to the iex environment.

It is installed in the usual way:

Add {:about, "~> 0.0.1"} to your deps list in mix.exs

Run mix deps.get

Run iex -S mix

You can now use help topics like:

iex(1)> h About.pipeline

I am looking for suggestions/contributions to the project.

It’s hosted on https://github.com/chriseyre2000/about and available on hex.pm and hexdocs.

Designing Elixir Systems With OTP – Part Three

The B2 edition of this book is out. The new chapter is dedicated to Supervisors. These are correctly described as Lifecycle components.

This is the first time that I have seen the new DynamicSupervisors being used.

Minor note the parameter in

Lifecycle/lib/mastery/boundary/quiz_session.ex for select_session/1 has changed to name from session.

Similarly for answer_question/2

The code samples now clearly state where the code is to be added.

There was a minor typo and some missing code that breaks the final iex session.

Current code can be found at: https://github.com:chriseyre2000/designing_elixir

Elixir iex documentation : C

This is the third part of an exploration of the Elixir base libraries

Here is an introduction to what you get out of the box with iex:

LetterModuleDescription
CCalendarDate, time and calendar functions
CaseClauseErrorThis is a struct used for errors.
CodeUtilities for managing code compilation, code
evaluation, and code loading.
CollectableProtocol to traverse data structures.
Used for putting data into things.
CompileErrorThis is a struct used for errors.
CondClauseErrorThis is a struct used for errors.

Doing the same with :c gives the erlang modules

LetterModuleDescription
ccErlang compiler.
calendarDate, time and calendar functions
cerlCore Erlang abstract syntax trees.
cerl_clausesUtility functions for Core Erlang
case/receive clauses.
cerl_inline???
cerl_setsSet functions.
cerl_treesBasic functions on Core Erlang abstract syntax trees.
codeUtilities for managing code compilation, code
evaluation, and code loading.
code_serverProcess used for live code reloading
compileErlang compiler interface
core_lib???
core_lint
core_parse
core_pp
core_scan
countersLibrary of mutable counters with no locking.

Elixir iex documentation : B

This is the second part of an exploration of the Elixir base libraries

Here is an introduction to what you get out of the box with iex:

LetterModuleDescription
BBadArityErrorThis is a struct used for errors.
BadBooleanErrorThis is a struct used for errors.
BadFunctionErrorThis is a struct used for errors.
BadMapErrorThis is a struct used for errors.
BadStructErrorThis is a struct used for errors.
BaseEncoding and decoding functions
for 16, 32, 64, hex, url
BehaviourMechanism for handling behaviours
(deprecated)
BitwisePerforms bit calculations.

Doing the same with :b gives the erlang modules

LetterModuleDescription
bbase64Base 64 encode and decode
beam_aUsed after code generation before
optimisation. Normalises the code.
beam_asmAssembler for the beam
beam_blockErlang compiler
beam_bsErlang compiler
beam_bsmErlang compiler
beam_cleanErlang compiler
beam_deadErlang compiler
beam_dictErlang compiler
beam_disamErlang compiler
beam_exceptErlang compiler
beam_flattenErlang compiler
beam_jumpErlang compiler
beam_libErlang compiler
beam_listingErlang compiler
beam_opcodesErlang compiler
beam_peepErlang compiler
beam_receiveErlang compiler
beam_recordErlang compiler
beam_reorderErlang compiler
beam_splitErlang compiler
beam_trimErlang compiler
beam_typeErlang compiler
beam_utilsErlang compiler
beam_validatorErlang compiler
beam_zErlang compiler
binaryHandles binary data.
This is the Erlang string type