Packages
Computational distributable flows with stages inspired by Flow, Spark and EMR.
Current section
Files
Jump to
Current section
Files
lib/example/count_words.ex
defmodule ElasticFlow.Example do
@moduledoc """
Everyone loves examples! This is a simple program similar to Flow's example.. a word counting problem!
Follow the instructions from the README to setup and try it out. Estimated time: 5 minutes.
"""
# Run setup separately first
def run(file_name \\ "lib/example/data/essay.txt") do
alias ElasticFlow, as: ES
IO.inspect "Opening stream #{file_name} and adding step."
file = File.stream!(file_name)
ES.create_step(file) |> ES.add_step()
end
@doc """
A simple out of place utility to connect to other local nodes and simulate a distributed system.
Helpful for running the example quickly
"""
def setup() do
IO.inspect "Connecting to nodes."
# Connect master with all slaves. Will share info with slaves automatically
for key <- Map.keys(Application.get_env(:elastic_flow, :servers)) do
case Map.get(Application.get_env(:elastic_flow, :servers), key) do
:master ->
nil
_ ->
Node.connect key
end
end
end
@doc """
Retrieve the aggregated results of the example
"""
def results() do
ElasticFlow.Aggregator.retrieve_results()
end
@doc """
Custom distribut window to force more distribution for the small essay example data
Since distribute uses each_state, resetting is necessary to avoid sending duplicate data.
"""
def get_window() do
Flow.Window.global() |> Flow.Window.trigger_every(3, :reset)
end
@doc """
Word counting flow. Set your config to use this as a task
"""
def count_words(enumerable) do
empty_space = :binary.compile_pattern(" ")
Flow.from_enumerable(enumerable)
|> Flow.flat_map(&String.split(&1, empty_space))
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, acc ->
Map.update(acc, word, 1, & &1 + 1)
end)
|> Enum.to_list()
end
@doc """
The programs aggregation method, configured to be run against incoming results
"""
def aggregate(result, nil) do
aggregate(result, %{})
end
def aggregate(result, previous_results) do
result_map = Enum.reduce(result, %{}, fn {word, count}, acc ->
Map.put_new(acc, word, count)
end)
Map.merge(result_map, previous_results, fn _key, count1, count2 ->
count1 + count2
end)
end
end