如何将 Ecto 连接到 CockroachDB Serverless?

How do I connect Ecto to CockroachDB Serverless?

我想为我的 Ecto 应用程序使用 CockroachDB Serverless。如何指定连接字符串?

我在尝试连接时遇到这样的错误。

[error] GenServer #PID<0.295.0> terminating
** (Postgrex.Error) FATAL 08004 (sqlserver_rejected_establishment_of_sqlconnection) codeParamsRoutingFailed: missing cluster name in connection string
    (db_connection 2.4.1) lib/db_connection/connection.ex:100: DBConnection.Connection.connect/2

CockroachDB Serverless 表示通过在连接字符串中包含集群名称进行连接,如下所示:

postgresql://username:<ENTER-PASSWORD>@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--cluster%3Dcluster-name-1234

但我不确定如何让 Ecto 通过其配置创建此连接字符串。

此配置允许 Ecto 正确连接到 CockroachDB Serverless:

config :myapp, MyApp.repo,
  username: "username",
  password: "xxxx",
  database: "defaultdb",
  hostname: "free-tier.gcp-us-central1.cockroachlabs.cloud",
  port: 26257,
  ssl: true,
  ssl_opts: [
    cert_pem: "foo.pem",
    key_pem:  "bar.pem"
  ],
  show_sensitive_data_on_connection_error: true,
  pool_size: 10,
  parameters: [
    options: "--cluster=cluster-name-1234"
  ]

问题是 Postgrex 无法解析来自连接 URL 的所有信息 - 没有 table SSL 配置。解决方案是显式指定连接参数,包括 cacertfile SSL 选项。假设您已经将集群的 CA 证书下载到 priv/certs/ca-cert.crt,您可以使用以下配置作为模板:

config :my_app, MyApp.Repo,
  username: "my_user",
  password: "my_password",
  database: "defaultdb",
  hostname: "free-tier.gcp-us-central1.cockroachlabs.cloud",
  port: "26257",
  ssl: true,
  ssl_opts: [
    cacertfile: Path.expand("priv/certs/ca-cert.crt"),
  ],
  parameters: [options: "--cluster=my-cluster-123"]

可能的其他问题

Table 锁定

由于 CockroachDB 也不支持 Ecto/Postgrex 尝试迁移 table 的锁定,因此也需要禁用 :migration_lock 配置:

config :my_app, MyApp.Repo,
  # ...
  migration_lock: false

授权生成器

最后,新的 phx.gen.auth 生成器默认使用 citext 扩展以不区分大小写的方式存储用户的电子邮件地址。生成的迁移中执行 CREATE EXTENSION IF NOT EXISTS citext 的行应删除,:email 字段的列类型应从 :citext 更改为 :string