From the developer: What’s new in WombatOAM 3.0.0?

A lot has changed since the last major release of WombatOAM. There were several minor releases in the past year and below you’ll find a non-comprehensive list of the main features and improvements introduced in this time.

Before you go any further, you should know that you can test all of this out today with a 45 day free trial for WombatOAM 3.0.0beta.

What is WombatOAM?

WombatOAM is an on premises monitoring tool to collect metrics in your Erlang- and Elixir-based applications. It provides historical data and live visibility into your processes’ measurements and logs, continuously checks if these are normal, and raises alarms early to prevent downtime or faulty behaviour.

WombatOAM contains an interactive Web Dashboard where you can view metrics and manage the associated nodes, and features several integrations to send the data elsewhere.

A Better Dashboard

WombatOAM went through a big redesign, where it’s finally reached its current, much improved version. We worked hard on the Web Dashboard making the user interface more intuitive for developers and support engineers as well. The whole look and feel changed giving it a more modern appearance.



WombatOAM’s Frontpage shows the most important Erlang metrics


WombatOAM has several Tools which can help diagnose issues with Erlang nodes or clusters directly from the Web Dashboard. The built-in Etop and ETS Table viewer also got a facelift.

Now the Node manager tools are moved to the Node Homepage, so tools like Garbage Collector Runner and Node Configurator are accessible right from the Node details. This change was made to make sure you have all the available tools controlling the node and its parameters in one place.

Network partitions can and will happen in distributed systems. When a node using Mnesia is separated from the other nodes in the cluster the databases’ contents will diverge. WombatOAM can now detect partitioned Mnesia clusters and raises alarms, we’ve also included a tool to fix the issue by a click of a button.



Some of the Tools are available on the Node homepage to help investigate issues


To be able to quickly get up and running after adding a node, we introduced Product Based Frontpages supporting Riak, RabbitMQ, Phoenix, Erlang, and Elixir. This means that WombatOAM will automatically generate a frontpage with graphs of the most important metrics related to the application. Of course you still have the ability to set up custom graphs and customise the frontpage.

Improved Elixir and Phoenix support

Elixir’s popularity is continuing to rise so we added numerous features which makes Elixir users’ lives easier. WombatOAM now supports multiple metrics from the Phoenix Web Framework, it collects information related to requests, such as average response time, request count, errors, etc. It also logs query runtimes and other metrics from Ecto and can collect logs from Elixir’s Logger.



WombatOAM displaying Phoenix and Cowboy metrics


We’ve added a few other metrics and related alarms as well, like Inode Count, which will notify if a mount is running out of available Inodes. WombatOAM is now better at inspecting RabbitMQ queues and can provide a lot of useful information, including message counts in RAM or on disk, unacknowledged message numbers, etc, for each queue. We also developed a SumoDB plugin which can log the time taken by the database actions (for example insert, update, delete) and provides a viewer for the data stored in the db as well. We introduced a new graph type, you can now set up gauges to display metrics.

Smarter Alarm Handling

WombatOAM’s alarms can direct your attention towards serious issues in the system thus preventing outages. These problems can range from high CPU load or high memory usage to Erlang VM specific issues, limits imposed by the emulator like atom limits, and application misconfigurations. They can help you investigating scaling issues and application runtime issues as well.

Tags were introduced, giving you the options for defining alarm’s target. All built-in alarms are separated into two groups, dev and ops. This makes it possible to notify separate people when an alarm is raised, and on the Web Dashboard you can set default tags for yourself, making it easier to see the issues applying to you. You can specify custom tags as well giving you control over the alarm groups.

You can now create alarms to notify someone on specific conditions when you set up your application to push log entries or other custom notifications to WombatOAM.

New Integrations

We added a few new integrations as well. As WombatOAM is not primarily focused on storing the metrics for a long time, it’s better to send those to services which are more prepared for that use case. On top of the previous integrations like Graphite, now you can send the metrics and logs to Logstash, AppDynamics, or Datadog. Even better, now you get notified immediately by sending alarms to Slack.

Future

WombatOAM 3.0.0 contains many more features and improvements than these listed above, we hope you’ll find them useful.

We still have a lot of ideas and are open to your feedback as well, please send us an email if you have comments on WombatOAM’s new version or you would like to see something implemented or improved. We hope you will love WombatOAM as much as we loved working on it, we are looking forward to WombatOAM 4.0.



Get a 45 day free trial for WombatOAM 3.0.0beta now!

Permalink

This Week In Erlang Oct 20

Welcome to another “This week in Erlang” newsletter!

Articles and Blog posts

Library Updates

OTP Updates

Siri Hansen open an interesting PR this week, to optimize how supervisors store their children data. This is most interesting if you ever need to run a large number of children as the new design is more memory compact and faster:

https://github.com/erlang/otp/pull/1602

Library of the week

I’m so glad I asked for a suggestion for this week on the Erlanger Slack. The reason being Fred introduced me to this amazing library. docsh created by Radosław Szymczyszyn (@erszcz), allows you to search Erlang/OTP docs right from the REPL. I’m sure having this installed will boost your efficiency :) Check it out:

https://github.com/erszcz/docsh

Events and Meetups

Employment

Announcements

Permalink

Pattern Matching in Elixir: Five Things to Remember

Elixir has been getting a lot of attention these days for being such a powerful language. It is highly-concurrent, fault-tolerant, and scalable.

When beginning to learn Elixir, you quickly come upon the term Pattern Matching.
What is Pattern Matching and more importantly what do you need to know?

1) It’s Not Assignment

In Elixir there is no real concept of assignment as you might be used to in other programming languages (Ruby, Javascript, Java, etc.). The “=” is a match operator. It allows us to compare the right side of an expression(known as the “pattern”) against the left side (known as the “term”) to see if they “match”.

Let’s take a look in more detail:

If the examples above were from an imperative language, we could assume that we have a variable on the left and the value on the right and an assignment operator “=.”

Given there is no assignment operator – what is happening?

When a new variable is being initialized(as seen above), the following happens:

  • The pattern on the right is evaluated (either “1” or “2”)
  • The resulting value is matched against the left-side term (“a” or “b”)
  • The variables on the left-hand side is initialized and bound to the value on the right-hand side.

In Elixir we would say “a” is bound to “1” and “b” is bound to “2”.

Let’s take a look at another example:

What is happening here? This does not look like something we would normally see in an imperative language.

Looking above we know that “b” has a value of “2”. The pattern on our right (the value of b) is being matched to the term on the left-hand side “2”.

The pattern matches and so the value on the right-hand side is returned.

Yet what happens when the pattern doesn’t match?

Remember that “a” has a value of “1”. As the pattern is evaluated, the pattern on the right does not match the term left and we receive an error.

2) Variables are Bound and Rebound

As mentioned, in Elixir we cannot assign values to variables. However, we can bind a variable to a value. If a variable already has a value, we can rebind that value.

Here “b” is being rebound from a value of “2” to a value of “3″:

The last thing to note about variables is the pin(^) operator:

When using the pin operator we are matching against the contents of the variable rather than binding the variable to the term on the right-hand side.

In this case the pattern 4 does not match the term 3 (the value of the pinned variable ^b), we receive an error.

3) Matching in data structures.

Using pattern matching in data structures is common in Elixir:

In the example below, the untyped data structure with the curly braces and containing comma-delimited elements is called a Tuple. Tuples are generally used to group a fixed number of elements.

This example assumes that the right-hand pattern is a tuple with two elements. Notice that the left hand-term is a tuple with two variables.

The element with the value “:ok” is an atom. Atoms are literal constants in Elixir. They look like symbols for those familiar with Ruby or C/C++.

What do we imagine will happen above with what we know about pattern matching?

We know that Elixir is going to match the pattern on the right to the term on the left.
In this case, the variables “result” and “value” will each be bound to their respective values on the right-hand side.

As we can see above, once the variables are bound, the pattern on the right is the return value.

If we set the first element in the term as an atom “:ok” and leave the second item, we can see that the variable “value” is bound to the respective element in the right-hand term.

What happens when the pattern does not match?

Above we can see that the first element in the tuple on the right-hand side does not match the first element in the tuple on the left – and so we receive an error.

It is a common pattern in Elixir for functions to return either { :ok, result } or { :error, reason }.

4) Multi-Clause Functions

A multi-clause function is a function that has multiple definitions with the same arity (number of arguments). Pattern matching is very powerful when used in combination with multi-clause functions.

Let’s create a “Greeter” module. In Elixir we use modules to group together functions:

We have two definitions for the function “hello”. Notice that each function accepts a different argument. The function that is executed is the one where the arguments that are passed in match the pattern of the arguments in that function’s signature.

What are the benefits here?
Pattern matching forces us to be very intentional about our data, since each function takes a specific signature.
It also allows for more atomic code – the ability to break functions into small pieces.
It prevents the need for complicated conditional logic.

5) Recursion

In Elixir we think about looping differently than we might in imperative languages like Ruby or Javascript. Looping constructs like ‘while’ or ‘do while’ are not provided. The way we accomplish looping in Elixir is through recursion.

Let’s take a look at recursion using lists.

This data structure below that looks like what might be an array in Ruby or Javascript is actually a singly linked list. Elixir allows you to reference the first element in the list as the “head” and the rest of the list as the “tail”.

Here we have the “Calculator” module:

We have two function with the same arity. One returns a list with each item in the list multiplied by 2. The other returns an empty list.

When we call our Calculator function with a list, notice that we multiply the head of the list by 2. Then we call the function “multiply_by_2” on the tail of the list. It will continue iterating through each item in the list until the list is empty.

Once the list is empty, that empty list will match against the function that takes an empty list as an argument. That function will execute and the recursion will stop. This type of recursion is called “tail recursion” and is often how we iterate over lists in Elixir.

And that’s it – the basics of pattern matching in Elixir.

In summary:

  1. It’s not assignment
  2. Variables are bound and rebound
  3. Pattern matching in data structures is common
  4. Use pattern matching with multi-clause functions
  5. Recursion allows for looping.

Permalink

From the developer: What’s new in WombatOAM 3.0?

A lot has changed since the last major release of WombatOAM. There were several minor releases in the past year and below you’ll find a non-comprehensive list of the main features and improvements introduced in this time.

Before you go any further, you should know that you can test all of this out today with a 45 day free trial for WombatOAM 3.0.0beta.

What is WombatOAM?

WombatOAM is an on premises monitoring tool to collect metrics in your Erlang- and Elixir-based applications. It provides historical data and live visibility into your processes’ measurements and logs, continuously checks if these are normal, and raises alarms early to prevent downtime or faulty behaviour.

WombatOAM contains an interactive Web Dashboard where you can view metrics and manage the associated nodes, and features several integrations to send the data elsewhere.

A Better Dashboard

WombatOAM went through a big redesign, where it’s finally reached its current, much improved version. We worked hard on the Web Dashboard making the user interface more intuitive for developers and support engineers as well. The whole look and feel changed giving it a more modern appearance.



WombatOAM’s Frontpage shows the most important Erlang metrics


WombatOAM has several Tools which can help diagnose issues with Erlang nodes or clusters directly from the Web Dashboard. The built-in Etop and ETS Table viewer also got a facelift.

Now the Node manager tools are moved to the Node Homepage, so tools like Garbage Collector Runner and Node Configurator are accessible right from the Node details. This change was made to make sure you have all the available tools controlling the node and its parameters in one place.

Network partitions can and will happen in distributed systems. When a node using Mnesia is separated from the other nodes in the cluster the databases’ contents will diverge. WombatOAM can now detect partitioned Mnesia clusters and raises alarms, we’ve also included a tool to fix the issue by a click of a button.



Some of the Tools are available on the Node homepage to help investigate issues


To be able to quickly get up and running after adding a node, we introduced Product Based Frontpages supporting Riak, RabbitMQ, Phoenix, Erlang, and Elixir. This means that WombatOAM will automatically generate a frontpage with graphs of the most important metrics related to the application. Of course you still have the ability to set up custom graphs and customise the frontpage.

Improved Elixir and Phoenix support

Elixir’s popularity is continuing to rise so we added numerous features which makes Elixir users’ lives easier. WombatOAM now supports multiple metrics from the Phoenix Web Framework, it collects information related to requests, such as average response time, request count, errors, etc. It also logs query runtimes and other metrics from Ecto and can collect logs from Elixir’s Logger.



WombatOAM displaying Phoenix and Cowboy metrics


We’ve added a few other metrics and related alarms as well, like Inode Count, which will notify if a mount is running out of available Inodes. WombatOAM is now better at inspecting RabbitMQ queues and can provide a lot of useful information, including message counts in RAM or on disk, unacknowledged message numbers, etc, for each queue. We also developed a SumoDB plugin which can log the time taken by the database actions (for example insert, update, delete) and provides a viewer for the data stored in the db as well. We introduced a new graph type, you can now set up gauges to display metrics.

Smarter Alarm Handling

WombatOAM’s alarms can direct your attention towards serious issues in the system thus preventing outages. These problems can range from high CPU load or high memory usage to Erlang VM specific issues, limits imposed by the emulator like atom limits, and application misconfigurations. They can help you investigating scaling issues and application runtime issues as well.

Tags were introduced, giving you the options for defining alarm’s target. All built-in alarms are separated into two groups, dev and ops. This makes it possible to notify separate people when an alarm is raised, and on the Web Dashboard you can set default tags for yourself, making it easier to see the issues applying to you. You can specify custom tags as well giving you control over the alarm groups.

You can now create alarms to notify someone on specific conditions when you set up your application to push log entries or other custom notifications to WombatOAM.

New Integrations

We added a few new integrations as well. As WombatOAM is not primarily focused on storing the metrics for a long time, it’s better to send those to services which are more prepared for that use case. On top of the previous integrations like Graphite, now you can send the metrics and logs to Logstash, AppDynamics, or Datadog. Even better, now you get notified immediately by sending alarms to Slack.

Future

WombatOAM 3.0 contains many more features and improvements than these listed above, we hope you’ll find them useful.

We still have a lot of ideas and are open to your feedback as well, please send us an email if you have comments on WombatOAM’s new version or you would like to see something implemented or improved. We hope you will love WombatOAM as much as we loved working on it, we are looking forward to WombatOAM 4.0.



Get a 45 day free trial for WombatOAM 3.0.0beta now!

Permalink

Why DockYard Builds with Ember.js

DockYard builds modern web applications for all platforms. This article is intended to provide an explanation as to why DockYard uses Ember.js as our frontend framework to do this.

Modern Web Apps

One characteristic of modern web apps is that they “feel” like traditional mobile and desktop applications. They’re fast, fluid, and intuitive. This is made possible by Single Page Application (SPA) architecture, which loads a single HTML page and dynamically updates it via JavaScript (JS) and HTML5 APIs. You also need a backend framework that can accommodate the many requests that come with these rich UIs, which is why we use Elixir and Phoenix on the backend (a topic for another article). Updating page content without requiring a page refresh was initially achieved via plain old Ajax calls, typically using jQuery; however, this did not provide a framework for organizing that JS code. It was a mess and typically resulted in something developers called “jQuery soup” – an unmaintainable collage of JS code spread throughout the application.

In 2017, two of the predominant JavaScript frameworks for building Single Page Applications are Angular 2 and Ember.js. People often include React.js, as well; however, React.js is a library for building user interfaces, rather than a framework (it can be bundled with other libraries for teams interested in building and maintaining their own web framework).

Ember.js’s Origin Begins with Apple

As early as 2008, Apple was trying to solve the problem of building a robust, JS framework with a project known as SproutCore. A workshop at their Worldwide Developer Conference (WWDC) that year read:

SproutCore is an open source, platform-independent, Cocoa-inspired JavaScript framework for creating web applications that look and feel like Desktop applications. Learn how to combine SproutCore with HTML5’s standard offline data storage technologies to deliver a first-class user experience and exceptional performance in your web application. Apple’s open secret: SproutCore is Cocoa for the Web

To unpack that a bit: Cocoa is the API for the Macintosh operating system (now called “macOS”); Cocoa applications are now built using Apple’s Swift programming language.

Essentially, before Apple was raking in $28B per year via the App Store, they were trying to build Progressive Web Apps. Steve Jobs’s original vision for the iPhone supports this with:

The full Safari engine is inside of iPhone. And so, you can write amazing Web 2.0 and Ajax apps that look exactly and behave exactly like apps on the iPhone. And these apps can integrate perfectly with iPhone services. They can make a call, they can send an email, they can look up a location on Google Maps. And guess what? There’s no SDK that you need! You’ve got everything you need if you know how to write apps using the most modern web standards to write amazing apps for the iPhone today. So developers, we think we’ve got a very sweet story for you. You can begin building your iPhone apps today. Jobs’s original vision for the iPhone: No third-party native apps

Fast-forwarding a bit – SproutCore 2.0 became Ember.js under the guidance of former Apple developer Tom Dale and Ruby on Rails core team member Yehuda Katz. The project combined Apple’s best practice application architecture with the developer-friendly ergonomics of Ruby on Rails.

DockYard Adopts Ember.js

DockYard got on the Ember.js train early, before it reached v1.0.0. We knew that it was the right tool for the jobs we wanted to be working on (ambitious web apps), so we never hedged our bets on Ember.js by picking up competing frameworks. We’ve organized the Boston Ember.js Group since 2013 and hosted Wicked Good Ember in 2014, 2015, and 2016.

Wicked Good Ember 2016

We’ve been the top sponsor for EmberConf (2015) and have sponsored the work of Igor Terzic on Ember Data.

This specialist vs. generalist approach to frontend development has left a lot of React.js, Angular 1, and Angular 2 work on the table over the years, but it has also meant:

  1. We’ve been building the applications we want to build for the clients we want to work with.
  2. We’ve been able to develop our Ember.js expertise beyond that of other, generalist consultancies.
  3. It has attracted the best talent to DockYard.

In short, we’ve interpreted “the right tool for the right job” to mean: find the right job.

Thankfully, Ember.js is the right tool for a lot of projects.

The Right Clients for Ember.js

The clients we work with generally have three driving concerns:

  1. Is the technology choice going to be an asset or a liability to our feature roadmap?
  2. Can I hire for the technology?
  3. How difficult will it be to maintain and extend the application after it’s delivered?

1. Ember.js Enables Product Roadmaps

Ember.js’s all-in-one architecture enables teams to focus on app-specific code and defer configuration details to the framework. This is better known as “convention over configuration.”

Focus on App-specific Code

Because it was inspired by Apple’s approach to native application development, Ember.js takes a holistic approach to solving the challenges that come along with modern web app development. It is comprised of libraries and APIs that standardize how developers write, test, and deploy an Ember.js application; it provides a first-class command line tool in ember-cli (which others have “borrowed”) and takes care of the build tooling, compression, asset fingerprinting, minification, and a host of other trivialities.

Again, Ember.js adopts the “convention over configuration” approach that Ruby on Rails pioneered. This means that developers spend less time thinking about configuration decisions, and more time thinking about the product roadmap. It also means that teams adopting Ember.js are inline with best practice web app architecture right out of the gate. The same can’t be said for frameworks that rely on Bring Your Own layering.

Video: Tom Dale on Ember.js Architecture vs. React.js

Customize as Needed

Ember.js has also worked hard to ensure that the architecture is modular. So if there are a few defaults that present challenges to specific teams, they can swap out the 10% of libraries that don’t suit them and benefit from the 90% of the framework that has been carefully curated for them. For teams that look at Ember.js’s architecture and think – we’ll probably need to rip out 50% of the defaults – Ember.js is probably the wrong framework for them.

2. Ember.js Hiring: Great Developers at Critical Mass

“There are more [insert hot, new JS library here] developers in the world than there are Ember.js developers.”

Going up against a Google-backed framework (Angular 2) and a Facebook-backed project (React.js) has not helped Ember.js win adoption. “Nobody ever got fired for buying IBM” logic applies here, and in part, it explains why Ember.js has faced an uphill battle in the JS framework marketing war.

But fixating on this fact is the wrong approach for building a great development team. The better question is: how many more good [hot, new JS].js developers are there than good Ember.js developers?

Leverage the Learning Curve

A competing frameworks homepage reads: “Already know HTML, CSS, and JavaScript? Read the guide and start building things in no time!”

Compare this to Ember.js’s homepage, which reads: “A framework for creating ambitious web applications.”

Ember.js provides a solution that goes beyond the narrow concerns of other libraries, and this naturally comes with more to learn. But part of what makes Ember.js difficult to adopt is what makes its developers so great: it’s more imposing to junior-level developers and provides some natural selection in the hiring process.

For hiring purposes, it can be useful to ask:

  1. Does the technology have critical mass?
  2. Does the technology make it more or less likely we build a great team?

There is already a critical mass of Ember.js developers, and the framework is growing each year alongside the Ember Learning team. For hiring managers who need to quickly deliver great web apps, it makes sense to adopt a framework that focuses less on short-term adoption and more on long-term potential.

Companies Using Ember.js

If you’re nervous about finding and hiring Ember.js developers, consider the companies who have made the investment in Ember.js: Amazon, Apple, Condé Nast, Heroku (Salesforce), Kickstarter, LinkedIn, MassMutual, McGraw-Hill Education, Microsoft, Netflix, Sony, Square, TED, Yahoo, and many more.

3. Ember.js for the Long-Term

We chose Ember.js because it would be easier for our clients to maintain, extend, and upgrade.

Onboarding New Developers

Ember.js’s embrace of “convention over configuration” and its pursuit of an all-in-one solution pays dividends when it comes to onboarding new developers.

Ember.js has tried-and-true best practices, which create a shared knowledge base for the development team. There are fewer conversations around “what’s going on in this part of the codebase” because there is an “Ember Way” to implement much of the code. Compare that to a custom-crafted, frontend tech stack which may require Senior-level developer talent to understand, maintain, and extend responsibly.

Invested in Web Standards

Ember.js is developed with an eye towards standards such as W3C and ECMAScript TC39 (the standards body for the language). This ensures that the framework will keep pace with the HTML and JavaScript APIs it relies on and provides a degree of future-proofing, relative to other frameworks less invested in web standards.

Video: Tom Dale discusses Engaging with Standards at Wicked Good Ember 2016

Ease of Upgrading

Keeping a production application on the latest, most secure version is never easy. But it’s easier with Ember.js.

Ember.js’s all-in-one architecture means that the core libraries, while modular, are designed to fit together. The core libraries align their roadmaps and follow Semantic Versioning on a 6-week release cycle or about twice a year on the Long-Term Support (LTS) release channel. The release team also does a great job of flagging deprecated features and wrapping new ones in feature flags, to ensure that developers can test out new APIs and sunset old ones.

Embracing Great Ideas

Ember.js is also unapologetic when it comes to borrowing great ideas. When another framework does something better, Ember.js is open to adopting it. And while this requires swallowing one’s pride, the impulse to borrow from other frameworks is great for the longevity of Ember.js. For example, much of Ember.js’s advancements in the rendering and view layers are inspired by React.js’s approach to delivering fast and lightweight UI components.

Borrowing great ideas (with due attribution) will allow Ember.js to evolve with a technology space that is always fickle and ever-changing. For the last 6 years, the Ember.js community has done a great job of responsibly incorporating new ideas into the framework; their ability to continue to do so makes Ember.js a great long-term bet moving forward.

Permalink

DockYard is hiring to solve Elixir deployment

DockYard has been investing in the Elixir eco-system since we first adopted Elixir nearly four years ago. Over the past three years we have been the Platinum Sponsor at ElixirConf and nearly two years ago we became the Sponsor for the Phoenix Framework when we hired Chris McCord to work on Phoenix nearly year-round.

Today we’re proud to announce that we are extending our investment in Elixir by seeking an Elixir dev to lead the development for a first-class Elixir deployment library. This project will have direct oversight by the Elixir Core Team. We plan to make the result of this effort 100% Open Source.

Please see our recent ElixirConf announcement:

Why are we interested in Deployment?

Over the past few years we have been incredibly impressed with how mature the Elixir tooling and great app eco-system has developed. When we are faced with evangelizing Elixir into communities and companies most questions are easy to answer. However, the one question that is always difficult to answer is the one around deployment. There have been some very good efforts around deployment in Elixir to date but too often they fall short of the level of ease we’ve come to expect from the other aspects of Elixir.

DockYard is in a unique position where we will significantly benefit from having a first-class build and release system for Elixir. It will make our jobs easier for estimating, building, and maintaining our client apps. We believe in the power of Open Source and know that this effort won’t be complete without community involvement so we are more than happy to make the result of this effort freely available.

Who are we seeking?

We’d like to source ideas and applications from the community. We have a general idea around the architecture for this, but deployment is a complex issue. This will be a challenge no doubt. One that we are confident that Elixir itself will make easier than it would be otherwise in other languages.

Please apply on our Join Us page. We are looking forward to working with you and making Elixir the best platform ever.

Permalink

Adding an Email Verification Flow With Phoenix

Many modern web applications require users to verify their email address at one point or another. This is especially important when you have a billing process that sends receipts to your users. We can easily add this feature to applications with Elixir and Phoenix.

The Basic Flow

We’ll assume that the row that has the email address also has a verified boolean field or something equivalent.

  1. A user registers or adds an email to their account
  2. Your application generates a unique token that is tied to the user
  3. An email is sent to the user’s email address with a link to click
  4. User navigates to link in their browser and has their email address verified

The Verification Endpoint

Let’s stub out some code for the new route. Create a new action in your controller:

defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  # Your other actions

  def verify_email(conn, params) do
    # We'll update this later
  end
end

Tie the action to a route in your router:

scope "/", MyAppWeb do
  # ...
  get "/verify", UserController, :verify_email
end

Generating a Unique Token

When you generate your token, you’ll want to make sure that the token doesn’t leak account information during the verification process as well as having the token expire after a certain duration. For us, Phoenix already comes with a module to help us in this area; Phoenix.Token. We can use Phoenix.Token to create a signed token that can be tied to a specific user and can enforce an expiration.

Here’s how we can generate the token with Phoenix.Token.sign/4:

defmodule MyApp.Token do
  @moduledoc """
  Handles creating and validating tokens.
  """

  @account_verification_salt "account verification salt"

  def generate_new_account_token(%User{id: user_id}) do
    Phoenix.Token.sign(MyAppWeb.Endpoint, @account_verification_salt, id)
  end
end

You’ll want to update your user registration endpoint to generate the token and email the user with the link. You can use your router’s path helpers to create the link.

defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  def create(conn, params) do
    # ...

    token = MyApp.Token.generate_new_account_token(user)
    verification_url = user_url(conn, :verify_email, token: token)
    MyApp.Notifications.send_account_verification_email(user, verification_url)

    # ...
  end
end

Verifying the token

Now that we can send a signed token to a user, we need to verify the token and then mark the user as verified. Let’s go back and update our UserController and Token modules to verify our signed token. We will use Phoenix.Token.verify/4 to verify our tokens.

defmodule MyApp.Token do
  # ...

  def verify_new_account_token(token) do
    max_age = 86_4000 # tokens that are older than a day should be invalid
    Phoenix.Token.verify(MyAppWeb.Endpoint, @account_verification_salt, token, max_age: max_age)
  end
end


defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  # ... Your other actions

  def verify_email(conn, %{"token" => token}) do
    with {:ok, user_id} <- MyApp.Token.verify_new_account_token(token),
         {:ok, %User{verified: false} = user} <- MyApp.Users.by_id(user_id) do
      MyApp.Accounts.mark_as_verified(user)
      render(conn, "verified.html")
    else
      _ -> render(conn, "invalid_token.html")
    end
  end
  def verify_email(conn, _) do
    # If there is no token in our params, tell the user they've provided
    # an invalid token or expired token
    conn
    |> put_flash(:error, "The verification link is invalid.")
    |> redirect(to: "/")
  end
end

Wrap Up

Leveraging Phoenix’s Token module, we created a straightforward method of adding a user email verification feature.

Permalink

Copyright © 2016, Planet Erlang. No rights reserved.
Planet Erlang is maintained by Proctor.