Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report broken for long_running_queries since Ecto 3.12.0 #458

Closed
saveman71 opened this issue Dec 3, 2024 · 8 comments
Closed

Report broken for long_running_queries since Ecto 3.12.0 #458

saveman71 opened this issue Dec 3, 2024 · 8 comments

Comments

@saveman71
Copy link

saveman71 commented Dec 3, 2024

From my understanding, Ecto starting parsing :duration as %Duration structs in v3.12.0. We've seen a few errors that I attribute to the new type but I may be wrong.

Environment

  • Elixir version (elixir -v):
Erlang/OTP 27 [erts-15.1.1] [source] [64-bit] [smp:20:20] [ds:20:20:10] [async-threads:1] [jit:ns]

Elixir 1.17.3 (compiled with Erlang/OTP 27)
  • Phoenix version (mix deps): phoenix 1.7.14
  • Phoenix LiveView version (mix deps): phoenix_live_view 0.20.17
  • Phoenix Dashboard version (mix deps): phoenix_live_dashboard 0.8.5
  • Operating system: Linux
  • Browsers you attempted to reproduce this bug on (the more the merrier): N/A

Actual behavior

When accessing the dahsboard for long_running_queries, I get a 500. It works if they aren't any long queries.

How to repro : MyApp.Repo.query!("select pg_sleep(5 * 60);")

On prod the error is

UndefinedFunctionError

function Duration.compare/2 is undefined or private

On local, don't have exactly this one, I have Phoenix.HTML.Safe not implemented for %Duration{}.

[I] 12:15:01.986 Phoenix.Logger.phoenix_endpoint_stop/4:231 GA2mgGCyNXIdp_UABVZC Sent 500 in 71ms                                                                                                                                                                                         
[E] 12:15:02.006 nil.: #PID<0.18104.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.18103.0>, stream id 1) terminated                                                                                                                                                   
Server: app-local.digiforma.com:80 (http)                                                                                                                                                                                                                                                 
Request: GET /internal/dashboard/ecto_stats?nav=long_running_queries&repo=Digiforma.Repo                                                                                                                                                                                                  
** (exit) an exception was raised:                                                                                                                                                                                                                                                        
    ** (Protocol.UndefinedError) protocol Phoenix.HTML.Safe not implemented for %Duration{second: 3, microsecond: {283748, 6}} of type Duration (a struct). This protocol is implemented for the following type(s): Atom, BitString, Cldr.Unit, Date, DateTime, Decimal, Float, Integer, L
ist, Money, NaiveDateTime, Phoenix.LiveComponent.CID, Phoenix.LiveView.Component, Phoenix.LiveView.Comprehension, Phoenix.LiveView.JS, Phoenix.LiveView.Rendered, Time, Tuple, URI                                                                                                        
        (phoenix_html 4.1.1) lib/phoenix_html/safe.ex:1: Phoenix.HTML.Safe.impl_for!/1                                                                                                                                                                                                    
        (phoenix_html 4.1.1) lib/phoenix_html/safe.ex:15: Phoenix.HTML.Safe.to_iodata/1                                                                                                                                                                                                   
        (phoenix_live_dashboard 0.8.5) lib/phoenix/live_dashboard/pages/ecto_stats_page.ex:183: anonymous fn/4 in Phoenix.LiveDashboard.EctoStatsPage.render_repo_tab/1                                                                                                                   
        (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:391: Phoenix.LiveView.Diff.traverse/7                                                                                                                                                                                   
        (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:532: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7                                                                                                                                                         
        (elixir 1.17.3) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3                                                                                                                                                                                                             
        (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:389: Phoenix.LiveView.Diff.traverse/7                                                                                                                                                                                   
        (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:559: anonymous fn/3 in Phoenix.LiveView.Diff.traverse_comprehension/5                                                                                                                                                   
        (elixir 1.17.3) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3                                                                                                                                                                                                      
        (elixir 1.17.3) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3                                                                                                                                                                                                      
        (elixir 1.17.3) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3                                                                                                                                                                                                      
        (elixir 1.17.3) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3                                                                                                                                                                                                      
        (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:470: Phoenix.LiveView.Diff.traverse/7                                                                                                                                                                                   
        (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:559: anonymous fn/3 in Phoenix.LiveView.Diff.traverse_comprehension/5                                                                                                                                                   
        (elixir 1.17.3) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3                                                                                                                                                                                                      
        (elixir 1.17.3) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3                                                                                                                                                                                                      
        (elixir 1.17.3) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3                                                                                                                                                                                                      
        (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:480: Phoenix.LiveView.Diff.traverse/7                                                                                                                                                                                   
        (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:532: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7                                                                                                                                                         
        (elixir 1.17.3) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3                                                                                                                                                                                                             

image

Expected behavior

No 500 if there are long running queries

@josevalim
Copy link
Member

I believe there is something else going on here. Ecto only uses :duration if you explicitly declare the field as :duration, which our queries don't do. Postgrex may decode something as Duration, but you have to explicitly opt-in to that:

%Duration{} may only be used with Elixir 1.17.0+. Intervals will only be decoded into a %Duration{} struct if the option interval_decode_type: Duration is passed to Postgrex.Types.define/3.

Did you set that option by any chance in your project?

@saveman71
Copy link
Author

saveman71 commented Dec 3, 2024

Yup, I suspected that some magic was happening too here, thanks for pointing us to the right direction.

We do have a line that looks like this:

Postgrex.Types.define(AppCore.PostgrexTypes, [AppCore.PostgrexTypes.ExtCitext], interval_decode_type: Duration)

Can we somehow exclude the live_dashboard here?

@saveman71
Copy link
Author

Since this is set at the repo level we could create a new Repo without these options, but then... have to remember that the main repo will crash on those tabs. If i'm following correctly.

@josevalim
Copy link
Member

I will submit a PR to Elixir and the Ecto stats project. But it will require Elixir v1.18. Meanwhile you can remove the option or disable these pages from the dashboard (or use a separate repo).

@saveman71
Copy link
Author

saveman71 commented Dec 3, 2024

We don't mind those pages crashing if we know why, we have other tools to get the long running queries in the meantime. The main driver for opening this issue was letting people know in case they ran in the same problem, as we didn't find any existing reports.

Thank you for the help troubleshooting and for handling it, no rush. Shall I close the issue?

@akash-akya
Copy link

akash-akya commented Dec 30, 2024

@josevalim I am still seeing the issue. It seems we are not actually calling format_value function from ecto_psql_extras in lib/phoenix/live_dashboard/pages/ecto_stats_page.ex?

This change based on your change fixed it for me:

--- lib/phoenix/live_dashboard/pages/ecto_stats_page.ex	2024-12-30 18:11:20.089569036 +0530
+++ lib/phoenix/live_dashboard/pages/ecto_stats_page.ex	2024-12-30 18:14:23.821469335 +0530
@@ -3,7 +3,7 @@
   use Phoenix.LiveDashboard.PageBuilder
   import Phoenix.LiveDashboard.Helpers
 
-  @compile {:no_warn_undefined, [Decimal, EctoPSQLExtras, {Ecto.Repo, :all_running, 0}]}
+  @compile {:no_warn_undefined, [Decimal, Duration, EctoPSQLExtras, {Ecto.Repo, :all_running, 0}]}
   @disabled_link "https://hexdocs.pm/phoenix_live_dashboard/ecto_stats.html"
   @page_title "Ecto Stats"
 
@@ -277,7 +277,7 @@
     {sorted, length(rows)}
   end
 
-  defp format(_, %struct{} = value) when struct in [Decimal, Postgrex.Interval],
+  defp format(_, %struct{} = value) when struct in [Decimal, Duration, Postgrex.Interval],
     do: struct.to_string(value)
 
   defp format(:bytes, value) when is_integer(value),

Environment

All are latest versions:

  • Elixir Version: 1.18.1
  • phoenix_live_dashboard: 0.8.5
  • ecto_psql_extras: 0.8.3

SteffenDE added a commit that referenced this issue Dec 30, 2024
@SteffenDE
Copy link
Contributor

@akash-akya your change looks good to me, opened #464!

josevalim pushed a commit that referenced this issue Dec 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@josevalim @saveman71 @SteffenDE @akash-akya and others