Tacnoman

Tacnoman

Hello guys
I must create an api with a great performance and I want to create with Elixir
I have a process (slow) that I must run after some requests. I want to make this flow

In each request, save the data received in memory
After x requests, send to another api (or after x seconds)

In node I can make this:

let batchData = []
const handlerRequest = (req, res) => {
  batchData.push(req. body.data)
  if (batchData > 1000) {
    // Process to send to another api
    batchData = []
  }
  res.json({ success: true })
}

Or

let batchData = []
setInterval(() => {
  if (batchData > 1000) {
    // Process to send to another api
    batchData = []
  }
}, 10000)

const handlerRequest = (req, res) => {
  batchData.push(req. body.data)
  res.json({ success: true })
}

How can I do something like this in Elixir Phoenix?

Thanks for this

Showing Posts 1 to 3

kokolegorille

kokolegorille

You can do this with OTP. Here is a simple GenServer that send itself a regular tick, and check the size of it’s state when data is pushed.

defmodule Demo.Gs do
  use GenServer
  @interval 10_000
  @initial_state <<>>
  
  def start_link(arg \\ @initial_state) do
    GenServer.start_link(__MODULE__, arg, name: __MODULE__)
  end

  def push(data) do
    GenServer.cast(__MODULE__, {:push, data})
  end
  
  def init(arg) do
    Process.send_after(self(), :tick, @interval)
    {:ok, arg}
  end
  
  def handle_cast({:push, data}, state) do
    state = data <> state
    case String.length(state) > 1_000 do
      true -> 
        process(state)
        {:noreply, @initial_state}
      false ->
        {:noreply, state}
    end
  end
  
  def handle_info(:tick, state) do
    process(state)
    Process.send_after(self(), :tick, @interval)
    {:noreply, @initial_state}
  end
  
  defp process(state) do
    IO.puts state
  end
end

It is just a simple example, just printing state after 10 seconds, or when pushed data is bigger than 1_000

PS. You just need to change process() with your own implementation.

Tacnoman

Tacnoman OP

Really, really thanks for this

My final solution:

defmodule Speed2.BatchProcess do
  use GenServer
  @initial_state []
  @interval 10000

  def start_link do
    GenServer.start_link(__MODULE__, [])
  end

  def init(initial_data) do
    Process.send_after(self(), :tick, @interval)
    {:ok, initial_data}
  end

  def handle_info(:tick, state) do
    process(state)
    Process.send_after(self(), :tick, @interval)
    {:noreply, @initial_state}
  end

  def get_my_state(process_id) do
    GenServer.call(process_id, :get_the_state)
  end

  def push(process_id, value) do
    GenServer.call(process_id, {:push, value})
  end

  def clean(process_id) do
    GenServer.call(process_id, :clean)
  end

  def process(state) do
    IO.inspect state
  end

  def handle_call(:get_the_state, _from, my_state) do
    {:reply, my_state, my_state}
  end

  def handle_call({:push, value}, _from, my_state) do
    new_state = my_state ++ [value]
    case Enum.count(new_state) > 10 do
      true -> 
        process(new_state)
        {:reply, new_state, @initial_state}
      false ->
        {:reply, new_state, new_state}
    end
  end

  def handle_call(:clean, _from, my_state) do
    {:reply, my_state, @initial_state}
  end
end
kokolegorille

kokolegorille

Nice, but as an advice I prefer to separate API from Server callbacks. That means putting handle info, init down in your code with server callbacks :slight_smile:

Also…

new_state = my_state ++ [value]

# I would use, which is not the same... 
# but i would push at the head of a list, and maybe reverse later.

new_state = [value | my_state]

# Also

case do end... could also be if do else end...

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews