Macaw.Data.Source.Finish (macaw_data v0.5.3)

Copy Markdown View Source

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:

  1. :window: rows trimmed to the window field's range, the served window intersected;
  2. :box: rows trimmed to the box over the :point window field;
  3. :region: rows trimmed to each ranged field's range;
  4. :latest: each identity's latest row by the window field (spec/01 §1.4);
  5. :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

ceiling(budget, opts)

@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}

finish(delivery, description, request, opts \\ [])

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.

pooled(budgets)

@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

reduce(delivery, schema, budget, method \\ "lttb", registry \\ Operations.registry())

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}