-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) -> <<<>/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, <<<>, 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)}.