pnezis

pnezis

Broadway pipelines questions and best practices

I am using broadway lately (which by the way is a pleasure to work with) for some data pipelines and I am wondering if the approaches I have taken are the optimal ones.

Context

The basic workflow is:

  • Read messages from a set of kafka topics
  • Process the raw messages and extract a set of valid json documents. Some incoming may be invalid so we need to ignore them.
  • Store the processed data.

How to ignore/skip raw messages.

Incoming data are processed in a process_data function which returns the status of the processing and the transformed data. The returned statuses can be :ok, :skip or :error. Currently I am handling messages as following:

def handle_message(_, %Message{data: data} = message, _) do
    case process_data(data) do
      {:ok, data} -> 
            Message.update_data(message, fn _ -> data end)
            |> Message.put_batch_key(data.type)
            |> Message.put_batcher(:default)

      {:skip, reason} ->
          Message.failed(message, reason)

      {:error, reason} ->
          Message.failed(message, reason) 
    end
end

Question 1

Should I mark the messages as failed directly or should I add them to the batcher and ignore them in the handle_batch function?

Multiple batchers

Assume that I want to do more than one operation on the successfully processed messages, e.g. store them in a database and store them to s3. broadway does not support propagating the same message to different batchers for good reasons. I see two options here:

  • Use a single batcher and do all the batch processing (e.g. store mesages both to the database and s3). The drawback of this approach is that I cannot have different batch_size and batch_timeout options.
  • Create a pipeline for each batcher. The drawback of this approach is that the same raw messages will be processed multiple times.

Question 2

Is there any alternative method? What do you think is the best approach for that use case?

Multiple extracted messages for each incoming message

Each incoming kafka message may contain multiple sub-messages. For example a raw message can be:

[A1, A2, B1, C1, B2, A3]

where A,B, C are the different message types. I would like to do something like:

extracted_messages
|> Enum.map(fn x -> Message.put_batch_key(x, x.type) end)
|> Enum.map(&Message.put_batcher(&1, :default))

The problem here is that handle_message must return exactly one message, so I cannot split a single incoming messages to multiple processed messages, each of which should have a different batch key or potentially a different batcher.

Question 3

The approach I am currently following is to send each of these sub-messages to another kakfa topic and handle them with a secodary pipeline. Is there any better solution? Could this be achieved in a single pipeline?

Where Next?

Popular in Questions Top

pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement