From 7c6ca2a1263c035674e785f0bb697ba60b7373a4 Mon Sep 17 00:00:00 2001 From: michaeljguarino Date: Fri, 8 Nov 2024 13:27:57 -0500 Subject: [PATCH] Prerelease touchups (#1568) --- lib/console/ai/chat.ex | 2 +- lib/console/ai/fixer.ex | 2 +- lib/console/ai/goth_manager.ex | 6 +++- .../pubsub/protocols/notifiable.ex | 26 ++++++++++++---- lib/console/retrier.ex | 30 +++++++++++++++++++ 5 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 lib/console/retrier.ex diff --git a/lib/console/ai/chat.ex b/lib/console/ai/chat.ex index 1ff6fa32e3..93a8665cb7 100644 --- a/lib/console/ai/chat.ex +++ b/lib/console/ai/chat.ex @@ -23,7 +23,7 @@ defmodule Console.AI.Chat do @summary """ The following is a chat log about a topic in DevOps, focusing primarily on kubernetes and infrastructure as code issues. Provide a single sentence - easily understandable title for the conversation with at most 10 words. The title should beunderstandable without context of the conversation. + easily understandable title for the conversation with at most 8 words. The title should be understandable without context of the conversation. """ @chat """ diff --git a/lib/console/ai/fixer.ex b/lib/console/ai/fixer.ex index 044e33c8dd..ede2d08db1 100644 --- a/lib/console/ai/fixer.ex +++ b/lib/console/ai/fixer.ex @@ -38,5 +38,5 @@ defmodule Console.AI.Fixer do |> when_ok(&fix/1) end - defp ask(prompt), do: prompt ++ [{:user, "please provide the most cogent code or configuration change available based on the information I've already provided above to fix this issue"}] + defp ask(prompt), do: prompt ++ [{:user, "please provide the most cogent code or configuration change available based on the information I've already provided above to fix this issue. Be sure the Git repository and full file names that are needed to change."}] end diff --git a/lib/console/ai/goth_manager.ex b/lib/console/ai/goth_manager.ex index ca0b6b0c41..51f4351ff0 100644 --- a/lib/console/ai/goth_manager.ex +++ b/lib/console/ai/goth_manager.ex @@ -11,7 +11,11 @@ defmodule Console.AI.GothManager do {:ok, %State{}} end - def fetch(creds), do: GenServer.call(__MODULE__, {:fetch, creds}) + def fetch(creds) do + Console.Retrier.retry(fn -> + GenServer.call(__MODULE__, {:fetch, creds}) + end, pause: 50, max: 2) + end def handle_call({:fetch, creds}, _, %State{credentials: creds} = state) do {:reply, Goth.fetch(__MODULE__), state} diff --git a/lib/console/deployments/pubsub/protocols/notifiable.ex b/lib/console/deployments/pubsub/protocols/notifiable.ex index 68b693ef76..1c505ec7f4 100644 --- a/lib/console/deployments/pubsub/protocols/notifiable.ex +++ b/lib/console/deployments/pubsub/protocols/notifiable.ex @@ -36,6 +36,11 @@ defmodule Console.Deployments.Notifications.Utils do end end + def nested_dedupe([{scope, opts} | rest], fun) when is_list(opts), + do: deduplicate(scope, fn -> nested_dedupe(rest, fun) end, opts) + def nested_dedupe([scope | rest], fun), do: deduplicate(scope, fn -> nested_dedupe(rest, fun) end) + def nested_dedupe([], fun) when is_function(fun), do: fun.() + def filters(%Service{id: id, cluster_id: cid}), do: [service_id: id, cluster_id: cid] def filters(%Cluster{id: id}), do: [cluster_id: id] def filters(%Pipeline{id: id}), do: [pipeline_id: id] @@ -123,8 +128,11 @@ defimpl Console.Deployments.PubSub.Notifiable, for: Console.PubSub.ServiceInsigh alias Console.Schema.AiInsight require Logger - def message(%{item: {svc, %AiInsight{text: t} = insight}}) when byte_size(t) > 0 do - Utils.deduplicate({:svc_insight, svc.id}, fn -> + def message(%{item: {svc, %AiInsight{text: t, sha: sha} = insight}}) when byte_size(t) > 0 do + Utils.nested_dedupe([ + {{:insight_sha, sha}, [ttl: :timer.hours(24)]}, + {:svc_insight, svc.id} + ], fn -> svc = Console.Repo.preload(svc, [:cluster, :repository]) {"service.insight", Utils.filters(svc), %{service: svc, insight: insight, text: Utils.insight(insight)}} end) @@ -137,8 +145,11 @@ defimpl Console.Deployments.PubSub.Notifiable, for: Console.PubSub.StackInsight alias Console.Schema.AiInsight require Logger - def message(%{item: {stack, %AiInsight{text: t} = insight}}) when byte_size(t) > 0 do - Utils.deduplicate({:stack_insight, stack.id}, fn -> + def message(%{item: {stack, %AiInsight{text: t, sha: sha} = insight}}) when byte_size(t) > 0 do + Utils.nested_dedupe([ + {{:insight_sha, sha}, [ttl: :timer.hours(24)]}, + {:stack_insight, stack.id} + ], fn -> stack = Console.Repo.preload(stack, [:cluster, :repository]) {"stack.insight", Utils.filters(stack), %{stack: stack, insight: insight, text: Utils.insight(insight)}} end) @@ -151,8 +162,11 @@ defimpl Console.Deployments.PubSub.Notifiable, for: Console.PubSub.ClusterInsigh alias Console.Schema.AiInsight require Logger - def message(%{item: {cluster, %AiInsight{text: t} = insight}}) when byte_size(t) > 0 do - Utils.deduplicate({:cluster_insight, cluster.id}, fn -> + def message(%{item: {cluster, %AiInsight{text: t, sha: sha} = insight}}) when byte_size(t) > 0 do + Utils.nested_dedupe([ + {{:insight_sha, sha}, [ttl: :timer.hours(24)]}, + {:cluster_insight, cluster.id} + ], fn -> {"cluster.insight", Utils.filters(cluster), %{cluster: cluster, insight: insight, text: Utils.insight(insight)}} end) end diff --git a/lib/console/retrier.ex b/lib/console/retrier.ex new file mode 100644 index 0000000000..92f913a861 --- /dev/null +++ b/lib/console/retrier.ex @@ -0,0 +1,30 @@ +defmodule Console.Retrier do + require Logger + + defstruct [:retry, :res, max: 3, pause: 100] + + def new(opts), do: struct(__MODULE__, opts) + + def retry(fun, opts \\ []), do: do_retry(new(opts), fun) + + defp do_retry(%__MODULE__{max: r, retry: r, res: res}, _), do: res + defp do_retry(%__MODULE__{retry: r, pause: p} = retrier, fun) do + if r > 0 do + :timer.sleep(p + jitter(p)) + end + + try do + case fun.() do + {:error, _} = res -> do_retry(%{retrier | retry: r + 1, res: res}, fun) + :error -> do_retry(%{retrier | retry: r + 1, res: :error}, fun) + res -> res + end + rescue + err -> + Logger.error(Exception.format(:error, err, __STACKTRACE__)) + do_retry(%{retrier | retry: r + 1, res: {:error, {:exception, err}}}, fun) + end + end + + defp jitter(pause), do: :rand.uniform(floor(pause / 2)) - :timer.seconds(floor(pause / 4)) +end