Finishing (spec/01 §2.4): Macaw does what a source did not.
Every capability is optional. Where a source's description does not list one the
request asks, finish/3 does it to the delivery and reports it in served:
:window: rows trimmed to the window field's range, the served window intersected;:box: rows trimmed to the box over the:pointwindow field;:region: rows trimmed to each ranged field's range;:latest: each identity's latest row by the window field (spec/01 §1.4);:budget: the rows reduced to the budget by a registered reducer (reduce/5, spec/04 §7),reduced_by: :runtime.
The budget never widens the window: finishing only removes rows. A delivery that needs none of it comes back as it is.
The pure rules of running sources (spec/01 §6) are here too: ceiling/2 clamps a
budget to the host's ceiling, and pooled/1 is the one budget a pooled fetch asks for,
the largest among its readers, each reader then reduced to its own by reduce/5.
Ported from visualize's Visualize.Feed.finish/3 and reduce/4.
Summary
Functions
A budget clamped to the host's ceiling (spec/01 §6, macaw_compose 05 §1.2): {budget, clamped?}. A nil budget reads at the ceiling; a page's ceiling, given as page:,
may lower the host's, never raise it.
The delivery finished for the request, each step where the description's supports
lacks it. reduce: names the budget's reducer by spelling, a registered transform that
declares reduces/0 ("lttb", the default, or "m4" in macaw_data's own package),
and operations: is the registry it is found in (macaw_data's own by default). A name
that is no registered reducer raises ArgumentError naming it (spec/04 §7).
The budget a pooled fetch asks for: the largest among its readers' (spec/01 §6), nil
when any reader wants every row.
The delivery reduced to budget rows by the reducer method names in registry
(spec/04 §7): "lttb" by default, "m4", or any registered transform declaring
reduces/0, by spelling; macaw_data's own registry by default. It records
reduced_by: :runtime. Each series (the rows sharing every :category field's value)
is reduced field by field against the window field, or the row's place without one, by
the reducer's node %{fields: [x, y], count => c}, c the budget's share in the units
reduces/0 counts, never below the least its option takes, and
the union of the kept rows returned whole, in their order, never more than the budget.
A nil budget, a delivery within it, and a schema with no :number field to reduce by
come back as they are.
Functions
@spec ceiling(pos_integer() | nil, keyword()) :: {pos_integer(), boolean()}
A budget clamped to the host's ceiling (spec/01 §6, macaw_compose 05 §1.2): {budget, clamped?}. A nil budget reads at the ceiling; a page's ceiling, given as page:,
may lower the host's, never raise it.
iex> Macaw.Data.Source.Finish.ceiling(50_000, host: 10_000)
{10_000, true}
iex> Macaw.Data.Source.Finish.ceiling(nil, host: 10_000, page: 2_000)
{2_000, false}
@spec finish( Macaw.Data.Delivery.t(), Macaw.Data.Source.Description.t(), Macaw.Data.Source.Request.t(), keyword() ) :: Macaw.Data.Delivery.t()
The delivery finished for the request, each step where the description's supports
lacks it. reduce: names the budget's reducer by spelling, a registered transform that
declares reduces/0 ("lttb", the default, or "m4" in macaw_data's own package),
and operations: is the registry it is found in (macaw_data's own by default). A name
that is no registered reducer raises ArgumentError naming it (spec/04 §7).
Raises ArgumentError for a request the schema cannot answer (Window.check/2): the
request is the caller's.
@spec pooled([pos_integer() | nil, ...]) :: pos_integer() | nil
The budget a pooled fetch asks for: the largest among its readers' (spec/01 §6), nil
when any reader wants every row.
iex> Macaw.Data.Source.Finish.pooled([100, 4_000, 250])
4000
@spec reduce( Macaw.Data.Delivery.t(), Macaw.Data.Schema.t(), pos_integer() | nil, String.t() | atom(), Macaw.Data.Operations.Registry.t() ) :: Macaw.Data.Delivery.t()
The delivery reduced to budget rows by the reducer method names in registry
(spec/04 §7): "lttb" by default, "m4", or any registered transform declaring
reduces/0, by spelling; macaw_data's own registry by default. It records
reduced_by: :runtime. Each series (the rows sharing every :category field's value)
is reduced field by field against the window field, or the row's place without one, by
the reducer's node %{fields: [x, y], count => c}, c the budget's share in the units
reduces/0 counts, never below the least its option takes, and
the union of the kept rows returned whole, in their order, never more than the budget.
A nil budget, a delivery within it, and a schema with no :number field to reduce by
come back as they are.
iex> alias Macaw.Data.{Delivery, Schema, Source.Finish}
iex> schema = Schema.new!(%{t: %{type: :number, window: true}, v: %{type: :number}})
iex> reduced = Finish.reduce(Delivery.new(for t <- 1..100, do: %{t: t, v: rem(t * 7, 5)}), schema, 10)
iex> {Table.size(reduced.table), reduced.served.reduced_by}
{10, :runtime}