-module(lightspeed@data_ergonomics).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/data_ergonomics.gleam").
-export([text_field/3, int_field/3, bool_field/3, empty_field/2, changeset/3, validate_changeset/1, changeset_valid/1, changeset_errors/1, changeset_error_signature/1, field_value_label/1, data_error_label/1, new_runtime/0, seed_runtime/1, rows/1, row_signature/1, runtime_signature/1, row/4, create/2, fetch/2, update/4, delete/2, dashboard_summary/1, dashboard_signature/1, unit_of_work/2, operation_label/1, unit_of_work_error_label/1, run_unit_of_work/2, query_shape/5, diagnose_query/1, diagnostic_label/1, diagnostics_signature/1, dashboard_with_diagnostics/2]).
-export_type([field_value/0, validation_rule/0, field/0, changeset/0, row/0, data_error/0, runtime/0, dashboard_summary/0, unit_operation/0, unit_of_work/0, unit_of_work_error/0, query_shape/0, query_diagnostic/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(" ORM/data ergonomics parity profile contracts for M57.\n").
-type field_value() :: {text_value, binary()} |
{int_value, integer()} |
{bool_value, boolean()} |
empty_value.
-type validation_rule() :: required |
{min_length, integer()} |
{min_int, integer()}.
-type field() :: {field,
binary(),
field_value(),
list(validation_rule()),
list(binary())}.
-type changeset() :: {changeset,
binary(),
list(field()),
list(changeset()),
list(binary())}.
-type row() :: {row, binary(), integer(), binary(), list({binary(), binary()})}.
-type data_error() :: {validation_failed, binary()} |
{not_found, binary()} |
{concurrency_conflict, binary(), integer(), integer()}.
-opaque runtime() :: {runtime, list(row()), integer()}.
-type dashboard_summary() :: {dashboard_summary,
integer(),
integer(),
integer(),
integer()}.
-type unit_operation() :: {create_from_changeset, changeset()} |
{update_from_changeset, binary(), integer(), changeset()} |
{delete_by_id, binary()}.
-type unit_of_work() :: {unit_of_work, binary(), list(unit_operation())}.
-type unit_of_work_error() :: {operation_failed, integer(), data_error()}.
-type query_shape() :: {query_shape,
binary(),
integer(),
integer(),
integer(),
binary()}.
-type query_diagnostic() :: {n_plus_one_detected, binary(), integer()} |
{slow_query_detected, binary(), integer()} |
{trace_correlated, binary(), binary()}.
-file("src/lightspeed/data_ergonomics.gleam", 110).
?DOC(" Build one text field.\n").
-spec text_field(binary(), binary(), list(validation_rule())) -> field().
text_field(Name, Value, Rules) ->
{field, Name, {text_value, Value}, Rules, []}.
-file("src/lightspeed/data_ergonomics.gleam", 119).
?DOC(" Build one int field.\n").
-spec int_field(binary(), integer(), list(validation_rule())) -> field().
int_field(Name, Value, Rules) ->
{field, Name, {int_value, Value}, Rules, []}.
-file("src/lightspeed/data_ergonomics.gleam", 128).
?DOC(" Build one bool field.\n").
-spec bool_field(binary(), boolean(), list(validation_rule())) -> field().
bool_field(Name, Value, Rules) ->
{field, Name, {bool_value, Value}, Rules, []}.
-file("src/lightspeed/data_ergonomics.gleam", 137).
?DOC(" Build one empty field for required validation paths.\n").
-spec empty_field(binary(), list(validation_rule())) -> field().
empty_field(Name, Rules) ->
{field, Name, empty_value, Rules, []}.
-file("src/lightspeed/data_ergonomics.gleam", 142).
?DOC(" Build one changeset.\n").
-spec changeset(binary(), list(field()), list(changeset())) -> changeset().
changeset(Resource, Fields, Nested) ->
{changeset, Resource, Fields, Nested, []}.
-file("src/lightspeed/data_ergonomics.gleam", 750).
-spec append(list(JSX), list(JSX)) -> list(JSX).
append(Left, Right) ->
case Left of
[] ->
Right;
[Entry | Rest] ->
[Entry | append(Rest, Right)]
end.
-file("src/lightspeed/data_ergonomics.gleam", 538).
-spec flatten_nested_errors(list(changeset()), list(binary())) -> list(binary()).
flatten_nested_errors(Nested, Errors_rev) ->
case Nested of
[] ->
lists:reverse(Errors_rev);
[Child | Rest] ->
Prefixed = gleam@list:map(
erlang:element(5, Child),
fun(Error) ->
<<<<<<"nested:"/utf8, (erlang:element(2, Child))/binary>>/binary,
":"/utf8>>/binary,
Error/binary>>
end
),
flatten_nested_errors(
Rest,
append(lists:reverse(Prefixed), Errors_rev)
)
end.
-file("src/lightspeed/data_ergonomics.gleam", 526).
-spec flatten_field_errors(list(field()), list(binary())) -> list(binary()).
flatten_field_errors(Fields, Errors_rev) ->
case Fields of
[] ->
lists:reverse(Errors_rev);
[Field | Rest] ->
flatten_field_errors(
Rest,
append(lists:reverse(erlang:element(5, Field)), Errors_rev)
)
end.
-file("src/lightspeed/data_ergonomics.gleam", 518).
-spec value_empty(field_value()) -> boolean().
value_empty(Value) ->
case Value of
{text_value, Text} ->
Text =:= <<""/utf8>>;
empty_value ->
true;
_ ->
false
end.
-file("src/lightspeed/data_ergonomics.gleam", 479).
-spec validate_rule(field(), validation_rule()) -> {ok, nil} | {error, binary()}.
validate_rule(Field, Rule) ->
case Rule of
required ->
case value_empty(erlang:element(3, Field)) of
true ->
{error,
<<"required:"/utf8, (erlang:element(2, Field))/binary>>};
false ->
{ok, nil}
end;
{min_length, Minimum} ->
case erlang:element(3, Field) of
{text_value, Text} ->
case string:length(Text) < Minimum of
true ->
{error,
<<<<<<"min_length:"/utf8,
(erlang:element(2, Field))/binary>>/binary,
":"/utf8>>/binary,
(erlang:integer_to_binary(Minimum))/binary>>};
false ->
{ok, nil}
end;
empty_value ->
{error,
<<<<<<"min_length:"/utf8,
(erlang:element(2, Field))/binary>>/binary,
":"/utf8>>/binary,
(erlang:integer_to_binary(Minimum))/binary>>};
_ ->
{error,
<<"invalid_type:min_length:"/utf8,
(erlang:element(2, Field))/binary>>}
end;
{min_int, Minimum@1} ->
case erlang:element(3, Field) of
{int_value, Number} ->
case Number < Minimum@1 of
true ->
{error,
<<<<<<"min_int:"/utf8,
(erlang:element(2, Field))/binary>>/binary,
":"/utf8>>/binary,
(erlang:integer_to_binary(Minimum@1))/binary>>};
false ->
{ok, nil}
end;
_ ->
{error,
<<"invalid_type:min_int:"/utf8,
(erlang:element(2, Field))/binary>>}
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 463).
-spec validate_rules(field(), list(validation_rule()), list(binary())) -> list(binary()).
validate_rules(Field, Rules, Errors_rev) ->
case Rules of
[] ->
lists:reverse(Errors_rev);
[Rule | Rest] ->
case validate_rule(Field, Rule) of
{ok, nil} ->
validate_rules(Field, Rest, Errors_rev);
{error, Error} ->
validate_rules(Field, Rest, [Error | Errors_rev])
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 458).
-spec validate_field(field()) -> field().
validate_field(Field) ->
Errors = validate_rules(Field, erlang:element(4, Field), []),
{field,
erlang:element(2, Field),
erlang:element(3, Field),
erlang:element(4, Field),
Errors}.
-file("src/lightspeed/data_ergonomics.gleam", 151).
?DOC(" Validate one changeset recursively and propagate nested errors.\n").
-spec validate_changeset(changeset()) -> changeset().
validate_changeset(Changeset) ->
Validated_fields = gleam@list:map(
erlang:element(3, Changeset),
fun validate_field/1
),
Field_errors = flatten_field_errors(Validated_fields, []),
Validated_nested = gleam@list:map(
erlang:element(4, Changeset),
fun validate_changeset/1
),
Nested_errors = flatten_nested_errors(Validated_nested, []),
Errors = append(Field_errors, Nested_errors),
{changeset,
erlang:element(2, Changeset),
Validated_fields,
Validated_nested,
Errors}.
-file("src/lightspeed/data_ergonomics.gleam", 167).
?DOC(" True when a validated changeset has no errors.\n").
-spec changeset_valid(changeset()) -> boolean().
changeset_valid(Changeset) ->
erlang:element(5, Changeset) =:= [].
-file("src/lightspeed/data_ergonomics.gleam", 172).
?DOC(" All errors on one validated changeset.\n").
-spec changeset_errors(changeset()) -> list(binary()).
changeset_errors(Changeset) ->
erlang:element(5, Changeset).
-file("src/lightspeed/data_ergonomics.gleam", 764).
-spec join_with(binary(), list(binary())) -> binary().
join_with(Separator, Values) ->
case Values of
[] ->
<<""/utf8>>;
[First | Rest] ->
gleam@list:fold(
Rest,
First,
fun(Accumulator, Value) ->
<<<<Accumulator/binary, Separator/binary>>/binary,
Value/binary>>
end
)
end.
-file("src/lightspeed/data_ergonomics.gleam", 177).
?DOC(" Stable changeset error signature.\n").
-spec changeset_error_signature(changeset()) -> binary().
changeset_error_signature(Changeset) ->
join_with(<<","/utf8>>, erlang:element(5, Changeset)).
-file("src/lightspeed/data_ergonomics.gleam", 757).
-spec bool_label(boolean()) -> binary().
bool_label(Value) ->
case Value of
true ->
<<"true"/utf8>>;
false ->
<<"false"/utf8>>
end.
-file("src/lightspeed/data_ergonomics.gleam", 182).
?DOC(" Stable field value label.\n").
-spec field_value_label(field_value()) -> binary().
field_value_label(Value) ->
case Value of
{text_value, Text} ->
Text;
{int_value, Number} ->
erlang:integer_to_binary(Number);
{bool_value, Flag} ->
bool_label(Flag);
empty_value ->
<<""/utf8>>
end.
-file("src/lightspeed/data_ergonomics.gleam", 192).
?DOC(" Stable data error label.\n").
-spec data_error_label(data_error()) -> binary().
data_error_label(Error) ->
case Error of
{validation_failed, Reason} ->
<<"validation_failed:"/utf8, Reason/binary>>;
{not_found, Id} ->
<<"not_found:"/utf8, Id/binary>>;
{concurrency_conflict, Id@1, Expected, Actual} ->
<<<<<<<<<<"concurrency_conflict:"/utf8, Id@1/binary>>/binary,
":expected="/utf8>>/binary,
(erlang:integer_to_binary(Expected))/binary>>/binary,
":actual="/utf8>>/binary,
(erlang:integer_to_binary(Actual))/binary>>
end.
-file("src/lightspeed/data_ergonomics.gleam", 207).
?DOC(" Build an empty runtime.\n").
-spec new_runtime() -> runtime().
new_runtime() ->
{runtime, [], 1}.
-file("src/lightspeed/data_ergonomics.gleam", 212).
?DOC(" Build a runtime from existing rows.\n").
-spec seed_runtime(list(row())) -> runtime().
seed_runtime(Rows) ->
{runtime, lists:reverse(Rows), erlang:length(Rows) + 1}.
-file("src/lightspeed/data_ergonomics.gleam", 217).
?DOC(" Runtime rows in stable order.\n").
-spec rows(runtime()) -> list(row()).
rows(Runtime) ->
lists:reverse(erlang:element(2, Runtime)).
-file("src/lightspeed/data_ergonomics.gleam", 658).
-spec attributes_signature(list({binary(), binary()})) -> binary().
attributes_signature(Attributes) ->
Labels = gleam@list:map(
Attributes,
fun(Attribute) ->
{Key, Value} = Attribute,
<<<<Key/binary, "="/utf8>>/binary, Value/binary>>
end
),
join_with(<<","/utf8>>, Labels).
-file("src/lightspeed/data_ergonomics.gleam", 244).
?DOC(" Stable row signature.\n").
-spec row_signature(row()) -> binary().
row_signature(Row) ->
<<<<<<<<<<<<(erlang:element(2, Row))/binary, ":rev="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(3, Row)))/binary>>/binary,
":resource="/utf8>>/binary,
(erlang:element(4, Row))/binary>>/binary,
":attrs="/utf8>>/binary,
(attributes_signature(erlang:element(5, Row)))/binary>>.
-file("src/lightspeed/data_ergonomics.gleam", 222).
?DOC(" Stable runtime signature for fixtures.\n").
-spec runtime_signature(runtime()) -> binary().
runtime_signature(Runtime) ->
Row_signatures = gleam@list:map(rows(Runtime), fun row_signature/1),
<<<<<<<<<<"rows="/utf8,
(erlang:integer_to_binary(erlang:length(Row_signatures)))/binary>>/binary,
"|next_id="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(3, Runtime)))/binary>>/binary,
"|entries="/utf8>>/binary,
(join_with(<<";"/utf8>>, Row_signatures))/binary>>.
-file("src/lightspeed/data_ergonomics.gleam", 234).
?DOC(" Build one row record.\n").
-spec row(binary(), integer(), binary(), list({binary(), binary()})) -> row().
row(Id, Revision, Resource, Attributes) ->
{row, Id, Revision, Resource, Attributes}.
-file("src/lightspeed/data_ergonomics.gleam", 555).
-spec fields_to_attributes(list(field()), list({binary(), binary()})) -> list({binary(),
binary()}).
fields_to_attributes(Fields, Attributes_rev) ->
case Fields of
[] ->
lists:reverse(Attributes_rev);
[Field | Rest] ->
fields_to_attributes(
Rest,
[{erlang:element(2, Field),
field_value_label(erlang:element(3, Field))} |
Attributes_rev]
)
end.
-file("src/lightspeed/data_ergonomics.gleam", 255).
?DOC(" Create one row from a changeset.\n").
-spec create(runtime(), changeset()) -> {ok, {runtime(), row()}} |
{error, data_error()}.
create(Runtime, Changeset) ->
Validated = validate_changeset(Changeset),
case changeset_valid(Validated) of
false ->
{error, {validation_failed, changeset_error_signature(Validated)}};
true ->
Created = {row,
<<"row-"/utf8,
(erlang:integer_to_binary(erlang:element(3, Runtime)))/binary>>,
1,
erlang:element(2, Validated),
fields_to_attributes(erlang:element(3, Validated), [])},
{ok,
{{runtime,
[Created | erlang:element(2, Runtime)],
erlang:element(3, Runtime) + 1},
Created}}
end.
-file("src/lightspeed/data_ergonomics.gleam", 569).
-spec lookup_row(list(row()), binary()) -> {ok, row()} | {error, nil}.
lookup_row(Rows_rev, Id) ->
case Rows_rev of
[] ->
{error, nil};
[Entry | Rest] ->
case erlang:element(2, Entry) =:= Id of
true ->
{ok, Entry};
false ->
lookup_row(Rest, Id)
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 284).
?DOC(" Fetch one row by id.\n").
-spec fetch(runtime(), binary()) -> {ok, row()} | {error, data_error()}.
fetch(Runtime, Id) ->
case lookup_row(erlang:element(2, Runtime), Id) of
{error, nil} ->
{error, {not_found, Id}};
{ok, Found} ->
{ok, Found}
end.
-file("src/lightspeed/data_ergonomics.gleam", 580).
-spec replace_row(list(row()), binary(), row()) -> list(row()).
replace_row(Rows_rev, Id, Updated) ->
case Rows_rev of
[] ->
[];
[Entry | Rest] ->
case erlang:element(2, Entry) =:= Id of
true ->
[Updated | Rest];
false ->
[Entry | replace_row(Rest, Id, Updated)]
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 292).
?DOC(" Update one row with optimistic-concurrency checks.\n").
-spec update(runtime(), binary(), integer(), changeset()) -> {ok,
{runtime(), row()}} |
{error, data_error()}.
update(Runtime, Id, Expected_revision, Changeset) ->
Validated = validate_changeset(Changeset),
case changeset_valid(Validated) of
false ->
{error, {validation_failed, changeset_error_signature(Validated)}};
true ->
case lookup_row(erlang:element(2, Runtime), Id) of
{error, nil} ->
{error, {not_found, Id}};
{ok, Found} ->
case erlang:element(3, Found) =:= Expected_revision of
false ->
{error,
{concurrency_conflict,
Id,
Expected_revision,
erlang:element(3, Found)}};
true ->
Updated = {row,
erlang:element(2, Found),
erlang:element(3, Found) + 1,
erlang:element(2, Validated),
fields_to_attributes(
erlang:element(3, Validated),
[]
)},
{ok,
{{runtime,
replace_row(
erlang:element(2, Runtime),
erlang:element(2, Updated),
Updated
),
erlang:element(3, Runtime)},
Updated}}
end
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 591).
-spec remove_row(list(row()), binary()) -> list(row()).
remove_row(Rows_rev, Id) ->
case Rows_rev of
[] ->
[];
[Entry | Rest] ->
case erlang:element(2, Entry) =:= Id of
true ->
remove_row(Rest, Id);
false ->
[Entry | remove_row(Rest, Id)]
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 338).
?DOC(" Delete one row.\n").
-spec delete(runtime(), binary()) -> {ok, runtime()} | {error, data_error()}.
delete(Runtime, Id) ->
case lookup_row(erlang:element(2, Runtime), Id) of
{error, nil} ->
{error, {not_found, Id}};
{ok, _} ->
{ok,
{runtime,
remove_row(erlang:element(2, Runtime), Id),
erlang:element(3, Runtime)}}
end.
-file("src/lightspeed/data_ergonomics.gleam", 647).
-spec attribute_value(list({binary(), binary()}), binary()) -> binary().
attribute_value(Attributes, Key) ->
case Attributes of
[] ->
<<""/utf8>>;
[{Attribute_key, Value} | Rest] ->
case Attribute_key =:= Key of
true ->
Value;
false ->
attribute_value(Rest, Key)
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 602).
-spec summarize_rows(list(row()), dashboard_summary()) -> dashboard_summary().
summarize_rows(Rows, Summary) ->
case Rows of
[] ->
Summary;
[Entry | Rest] ->
case attribute_value(erlang:element(5, Entry), <<"status"/utf8>>) of
<<"draft"/utf8>> ->
summarize_rows(
Rest,
{dashboard_summary,
erlang:element(2, Summary) + 1,
erlang:element(3, Summary) + 1,
erlang:element(4, Summary),
erlang:element(5, Summary)}
);
<<"published"/utf8>> ->
summarize_rows(
Rest,
{dashboard_summary,
erlang:element(2, Summary) + 1,
erlang:element(3, Summary),
erlang:element(4, Summary) + 1,
erlang:element(5, Summary)}
);
_ ->
summarize_rows(
Rest,
{dashboard_summary,
erlang:element(2, Summary) + 1,
erlang:element(3, Summary),
erlang:element(4, Summary),
erlang:element(5, Summary) + 1}
)
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 350).
?DOC(" Build dashboard summary for common CRUD status cards.\n").
-spec dashboard_summary(runtime()) -> dashboard_summary().
dashboard_summary(Runtime) ->
summarize_rows(rows(Runtime), {dashboard_summary, 0, 0, 0, 0}).
-file("src/lightspeed/data_ergonomics.gleam", 355).
?DOC(" Stable dashboard summary signature.\n").
-spec dashboard_signature(dashboard_summary()) -> binary().
dashboard_signature(Summary) ->
<<<<<<<<<<<<<<"total="/utf8,
(erlang:integer_to_binary(
erlang:element(2, Summary)
))/binary>>/binary,
":draft="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(3, Summary)))/binary>>/binary,
":published="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(4, Summary)))/binary>>/binary,
":stale="/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(5, Summary)))/binary>>.
-file("src/lightspeed/data_ergonomics.gleam", 367).
?DOC(" Build one unit-of-work from typed operations.\n").
-spec unit_of_work(binary(), list(unit_operation())) -> unit_of_work().
unit_of_work(Name, Operations) ->
{unit_of_work, Name, Operations}.
-file("src/lightspeed/data_ergonomics.gleam", 375).
?DOC(" Stable operation label.\n").
-spec operation_label(unit_operation()) -> binary().
operation_label(Operation) ->
case Operation of
{create_from_changeset, Changeset} ->
<<"create:"/utf8, (erlang:element(2, Changeset))/binary>>;
{update_from_changeset, Id, Expected_revision, Changeset@1} ->
<<<<<<<<<<"update:"/utf8, Id/binary>>/binary, ":expected="/utf8>>/binary,
(erlang:integer_to_binary(Expected_revision))/binary>>/binary,
":resource="/utf8>>/binary,
(erlang:element(2, Changeset@1))/binary>>;
{delete_by_id, Id@1} ->
<<"delete:"/utf8, Id@1/binary>>
end.
-file("src/lightspeed/data_ergonomics.gleam", 390).
?DOC(" Stable unit-of-work error label.\n").
-spec unit_of_work_error_label(unit_of_work_error()) -> binary().
unit_of_work_error_label(Error) ->
case Error of
{operation_failed, Index, Data_error} ->
<<<<<<"operation_failed:"/utf8,
(erlang:integer_to_binary(Index))/binary>>/binary,
":"/utf8>>/binary,
(data_error_label(Data_error))/binary>>
end.
-file("src/lightspeed/data_ergonomics.gleam", 668).
-spec apply_operations(
runtime(),
list(unit_operation()),
integer(),
list(binary())
) -> {ok, {runtime(), list(binary())}} | {error, unit_of_work_error()}.
apply_operations(Runtime, Operations, Index, Signatures_rev) ->
case Operations of
[] ->
{ok, {Runtime, lists:reverse(Signatures_rev)}};
[Operation | Rest] ->
case Operation of
{create_from_changeset, Changeset} ->
case create(Runtime, Changeset) of
{error, Error} ->
{error, {operation_failed, Index, Error}};
{ok, {Next_runtime, Created}} ->
apply_operations(
Next_runtime,
Rest,
Index + 1,
[<<<<<<"create:"/utf8,
(erlang:element(2, Created))/binary>>/binary,
":rev="/utf8>>/binary,
(erlang:integer_to_binary(
erlang:element(3, Created)
))/binary>> |
Signatures_rev]
)
end;
{update_from_changeset, Id, Expected_revision, Changeset@1} ->
case update(Runtime, Id, Expected_revision, Changeset@1) of
{error, Error@1} ->
{error, {operation_failed, Index, Error@1}};
{ok, {Next_runtime@1, Updated}} ->
apply_operations(
Next_runtime@1,
Rest,
Index + 1,
[<<<<<<"update:"/utf8,
(erlang:element(2, Updated))/binary>>/binary,
":rev="/utf8>>/binary,
(erlang:integer_to_binary(
erlang:element(3, Updated)
))/binary>> |
Signatures_rev]
)
end;
{delete_by_id, Id@1} ->
case delete(Runtime, Id@1) of
{error, Error@2} ->
{error, {operation_failed, Index, Error@2}};
{ok, Next_runtime@2} ->
apply_operations(
Next_runtime@2,
Rest,
Index + 1,
[<<"delete:"/utf8, Id@1/binary>> |
Signatures_rev]
)
end
end
end.
-file("src/lightspeed/data_ergonomics.gleam", 401).
?DOC(" Apply one unit-of-work with atomic semantics.\n").
-spec run_unit_of_work(runtime(), unit_of_work()) -> {ok,
{runtime(), list(binary())}} |
{error, unit_of_work_error()}.
run_unit_of_work(Runtime, Unit_of_work) ->
apply_operations(Runtime, erlang:element(3, Unit_of_work), 1, []).
-file("src/lightspeed/data_ergonomics.gleam", 409).
?DOC(" Build one query shape.\n").
-spec query_shape(binary(), integer(), integer(), integer(), binary()) -> query_shape().
query_shape(
Name,
Projected_rows,
Statement_count,
Estimated_latency_ms,
Trace_id
) ->
{query_shape,
Name,
Projected_rows,
Statement_count,
Estimated_latency_ms,
Trace_id}.
-file("src/lightspeed/data_ergonomics.gleam", 734).
-spec maybe_add_slow_query(list(query_diagnostic()), query_shape()) -> list(query_diagnostic()).
maybe_add_slow_query(Diagnostics, Shape) ->
case erlang:element(5, Shape) >= 120 of
true ->
append(
Diagnostics,
[{slow_query_detected,
erlang:element(2, Shape),
erlang:element(5, Shape)}]
);
false ->
Diagnostics
end.
-file("src/lightspeed/data_ergonomics.gleam", 718).
-spec maybe_add_n_plus_one(list(query_diagnostic()), query_shape()) -> list(query_diagnostic()).
maybe_add_n_plus_one(Diagnostics, Shape) ->
case (erlang:element(4, Shape) > 4) andalso (erlang:element(3, Shape) > 0) of
true ->
append(
Diagnostics,
[{n_plus_one_detected,
erlang:element(2, Shape),
erlang:element(4, Shape)}]
);
false ->
Diagnostics
end.
-file("src/lightspeed/data_ergonomics.gleam", 426).
?DOC(" Derive deterministic diagnostics for a query shape.\n").
-spec diagnose_query(query_shape()) -> list(query_diagnostic()).
diagnose_query(Shape) ->
_pipe = [],
_pipe@1 = maybe_add_n_plus_one(_pipe, Shape),
_pipe@2 = maybe_add_slow_query(_pipe@1, Shape),
append(
_pipe@2,
[{trace_correlated, erlang:element(6, Shape), erlang:element(2, Shape)}]
).
-file("src/lightspeed/data_ergonomics.gleam", 434).
?DOC(" Stable query diagnostic label.\n").
-spec diagnostic_label(query_diagnostic()) -> binary().
diagnostic_label(Diagnostic) ->
case Diagnostic of
{n_plus_one_detected, Query, Statement_count} ->
<<<<<<"n_plus_one:"/utf8, Query/binary>>/binary,
":statements="/utf8>>/binary,
(erlang:integer_to_binary(Statement_count))/binary>>;
{slow_query_detected, Query@1, Latency_ms} ->
<<<<<<"slow_query:"/utf8, Query@1/binary>>/binary,
":latency_ms="/utf8>>/binary,
(erlang:integer_to_binary(Latency_ms))/binary>>;
{trace_correlated, Trace_id, Query@2} ->
<<<<<<"trace_correlated:"/utf8, Trace_id/binary>>/binary,
":query="/utf8>>/binary,
Query@2/binary>>
end.
-file("src/lightspeed/data_ergonomics.gleam", 446).
?DOC(" Stable query diagnostics signature.\n").
-spec diagnostics_signature(list(query_diagnostic())) -> binary().
diagnostics_signature(Diagnostics) ->
join_with(<<";"/utf8>>, gleam@list:map(Diagnostics, fun diagnostic_label/1)).
-file("src/lightspeed/data_ergonomics.gleam", 451).
?DOC(" Dashboard summary with query diagnostics.\n").
-spec dashboard_with_diagnostics(runtime(), query_shape()) -> {dashboard_summary(),
list(query_diagnostic())}.
dashboard_with_diagnostics(Runtime, Shape) ->
{dashboard_summary(Runtime), diagnose_query(Shape)}.