From 8463d148775783da5318864a2a3b1f4289a11ede Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Fri, 13 Dec 2024 11:50:38 +0200 Subject: [PATCH] Improve available_selectors in getMetric's metadata If a metric is available in multiple modules, combine the available metrics when reporting in the API. --- .../available_metrics/available_metrics.ex | 3 +- lib/sanbase/metric/behaviour.ex | 2 ++ lib/sanbase/metric/metric.ex | 32 ++++++++++++++++++- .../resolvers/metric/metric_resolver.ex | 10 ++++++ .../graphql/schema/types/metric_types.ex | 4 ++- 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/lib/sanbase/available_metrics/available_metrics.ex b/lib/sanbase/available_metrics/available_metrics.ex index b6334b1a51..89d5e2f1ef 100644 --- a/lib/sanbase/available_metrics/available_metrics.ex +++ b/lib/sanbase/available_metrics/available_metrics.ex @@ -68,6 +68,7 @@ defmodule Sanbase.AvailableMetrics do metrics |> Enum.map(fn metric -> {:ok, m} = Sanbase.Metric.metadata(metric) + {:ok, available_selectors} = Sanbase.Metric.available_selectors(metric) %{ metric: m.metric, @@ -79,7 +80,7 @@ defmodule Sanbase.AvailableMetrics do frequency_seconds: Sanbase.DateTimeUtils.str_to_sec(m.min_interval), sanbase_access: "free", sanapi_access: "free", - available_selectors: m.available_selectors, + available_selectors: available_selectors, required_selectors: m.required_selectors, access: Map.get(access_map, metric) } diff --git a/lib/sanbase/metric/behaviour.ex b/lib/sanbase/metric/behaviour.ex index e05b56d6e6..a6a4c62aeb 100644 --- a/lib/sanbase/metric/behaviour.ex +++ b/lib/sanbase/metric/behaviour.ex @@ -121,6 +121,8 @@ defmodule Sanbase.Metric.Behaviour do @type available_label_fqns_result :: {:ok, list(String.t())} | {:error, String.t()} + @type available_selectors_result :: {:ok, list(atom())} | {:error, String.t()} + @type has_incomplete_data_result :: boolean() @type complexity_weight_result :: number() diff --git a/lib/sanbase/metric/metric.ex b/lib/sanbase/metric/metric.ex index fbb55b1fa4..40f7886890 100644 --- a/lib/sanbase/metric/metric.ex +++ b/lib/sanbase/metric/metric.ex @@ -430,6 +430,33 @@ defmodule Sanbase.Metric do end end + @doc ~s""" + Get the list of available selectors for a metric. + This is a separate function as it combines the available selectors from multiple + modules that implement the metric. + Most notably, social metrics from CH are precomptued only for slugs, while the + SocialData.MetricAdapter implements it for text, founders, etc. + """ + @spec available_selectors(metric) :: Type.available_selectors_result() + def available_selectors(metric) do + case get_module(metric, return_all_modules: true) do + nil -> + metric_not_available_error(metric) + + module_or_modules -> + available_selectors = + module_or_modules + |> List.wrap() + |> Enum.flat_map(fn module -> + {:ok, metadata} = apply(module, :metadata, [metric]) + metadata.available_selectors + end) + |> Enum.uniq() + + {:ok, available_selectors} + end + end + @doc ~s""" Get the first datetime for which a given metric is available for a given slug """ @@ -851,7 +878,10 @@ defmodule Sanbase.Metric do end true -> - metric_to_single_module(metric, opts) + case Keyword.get(opts, :return_all_modules, false) do + false -> metric_to_single_module(metric, opts) + true -> Map.get(Helper.metric_to_modules_map(), metric) + end end end diff --git a/lib/sanbase_web/graphql/resolvers/metric/metric_resolver.ex b/lib/sanbase_web/graphql/resolvers/metric/metric_resolver.ex index ee7102695f..a7bc4af0de 100644 --- a/lib/sanbase_web/graphql/resolvers/metric/metric_resolver.ex +++ b/lib/sanbase_web/graphql/resolvers/metric/metric_resolver.ex @@ -131,6 +131,16 @@ defmodule SanbaseWeb.Graphql.Resolvers.MetricResolver do end end + def get_available_selectors(_root, _args, %{source: %{metric: metric}}) do + case Metric.available_selectors(metric) do + {:ok, selectors} -> + {:ok, selectors} + + {:error, error} -> + {:error, handle_graphql_error("available_selectors", %{metric: metric}, error)} + end + end + def timeseries_data_complexity(_root, args, resolution) do # Explicitly set `child_complexity` to 2 as this would be the # value if both `datetime` and `value` fields are queried. diff --git a/lib/sanbase_web/graphql/schema/types/metric_types.ex b/lib/sanbase_web/graphql/schema/types/metric_types.ex index f4905215cb..a2c870396c 100644 --- a/lib/sanbase_web/graphql/schema/types/metric_types.ex +++ b/lib/sanbase_web/graphql/schema/types/metric_types.ex @@ -407,7 +407,9 @@ defmodule SanbaseWeb.Graphql.MetricTypes do Every metric has `availableSelectors` in its metadata, showing exactly which of the selectors can be used. """ - field(:available_selectors, list_of(:selector_name)) + field :available_selectors, list_of(:selector_name) do + resolve(&MetricResolver.get_available_selectors/3) + end @desc ~s""" The list of required selectors for the metric. It is used to show the list