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

{:error, "Table 'requests' could not be found"} #31

Open
KristerV opened this issue Nov 1, 2024 · 15 comments
Open

{:error, "Table 'requests' could not be found"} #31

KristerV opened this issue Nov 1, 2024 · 15 comments

Comments

@KristerV
Copy link

KristerV commented Nov 1, 2024

Hey, great library. I almost started writing this myself, but glad I didn't, because yours is so much better than what I had imagined.

So. Works in dev, deployed to fly.io and it produces an error. No events are logged, but the page opens.

2024-11-01T12:31:23Z app[2871ed6b664758] arn [info]** (MatchError) no match of right hand side value: {:error, "Table 'requests' could not be found"}
2024-11-01T12:31:23Z app[2871ed6b664758] arn [info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/repo.ex:215: PhoenixAnalytics.Repo.insert_many/1
2024-11-01T12:31:23Z app[2871ed6b664758] arn [info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/services/batcher.ex:101: PhoenixAnalytics.Services.Batcher.handle_info/2

and then some lines later it's

2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]** (MatchError) no match of right hand side value: {:error, "Catalog Error: Table with name requests does not exist!\nDid you mean \"pg_sequences\"?\nLINE 1: ...urce': path, 'visits': COUNT(*) } FROM requests\n                                                  ^"}
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/repo.ex:258: PhoenixAnalytics.Repo.execute_fetch/1
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/web/live/components/charts/popular_chart.ex:54: PhoenixAnalytics.Web.Live.Components.PopularChart.fetch_data/3
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/services/cache.ex:92: PhoenixAnalytics.Services.Cache.fetch/2
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/web/live/components/charts/popular_chart.ex:41: PhoenixAnalytics.Web.Live.Components.PopularChart.chart_data/2
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/web/live/components/charts/popular_chart.ex:34: anonymous fn/2 in PhoenixAnalytics.Web.Live.Components.PopularChart.update/2
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    (phoenix_live_view 1.0.0-rc.7) lib/phoenix_live_view/async.ex:148: anonymous fn/2 in Phoenix.LiveView.Async.assign_async/4
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    (phoenix_live_view 1.0.0-rc.7) lib/phoenix_live_view/async.ex:220: Phoenix.LiveView.Async.do_async/5
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    (elixir 1.17.2) lib/task/supervised.ex:101: Task.Supervised.invoke_mfa/2
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]Function: #Function<7.88405273/0 in Phoenix.LiveView.Async.run_async_task/5>
2024-11-01T12:31:38Z app[2871ed6b664758] arn [info]    Args: []

I would suspect that the migrations haven't been run, but as you know fly.io handles that and I haven't had any issues with migrations before.

Just to be clear I do have this migration.

defmodule MyApp.Repo.Migrations.AddPhoenixAnalytics do
  use Ecto.Migration

  def up, do: PhoenixAnalytics.Migration.up()
  def down, do: PhoenixAnalytics.Migration.down()
end

I checked manually and select * from schema_migrations; confirms the migrations have run.

and my config.exs is

config :phoenix_analytics,
  duckdb_path: System.get_env("DUCKDB_PATH") || "analytics.duckdb",
  app_domain: System.get_env("PHX_HOST") || "example.com"

I have not set the DUCKDB_PATH, as I understand there is no need? Prod does have HOST configured.

@dimitri4d
Copy link

I'm experiencing the same issue.

It seems in PhoenixAnalytics.Queries.Table, @db_alias is being appended directly to the table name, and attempt to create a table "postgres_db.requests" rather than just "requests".

defmodule PhoenixAnalytics.Queries.Table do
  @moduledoc false
  alias PhoenixAnalytics.Services.Utility

  @db_alias "postgres_db"
  @requests if Utility.mode() == :duck_postgres, do: "#{@db_alias}.requests", else: "requests"

  def name() do
    @requests
  end

  def create_requests do
    query = """
    CREATE TABLE IF NOT EXISTS #{@requests} (
      request_id UUID PRIMARY KEY,
      method VARCHAR NOT NULL,
      ...

@KristerV
Copy link
Author

KristerV commented Nov 6, 2024

docs to the Utility,.mode() are here: https://hexdocs.pm/phoenix_analytics/PhoenixAnalytics.Services.Utility.html#mode/0

so basically if both duck and postgres are configured that db_alias is used. in my case indeed both are used. question is what's different from my dev to prod.

@lalabuy948
Copy link
Owner

Hi @KristerV ,

Thank you for raising issue, I never worked with fly io. Could you please provide example how connection to db looks there?

As I can add simple parameter "ignore_alias" or something similar.

@KristerV
Copy link
Author

KristerV commented Nov 9, 2024

oh, right, i thought i read that you use fly.io actually.

i'll provide verbose info, who knows what will explain the issue.

First of all fly.io servers are shown as such:
image

The only secrets the app has are DATABASE_URL and SECRET_KEY_BASE.

Postgres server info:

image

image

It's worth noting that I tried looking for a requests table with a prefix or otherwise and could not find one. But I also couldn't find one in local dev (where analytics do work) so I guess I just don't know what I'm looking for. Is it really a DuckDB table?

Other than that there's not much more i can talk about the Postgres server. Don't think there's anything special about it.

App server

Is it possible that since DuckDB tries to make a local file that the app server is important to discuss? Fly creates a docker image and deploys that. Here's the Dockerfile:

# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian
# instead of Alpine to avoid DNS resolution issues in production.
#
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu
# https://hub.docker.com/_/ubuntu?tab=tags
#
# This file is based on these images:
#
#   - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
#   - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20240904-slim - for the release image
#   - https://pkgs.org/ - resource for finding needed packages
#   - Ex: hexpm/elixir:1.17.2-erlang-27.0.1-debian-bullseye-20240904-slim
#
ARG ELIXIR_VERSION=1.17.2
ARG OTP_VERSION=27.0.1
ARG DEBIAN_VERSION=bullseye-20240904-slim

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"

FROM ${BUILDER_IMAGE} as builder

# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git \
    && apt-get clean && rm -f /var/lib/apt/lists/*_*

# prepare build dir
WORKDIR /app

# install hex + rebar
RUN mix local.hex --force && \
    mix local.rebar --force

# set build ENV
ENV MIX_ENV="prod"

# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config

# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile

COPY priv priv

COPY lib lib

COPY assets assets

# compile assets
RUN mix assets.deploy

# Compile the release
RUN mix compile

# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/

COPY rel rel
RUN mix release

# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}

RUN apt-get update -y && \
  apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates \
  && apt-get clean && rm -f /var/lib/apt/lists/*_*

# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

WORKDIR "/app"
RUN chown nobody /app

# set runner ENV
ENV MIX_ENV="prod"

# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/kids ./

USER nobody

# If using an environment that doesn't automatically reap zombie processes, it is
# advised to add an init process such as tini via `apt-get install`
# above and adding an entrypoint. See https://github.com/krallin/tini for details
# ENTRYPOINT ["/tini", "--"]

CMD ["/app/bin/server"]

Then anything interesting for the deployment itself should be in fly.toml:

# fly.toml app configuration file generated for kids on 2024-10-28T16:19:07+02:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = 'kids'
primary_region = 'arn'
kill_signal = 'SIGTERM'

[build]

[deploy]
  release_command = '/app/bin/migrate'

[env]
  PHX_HOST = 'example.com'
  PORT = '8080'

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1
  processes = ['app']

  [http_service.concurrency]
    type = 'connections'
    hard_limit = 1000
    soft_limit = 1000

[[vm]]
  memory = '1gb'
  cpu_kind = 'shared'
  cpus = 1

Anything else that could help understand the issue?

@KristerV KristerV changed the title Plug and Play has errors in fly.io server {:error, "Table 'requests' could not be found"} Nov 11, 2024
@KristerV
Copy link
Author

KristerV commented Nov 11, 2024

What confuses me is that the mode is determined from the config:

def mode() do
duckdb_path = Application.fetch_env(:phoenix_analytics, :duckdb_path)
postgre_repo = Application.fetch_env(:phoenix_analytics, :postgres_conn)
cond do
duckdb_path != :error and postgre_repo == :error -> :duck_only
duckdb_path != :error and postgre_repo != :error -> :duck_postgres
true -> :duck_only
end
end

But in my config I don't have postgres configured..

edit: well i deployed a debug version of this repo (master) and this particular error is fixed apparently. it now knows it's not using postgres in the config. so the current state is better than the last version (0.2.1).

yet i get another error. from the code it seems like it's looking for the DuckDB table, but it doesn't exist.

[info]09:54:13.802 [error] Task #PID<0.5566.0> started from #PID<0.5558.0> terminating
[info]** (MatchError) no match of right hand side value: {:error, "Catalog Error: Table with name requests does not exist!\nDid you mean \"pg_sequences\"?\nLINE 1: SELECT count(DISTINCT remote_ip) FROM requests\n                                              ^"}
[info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/repo.ex:258: PhoenixAnalytics.Repo.execute_fetch/1
[info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/web/live/components/stats/single_stat.ex:71: PhoenixAnalytics.Web.Live.Components.SingleStat.fetch_stat_data/3
[info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/services/cache.ex:92: PhoenixAnalytics.Services.Cache.fetch/2
[info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/web/live/components/stats/single_stat.ex:55: PhoenixAnalytics.Web.Live.Components.SingleStat.stat_data/2
[info]    (phoenix_analytics 0.2.1) lib/phoenix_analytics/web/live/components/stats/single_stat.ex:45: anonymous fn/2 in PhoenixAnalytics.Web.Live.Components.SingleStat.update/2
[info]    (phoenix_live_view 1.0.0-rc.7) lib/phoenix_live_view/async.ex:148: anonymous fn/2 in Phoenix.LiveView.Async.assign_async/4
[info]    (phoenix_live_view 1.0.0-rc.7) lib/phoenix_live_view/async.ex:220: Phoenix.LiveView.Async.do_async/5
[info]    (elixir 1.17.2) lib/task/supervised.ex:101: Task.Supervised.invoke_mfa/2

so I SSH into the container and find that the duckdb file is right next to the executables, which are not persistent. in fact now that i think about it the whole container is ephermal. and creating a volume for it doesn't really make sense as fly.io gives you multiple physical machines per app by default. no point in scaling down.

so i'm going to go the other way and see if i can configure this on postgres.

@KristerV
Copy link
Author

KristerV commented Nov 11, 2024

if I configure like this:

config :phoenix_analytics,
  app_domain: System.get_env("PHX_HOST") || "example.com",
  postgres_conn: "dbname=phoenixanalytics user=postgres password=postgres host=localhost",
  cache_ttl: 120

Then I just get an error:

14:20:50.835 [info] == Running 20241101122212 MyApp.Repo.Migrations.AddPhoenixAnalytics.up/0 forward
** (FunctionClauseError) no function clause matching in Duckdbex.open/1    
    
    The following arguments were given to Duckdbex.open/1:
    
        # 1
        nil
    
    Attempted function clauses (showing 2 out of 2):
    
        def open(path) when is_binary(path)
        def open(%Duckdbex.Config{} = config)
    
    (duckdbex 0.3.6) Duckdbex.open/1
    (phoenix_analytics 0.2.1) lib/phoenix_analytics/migration.ex:11: PhoenixAnalytics.Migration.up/0
    (ecto_sql 3.12.1) lib/ecto/migration/runner.ex:310: Ecto.Migration.Runner.perform_operation/3
    (stdlib 6.0.1) timer.erl:590: :timer.tc/2
    (ecto_sql 3.12.1) lib/ecto/migration/runner.ex:25: Ecto.Migration.Runner.run/8
    (ecto_sql 3.12.1) lib/ecto/migrator.ex:365: Ecto.Migrator.attempt/8
    (ecto_sql 3.12.1) lib/ecto/migrator.ex:282: anonymous fn/5 in Ecto.Migrator.do_up/5
    (ecto_sql 3.12.1) lib/ecto/migrator.ex:337: anonymous fn/6 in Ecto.Migrator.async_migrate_maybe_in_transaction/7

So this means that PostgreSQL alone isn't enough. It must have DuckDB configured also (but why?), in which case I still get the error in the above post. I'm full of frustration.

All in all it seems PhoenixAnalytics does not support fly.io or clusters.

@lalabuy948 if you want to debug this maybe it makes sense to try fly.io? it's very popular in the Elixir community. They have a free tier and to deploy all you do is fly launch and it'll ask some questions and done soon. Very small effort. Please! :)

@lalabuy948
Copy link
Owner

Hi @KristerV

Could you add as well duck db path into your config?

In case you use Postgres as backend, duck db file will be empty, but it's still needed for duck db to operate properly.

@KristerV
Copy link
Author

okay, so

config.exs

config :phoenix_analytics,
  duckdb_path: System.get_env("DUCKDB_PATH") || "analytics.duckdb",
  app_domain: System.get_env("PHX_HOST") || "example.com",
  postgres_conn: "dbname=phoenixanalytics user=postgres password=postgres host=localhost",
  cache_ttl: 120

runtime.exs

  config :phoenix_analytics,
    app_domain: host,
    postgres_conn: database_url,
    cache_ttl: 120

so both postgres and duck have configs. but still same error:

[info]** (MatchError) no match of right hand side value: {:error, "Catalog Error: Table with name requests does not exist!\nDid you mean \"analytics.pg_catalog.pg_sequences\"?"}

what else can we try?

@lalabuy948
Copy link
Owner

Following up on that issue, I made a PR where I introduced an option not to touch disk at all.

I need to run performance tests and if it's gonna be ok, i will add it in next release.

@lalabuy948
Copy link
Owner

@capoccias
Copy link

capoccias commented Jan 14, 2025

Hey @lalabuy948 ,

I appear to be having the same/similar issue as mentioned here

Locally it's working but not in Fly.io

config.exs:

config :phoenix_analytics,
  app_domain: "example.com",
  postgres_conn: System.get_env("POSTGRES_CONN"),
  in_memory: true

Note I am using an entirely different database in a separate app for analytics:

defmodule App.AnalyticsRepo.Migrations.AddPhoenixAnalytics do
  use Ecto.Migration

  def up, do: PhoenixAnalytics.Migration.up()
  def down, do: PhoenixAnalytics.Migration.down()
end

Logs:

Running 20250113060527 App.AnalyticsRepo.Migrations.AddPhoenixAnalytics.up/0 forward
Failed to apply migration: Catalog Error: Schema with name postgres_db does not exist!
Migrated 20250113060527 in 0.1s

What's also annoying is that it's just printing the migration error so the migration succeeds despite not creating the requests table meaning I have to manually delete the row from schema_migrations to retry

My understanding is that this is only using postgres, not duckdb which seems odd that the only modes are :duck_only and :duck_postgres and not also :postgres_only but I may be mistaken

@lalabuy948 lalabuy948 reopened this Jan 16, 2025
@lalabuy948
Copy link
Owner

Hi @capoccias , indeed you are right. I think issue that I hard codded

 alias PhoenixAnalytics.Services.Utility
 
@db_alias "postgres_db"

Which I guess can be different.. What would most optimal way for you to add this db prefix?

@capoccias
Copy link

Hey @lalabuy948 ,

I'm at a bit of a loss as to what the fix would be here

I've tried manually creating the postgres_db schema and removing @db_alias but no luck

@mbnissen
Copy link

Im also struggling with getting this to work with postgres only

Also would be nice to use database_url for Fly.io instead of postgres_conn so you can use existing DATABASE_URL env variable

@mbnissen
Copy link

@lalabuy948 any updates for this? Im having same problem as @capoccias and cannot get it to work on Fly.io

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