-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
Can't add tests now since batching is a cloud only feature at the moment. Will need to come back and add it once extracted out into OSS --------- Co-authored-by: Darwin D Wu <darwin67@users.noreply.github.com>
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
defmodule Inngest.FnOpts do | ||
@moduledoc false | ||
|
||
defstruct [ | ||
:id, | ||
:name, | ||
:debounce, | ||
:batch_events, | ||
retries: 3 | ||
] | ||
|
||
alias Inngest.Util | ||
|
||
@type t() :: %__MODULE__{ | ||
id: binary(), | ||
name: binary(), | ||
retries: number() | nil, | ||
debounce: debounce() | nil, | ||
batch_events: batch_events() | nil | ||
} | ||
|
||
@type debounce() :: %{ | ||
key: nil | binary(), | ||
period: binary() | ||
} | ||
|
||
@type batch_events() :: %{ | ||
max_size: number(), | ||
timeout: binary() | ||
} | ||
|
||
@doc """ | ||
Validate the debounce configuration | ||
""" | ||
@spec validate_debounce(t(), map()) :: map() | ||
def validate_debounce(fnopts, config) do | ||
case fnopts |> Map.get(:debounce) do | ||
nil -> | ||
config | ||
|
||
debounce -> | ||
period = Map.get(debounce, :period) | ||
|
||
if is_nil(period) do | ||
raise Inngest.InvalidDebounceConfigError | ||
end | ||
|
||
case Util.parse_duration(period) do | ||
{:error, error} -> | ||
raise Inngest.InvalidDebounceConfigError, message: error | ||
|
||
{:ok, seconds} -> | ||
# credo:disable-for-next-line | ||
if seconds > 7 * Util.day_in_seconds() do | ||
raise Inngest.InvalidDebounceConfigError, | ||
message: "cannot specify period for more than 7 days" | ||
end | ||
end | ||
|
||
Map.put(config, :debounce, debounce) | ||
end | ||
end | ||
|
||
@doc """ | ||
Validate the event batch config | ||
""" | ||
@spec validate_batch_events(t(), map()) :: map() | ||
def validate_batch_events(fnopts, config) do | ||
case fnopts |> Map.get(:batch_events) do | ||
nil -> | ||
config | ||
|
||
batch -> | ||
max_size = Map.get(batch, :max_size) | ||
timeout = Map.get(batch, :timeout) | ||
|
||
if is_nil(max_size) do | ||
raise Inngest.InvalidBatchEventConfigError, | ||
message: "'max_size' must be set for batch_events" | ||
end | ||
|
||
if is_nil(timeout) do | ||
raise Inngest.InvalidBatchEventConfigError, | ||
message: "'timeout' must be set for batch_events" | ||
end | ||
|
||
case Util.parse_duration(timeout) do | ||
{:error, error} -> | ||
raise Inngest.InvalidBatchEventConfigError, message: error | ||
|
||
{:ok, seconds} -> | ||
# credo:disable-for-next-line | ||
if seconds < 1 || seconds > 60 do | ||
raise Inngest.InvalidBatchEventConfigError, | ||
message: "'timeout' duration set to '#{timeout}', needs to be 1s - 60s" | ||
end | ||
end | ||
|
||
batch = batch |> Map.put(:maxSize, max_size) |> Map.drop([:max_size]) | ||
Map.put(config, :batchEvents, batch) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
defmodule Inngest.Util do | ||
@moduledoc """ | ||
Utility functions | ||
""" | ||
|
||
@doc """ | ||
Parse string duration that Inngest understands into seconds | ||
""" | ||
@spec parse_duration(binary()) :: {:ok, number()} | {:error, binary()} | ||
def parse_duration(value) do | ||
with [_, num, unit] <- Regex.run(~r/(\d+)(s|m|h|d)/i, value), | ||
dur <- String.to_integer(num) do | ||
case unit do | ||
"d" -> {:ok, dur * day_in_seconds()} | ||
"h" -> {:ok, dur * hour_in_seconds()} | ||
"m" -> {:ok, dur * minute_in_seconds()} | ||
"s" -> {:ok, dur} | ||
_ -> {:error, "invalid time unit '#{unit}', must be d|h|m|s"} | ||
end | ||
else | ||
nil -> | ||
{:error, "invalid duration: '#{value}'"} | ||
|
||
_ -> | ||
{:error, "unknow error occurred when parsing duration"} | ||
end | ||
end | ||
|
||
def day_in_seconds(), do: 60 * 60 * 24 | ||
def hour_in_seconds(), do: 60 * 60 | ||
def minute_in_seconds(), do: 60 | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
defmodule Inngest.Function.Cases.BatchEventsTest do | ||
use ExUnit.Case, async: true | ||
|
||
alias Inngest.Test.DevServer | ||
Check warning on line 4 in test/inngest/function/cases/batch_events_test.exs GitHub Actions / Test (Elixir 1.14 / OTP 24.3)
Check warning on line 4 in test/inngest/function/cases/batch_events_test.exs GitHub Actions / Test (Elixir 1.14 / OTP 25.3)
Check warning on line 4 in test/inngest/function/cases/batch_events_test.exs GitHub Actions / Test (Elixir 1.15 / OTP 24.3)
|
||
import Inngest.Test.Helper | ||
Check warning on line 5 in test/inngest/function/cases/batch_events_test.exs GitHub Actions / Test (Elixir 1.14 / OTP 24.3)
Check warning on line 5 in test/inngest/function/cases/batch_events_test.exs GitHub Actions / Test (Elixir 1.14 / OTP 25.3)
Check warning on line 5 in test/inngest/function/cases/batch_events_test.exs GitHub Actions / Test (Elixir 1.15 / OTP 24.3)
|
||
|
||
# TODO: Add test after moving batching logic to OSS | ||
end |