-module(themis@internal@store). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([init/0, new_metric/5, find_metric/3, match_metrics/2, increment_record_by/4, increment_record/3, insert_record/4, match_records/2, find_record/3]). -export_type([store_error/0, store/0]). -type store_error() :: metric_name_already_exists | insert_error | {decode_errors, list(gleam@dynamic:decode_error())} | table_error | invalid_increment | single_result_expected | invalid_type | metric_not_found. -type store() :: {store, themis@internal@erlang@ets:table(), themis@internal@erlang@ets:table()}. -file("/git/Themis/src/themis/internal/store.gleam", 34). -spec init() -> store(). init() -> Metrics_table = themis@internal@erlang@ets:new( {table_builder, set, public}, <<"themis_metrics"/utf8>> ), Records_table = themis@internal@erlang@ets:new( {table_builder, set, public}, <<"themis_records"/utf8>> ), {store, Metrics_table, Records_table}. -file("/git/Themis/src/themis/internal/store.gleam", 42). -spec new_metric( store(), themis@internal@metric:metric_name(), binary(), binary(), list(float()) ) -> {ok, nil} | {error, store_error()}. new_metric(Store, Name, Description, Kind, Buckets) -> Table = erlang:element(2, Store), _pipe@2 = themis@internal@erlang@ets:insert_new_raw( Table, begin _pipe@1 = {begin _pipe = Name, themis@internal@metric:name_to_string(_pipe) end, Description, Kind, Buckets}, gleam_stdlib:identity(_pipe@1) end ), gleam@result:replace_error(_pipe@2, metric_name_already_exists). -file("/git/Themis/src/themis/internal/store.gleam", 58). -spec find_metric(store(), themis@internal@metric:metric_name(), binary()) -> {ok, {binary(), binary(), list(float())}} | {error, store_error()}. find_metric(Store, Name, Given_kind) -> Table = erlang:element(2, Store), gleam@result:'try'( case begin _pipe@1 = themis@internal@erlang@ets:lookup( Table, begin _pipe = Name, themis@internal@metric:name_to_string(_pipe) end ), gleam@list:map( _pipe@1, fun(Found) -> (gleam@dynamic:tuple4( fun gleam@dynamic:string/1, fun gleam@dynamic:string/1, fun gleam@dynamic:string/1, gleam@dynamic:list(fun gleam@dynamic:float/1) ))(Found) end ) end of [{ok, {_, Description, Kind, Buckets}}] -> {ok, {Description, Kind, Buckets}}; [] -> {error, metric_not_found}; _ -> {error, table_error} end, fun(_use0) -> {Description@1, Kind@1, Buckets@1} = _use0, case Kind@1 =:= Given_kind of false -> {error, invalid_type}; true -> {ok, {Description@1, Kind@1, Buckets@1}} end end ). -file("/git/Themis/src/themis/internal/store.gleam", 86). -spec match_metrics(store(), binary()) -> {ok, list({binary(), binary(), list(float())})} | {error, store_error()}. match_metrics(Store, Kind) -> Table = erlang:element(2, Store), _pipe = themis@internal@erlang@ets:match_metric(Table, Kind), _pipe@3 = gleam@list:map( _pipe, fun(Found) -> R = begin _pipe@1 = (gleam@dynamic:tuple4( fun gleam@dynamic:string/1, fun gleam@dynamic:string/1, fun gleam@dynamic:string/1, gleam@dynamic:list(fun gleam@dynamic:float/1) ))(Found), gleam@result:try_recover( _pipe@1, fun(E) -> {error, {decode_errors, E}} end ) end, gleam@result:'try'( R, fun(_use0) -> {Name, Description, _, Buckets} = _use0, _pipe@2 = {Name, Description, Buckets}, {ok, _pipe@2} end ) end ), gleam@result:all(_pipe@3). -file("/git/Themis/src/themis/internal/store.gleam", 109). -spec increment_record_by( store(), themis@internal@metric:metric_name(), themis@internal@label:label_set(), themis@number:number_() ) -> {ok, nil} | {error, store_error()}. increment_record_by(Store, Name, Labels, Value) -> case Value of {dec, _} -> _pipe = begin Table = erlang:element(3, Store), Labels@1 = themis@internal@label:to_strings(Labels), Name@1 = themis@internal@metric:name_to_string(Name), themis@internal@erlang@ets:counter_increment_by( Table, {Name@1, Labels@1}, Value ) end, {ok, _pipe}; {int, _} -> _pipe = begin Table = erlang:element(3, Store), Labels@1 = themis@internal@label:to_strings(Labels), Name@1 = themis@internal@metric:name_to_string(Name), themis@internal@erlang@ets:counter_increment_by( Table, {Name@1, Labels@1}, Value ) end, {ok, _pipe}; na_n -> {error, invalid_increment}; neg_inf -> {error, invalid_increment}; pos_inf -> {error, invalid_increment} end. -file("/git/Themis/src/themis/internal/store.gleam", 128). -spec increment_record( store(), themis@internal@metric:metric_name(), themis@internal@label:label_set() ) -> {ok, nil} | {error, store_error()}. increment_record(Store, Name, Labels) -> increment_record_by(Store, Name, Labels, themis@number:integer(1)). -file("/git/Themis/src/themis/internal/store.gleam", 136). -spec insert_record( store(), themis@internal@metric:metric_name(), themis@internal@label:label_set(), themis@number:number_() ) -> {ok, nil} | {error, store_error()}. insert_record(Store, Name, Labels, Value) -> Table = erlang:element(3, Store), Labels@1 = themis@internal@label:to_strings(Labels), {Int_value, Float_value, Flag_value} = case Value of {dec, Val} -> {0, Val, <<""/utf8>>}; {int, Val@1} -> {Val@1, +0.0, <<""/utf8>>}; pos_inf -> {0, +0.0, <<"+Inf"/utf8>>}; neg_inf -> {0, +0.0, <<"-Inf"/utf8>>}; na_n -> {0, +0.0, <<"NaN"/utf8>>} end, case themis@internal@erlang@ets:insert_raw( Table, {{begin _pipe = Name, themis@internal@metric:name_to_string(_pipe) end, Labels@1}, Int_value, Float_value, Flag_value} ) of false -> {error, insert_error}; true -> {ok, nil} end. -file("/git/Themis/src/themis/internal/store.gleam", 193). -spec decode_record(gleam@dynamic:dynamic_()) -> {ok, {themis@internal@label:label_set(), themis@number:number_()}} | {error, store_error()}. decode_record(Record) -> Record_result = begin _pipe = (gleam@dynamic:tuple4( gleam@dynamic:tuple2( fun gleam@dynamic:string/1, gleam@dynamic:list(fun gleam@dynamic:string/1) ), fun gleam@dynamic:int/1, fun gleam@dynamic:float/1, fun gleam@dynamic:string/1 ))(Record), gleam@result:try_recover( _pipe, fun(E) -> {error, {decode_errors, E}} end ) end, gleam@result:'try'( Record_result, fun(Record@1) -> {{_, Labels}, Int_value, Float_value, Flag} = Record@1, _assert_subject = gleam@float:modulo(Float_value, 1.0), {ok, Float_decimal} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"themis/internal/store"/utf8>>, function => <<"decode_record"/utf8>>, line => 208}) end, Numeric_value = case Float_decimal =:= +0.0 of false -> themis@number:decimal( begin _pipe@1 = Int_value, _pipe@2 = erlang:float(_pipe@1), gleam@float:add(_pipe@2, Float_value) end ); true -> themis@number:integer(Int_value) end, Value = case Flag of <<"-Inf"/utf8>> -> themis@number:negative_infinity(); <<"+Inf"/utf8>> -> themis@number:positive_infinity(); <<"NaN"/utf8>> -> themis@number:not_a_number(); _ -> Numeric_value end, Labels@1 = begin _pipe@3 = Labels, _pipe@4 = gleam@list:map( _pipe@3, fun(Label_string) -> _assert_subject@1 = gleam@string:split_once( Label_string, <<":"/utf8>> ), {ok, {Key, Value@1}} = case _assert_subject@1 of {ok, {_, _}} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail@1, module => <<"themis/internal/store"/utf8>>, function => <<"decode_record"/utf8>>, line => 222}) end, {Key, Value@1} end ), maps:from_list(_pipe@4) end, _assert_subject@2 = themis@internal@label:from_dict(Labels@1), {ok, Labels@2} = case _assert_subject@2 of {ok, _} -> _assert_subject@2; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail@2, module => <<"themis/internal/store"/utf8>>, function => <<"decode_record"/utf8>>, line => 226}) end, _pipe@5 = {Labels@2, Value}, {ok, _pipe@5} end ). -file("/git/Themis/src/themis/internal/store.gleam", 164). -spec match_records(store(), themis@internal@metric:metric_name()) -> {ok, gleam@dict:dict(themis@internal@label:label_set(), themis@number:number_())} | {error, store_error()}. match_records(Store, Name) -> Table = erlang:element(3, Store), _pipe@1 = themis@internal@erlang@ets:match_record( Table, begin _pipe = Name, themis@internal@metric:name_to_string(_pipe) end ), _pipe@2 = gleam@list:map(_pipe@1, fun decode_record/1), _pipe@3 = gleam@result:all(_pipe@2), gleam@result:map(_pipe@3, fun maps:from_list/1). -file("/git/Themis/src/themis/internal/store.gleam", 175). -spec find_record( store(), themis@internal@metric:metric_name(), themis@internal@label:label_set() ) -> {ok, {themis@internal@label:label_set(), themis@number:number_()}} | {error, store_error()}. find_record(Store, Name, Labels) -> Table = erlang:element(3, Store), _pipe@2 = case themis@internal@erlang@ets:lookup( Table, {begin _pipe = Name, themis@internal@metric:name_to_string(_pipe) end, begin _pipe@1 = Labels, themis@internal@label:to_strings(_pipe@1) end} ) of [Entry] -> {ok, Entry}; _ -> {error, single_result_expected} end, gleam@result:'try'(_pipe@2, fun decode_record/1).