Skip to content

Commit

Permalink
Add availableFounders to getMetric's metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanIvanoff committed Dec 13, 2024
1 parent a261c27 commit 231ee9d
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 1 deletion.
18 changes: 18 additions & 0 deletions lib/sanbase/clickhouse/founders/founders.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule Sanbase.Clickhouse.Founders do
def get_founders() do
query = get_founders_query()

Sanbase.ClickhouseRepo.query_transform(query, fn [name, slug] ->
%{name: name, slug: slug}
end)
end

defp get_founders_query() do
sql = """
SELECT name, slug
FROM founder_metadata
"""

Sanbase.Clickhouse.Query.new(sql, %{})
end
end
23 changes: 23 additions & 0 deletions lib/sanbase_web/graphql/resolvers/metric/metric_resolver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,29 @@ defmodule SanbaseWeb.Graphql.Resolvers.MetricResolver do
end
end

def get_available_founders(_root, _args, %{source: %{metric: metric}}) do
with {:ok, selectors} <- Metric.available_selectors(metric) do
case :founders in selectors do
true ->
with {:ok, data} <- Sanbase.Clickhouse.Founders.get_founders() do
slugs = Enum.map(data, & &1.slug)
projects = Sanbase.Project.List.by_slugs(slugs)
slug_to_project_map = Map.new(projects, &{&1.slug, &1})

result =
Enum.map(data, fn map ->
Map.put(map, :project, slug_to_project_map[map.slug])
end)

{:ok, result}
end

false ->
{:ok, []}
end
end
end

def get_human_readable_name(_root, _args, %{source: %{metric: metric}}),
do: Metric.human_readable_name(metric)

Expand Down
9 changes: 9 additions & 0 deletions lib/sanbase_web/graphql/schema/types/metric_types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ defmodule SanbaseWeb.Graphql.MetricTypes do
value(:table)
end

object :founder do
field(:name, non_null(:string))
field(:project, :project)
end

object :broken_data do
field(:from, non_null(:datetime))
field(:to, non_null(:datetime))
Expand Down Expand Up @@ -411,6 +416,10 @@ defmodule SanbaseWeb.Graphql.MetricTypes do
resolve(&MetricResolver.get_available_selectors/3)
end

field :available_founders, list_of(:founder) do
cache_resolve(&MetricResolver.get_available_founders/3)
end

@desc ~s"""
The list of required selectors for the metric. It is used to show the list
of selectors that is required in order to fetch the metric.
Expand Down
55 changes: 54 additions & 1 deletion test/sanbase_web/graphql/metric/api_metric_metadata_test.exs
Original file line number Diff line number Diff line change
@@ -1,11 +1,64 @@
defmodule SanbaseWeb.Graphql.ApiMetricMetadataTest do
use SanbaseWeb.ConnCase, async: false

import Sanbase.Factory, only: [rand_str: 0]
import Sanbase.Factory
import SanbaseWeb.Graphql.TestHelpers

alias Sanbase.Metric

test "returns data for availableFounders", %{conn: conn} do
metrics_with_founders =
Metric.available_metrics()
|> Enum.filter(fn m ->
{:ok, selectors} = Metric.available_selectors(m)

:founders in selectors
end)

insert(:project, %{name: "Ethereum", ticker: "ETH", slug: "ethereum"})
insert(:project, %{name: "Bitcoin", ticker: "BTC", slug: "bitcoin"})

rows = [
["Vitalik Buterin", "ethereum"],
["Satoshi Nakamoto", "bitcoin"]
]

query = fn metric ->
"""
{
getMetric(metric: "#{metric}"){
metadata{
availableFounders{ name project{ name } }
}
}
}
"""
end

Sanbase.Mock.prepare_mock2(&Sanbase.ClickhouseRepo.query/2, {:ok, %{rows: rows}})
|> Sanbase.Mock.run_with_mocks(fn ->
for metric <- metrics_with_founders do
result =
conn
|> post("/graphql", query_skeleton(query.(metric)))
|> json_response(200)
|> get_in(["data", "getMetric", "metadata", "availableFounders"])

assert %{"name" => "Vitalik Buterin", "project" => %{"name" => "Ethereum"}} in result
assert %{"name" => "Satoshi Nakamoto", "project" => %{"name" => "Bitcoin"}} in result
end
end)

result =
conn
|> post("/graphql", query_skeleton(query.("price_usd")))
|> json_response(200)
|> get_in(["data", "getMetric", "metadata", "availableFounders"])

# No founders for metrics without founders in their selectors
assert result == []
end

test "returns data for all available metric", %{conn: conn} do
metrics = Metric.available_metrics() |> Enum.shuffle()

Expand Down

0 comments on commit 231ee9d

Please sign in to comment.