Elixir in Action, Second Edition
Saša Jurić
  • January 2019
  • ISBN 9781617295027
  • 384 pages
  • printed in black & white
free previous edition eBook included
An eBook copy of the previous edition of this book is included at no additional cost. It will be automatically added to your Manning Bookshelf within 24 hours of purchase.

A gentle, lucid, and compelling guide to Elixir; loaded with practical advice.

George Thomas, Manhattan Associates

Revised and updated for Elixir 1.7, Elixir in Action, Second Edition teaches you how to apply Elixir to practical problems associated with scalability, fault tolerance, and high availability. Along the way, you'll develop an appreciation for, and considerable skill in, a functional and concurrent style of programming.

About the Technology

When you’re building mission-critical software, fault tolerance matters. The Elixir programming language delivers fast, reliable applications, whether you’re building a large-scale distributed system, a set of backend services, or a simple web app. And Elixir’s elegant syntax and functional programming mindset make your software easy to write, read, and maintain.

About the book

Elixir in Action, Second Edition teaches you how to build production-quality distributed applications using the Elixir programming language. Author Saša Juric introduces this powerful language using examples that highlight the benefits of Elixir’s functional and concurrent programming. You’ll discover how the OTP framework can radically reduce tedious low-level coding tasks. You’ll also explore practical approaches to concurrency as you learn to distribute a production system over multiple machines.

Table of Contents detailed table of contents

Part 1: Functional Elixir

1 First steps

1.1 About Erlang

1.1.1 High availability

1.1.2 Erlang concurrency

1.1.3 Server-side systems

1.1.4 The development platform

1.2 About Elixir

1.2.1 Code simplification

1.2.2 Composing functions

1.2.3 The big picture

1.3 Disadvantages

1.3.1 Speed

1.3.2 Ecosystem


2 Building blocks

2.1 The interactive shell

2.2 Working with variables

2.3 Organizing your code

2.3.1 Modules

2.3.2 Functions

2.3.3 Function arity

2.3.4 Function visibility

2.3.5 Imports and aliases

2.3.6 Module attributes


2.4 Understanding the type system

2.4.1 Numbers

2.4.2 Atoms

2.4.3 Tuples

2.4.4 Lists

2.4.5 Immutability

2.4.6 Maps

2.4.7 Binaries and bitstrings

2.4.8 Strings

2.4.9 First-class functions

2.4.10 Other built-in types

2.4.11 Higher-level types

2.4.12 IO lists

2.5 Operators

2.6 Macros

2.7 Understanding the runtime

2.7.1 Modules and functions in the runtime

2.7.2 Starting the runtime


3 Control flow

3.1 Pattern matching

3.1.1 The match operator

3.1.2 Matching tuples

3.1.3 Matching constants

3.1.4 Variables in patterns

3.1.5 Matching lists

3.1.6 Matching maps

3.1.7 Matching bitstrings and binaries

3.1.8 Compound matches

3.1.9 General behavior

3.2 Matching with functions

3.2.1 Multiclause functions

3.2.2 Guards

3.2.3 Multiclause lambdas

3.3 Conditionals

3.3.1 Branching with multiclause functions

3.3.2 Classical branching constructs

3.3.3 The with special form

3.4 Loops and iterations

3.4.1 Iterating with recursion

3.4.2 Tail function calls

3.4.3 Higher-order functions

3.4.4 Comprehensions

3.4.5 Streams


4 Data abstractions

4.1 Abstracting with modules

4.1.1 Basic abstraction

4.1.2 Composing abstractions

4.1.3 Structuring data with maps

4.1.4 Abstracting with structs

4.1.5 Data transparency

4.2 Working with hierarchical data

4.2.1 Generating IDs

4.2.2 Updating entries

4.2.3 Immutable hierarchical updates

4.2.4 Iterative updates

4.2.5 Exercise: importing from a file

4.3 Polymorphism with protocols

4.3.1 Protocol basics

4.3.2 Implementing a protocol

4.3.3 Built-in protocols


Part 2: Concurrent Elixir

5 Concurrency primitives

5.1 Concurrency in BEAM

5.2 Working with processes

5.2.1 Creating processes

5.2.2 Message passing

5.3 Stateful server processes

5.3.1 Server processes

5.3.2 Keeping a process state

5.3.3 Mutable state

5.3.4 Complex states

5.3.5 Registered processes

5.4 Runtime considerations

5.4.1 A process is sequential

5.4.2 Unlimited process mailboxes

5.4.3 Shared nothing concurrency

5.4.4 Scheduler inner workings


6 Generic server processes

6.1 Building a generic server process

6.1.1 Plugging in with modules

6.1.2 Implementing the generic code

6.1.3 Using the generic abstraction

6.1.4 Supporting asynchronous requests

6.1.5 Exercise: refactoring the to-do server

6.2 Using GenServer

6.2.1 OTP behaviours

6.2.2 Plugging into GenServer

6.2.3 Handling requests

6.2.4 Handling plain messages

6.2.5 Other GenServer features

6.2.6 Process life cycle

6.2.7 OTP-compliant processes

6.2.8 Exercise: GenServer-powered to-do server


7 Building a concurrent system

7.1 Working with the mix project

7.2 Managing multiple to-do lists

7.2.1 Implementing a cache

7.2.2 Writing tests

7.2.3 Analyzing process dependencies

7.3 Persisting data

7.3.1 Encoding and persisting

7.3.2 Using the database

7.3.3 Analyzing the system

7.3.4 Addressing the process bottleneck

7.3.5 Exercise: pooling and synchronizing

7.4 Reasoning with processes


8 Fault-tolerance basics

8.1 Runtime errors

8.1.1 Error types

8.1.2 Handling errors

8.2 Errors in concurrent systems

8.2.1 Linking processes

8.2.2 Monitors

8.3 Supervisors

8.3.1 Preparing the existing code

8.3.2 Starting the supervisor process

8.3.3 Child specification

8.3.4 Wrapping the Supervisor

8.3.5 Using a callback module

8.3.6 Linking all processes

8.3.7 Restart frequency


9 Isolating error effects

9.1 Supervision trees

9.1.1 Separating loosely dependent parts

9.1.2 Rich process discovery

9.1.3 Via tuples

9.1.4 Registering database workers

9.1.5 Supervising database workers

9.1.6 Organizing the supervision tree

9.2 Starting processes dynamically

9.2.1 Registering to-do servers

9.2.2 Dynamic supervision

9.2.3 Finding to-do servers

9.2.4 Using temporary restart strategy

9.2.5 Testing the system

9.3 “Let it crash”

9.3.1 Error kernel

9.3.2 Handling expected errors

9.3.3 Preserving the state


10 Beyond GenServer

10.1 Tasks

10.1.1 Awaited tasks

10.1.2 Non-awaited tasks

10.2 Agents

10.2.1 Basic usage

10.2.2 Agents and concurrency

10.2.3 Agent powered to-do server

10.2.4 Limitations of agents

10.3 ETS tables

10.3.1 Basic operations

10.3.2 ETS powered key-value store

10.3.3 Other ETS operations

10.3.4 Exercise: Process registry


Part 3: Production

11 Working with components

11.1 OTP applications

11.1.1 Creating applications with the mix tool

11.1.2 The application behaviour

11.1.3 Starting the application

11.1.4 Library applications

11.1.5 Creating a to-do application

11.1.6 The application folder structure

11.2 Working with dependencies

11.2.1 Adding a dependency

11.2.2 Adapting the pool

11.2.3 Visualizing the system

11.3 Building a web server

11.3.1 Choosing dependencies

11.3.2 Starting the server

11.3.3 Handling requests

11.3.4 Reasoning about the system

11.4 Configuring applications

11.4.1 Application environment

11.4.2 Varying configuration

11.4.3 Config script considerations


12 Building a distributed system

12.1 Distribution primitives

12.1.1 Starting a cluster

12.1.2 Communicating between nodes

12.1.3 Process discovery

12.1.5 Other distribution services

12.2 Building a fault-tolerant cluster

12.2.1 Cluster design

12.2.2 The distributed to-do cache

12.2.3 Implementing a replicated database

12.2.4 Testing the system

12.2.5 Detecting partitions

12.2.6 Highly available systems

12.3 Network considerations

12.3.1 Node names

12.3.2 Cookies

12.3.3 Hidden nodes

12.3.4 Firewalls


13 Running the system

13.1 Running a system with Elixir tools

13.1.1 Using mix and elixir commands

13.1.2 Running scripts

13.1.3 Compiling for production

13.2 OTP releases

13.2.1 Building a release with distillery

13.2.2 Using a release

13.2.3 Release contents

13.3 Analyzing system behavior

13.3.1 Debugging

13.3.2 Logging

13.3.3 Interacting with the system

13.3.4 Tracing


What's inside

  • Updated for Elixir 1.7
  • Functional and concurrent programming
  • Introduction to distributed system design
  • Creating deployable releases

About the reader

You’ll need intermediate skills with client/server applications and a language like Java, C#, or Ruby. No previous experience with Elixir required.

About the author

Saša Jurić is a developer with extensive experience using Elixir and Erlang in complex server-side systems.

placing your order...

Don't refresh or navigate away from the page.
print book $49.99 pBook + eBook + liveBook
includes previous edition eBook
Additional shipping charges may apply
Elixir in Action, Second Edition (print book) added to cart
continue shopping
go to cart

eBook $39.99 3 formats + liveBook
includes previous edition eBook
Elixir in Action, Second Edition (eBook) added to cart
continue shopping
go to cart

Prices displayed in rupees will be charged in USD when you check out.
customers also reading

This book 1-hop 2-hops 3-hops

FREE domestic shipping on three or more pBooks