You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Absinthe Middleware中调用FunWithFlags出现ets.lookup ArgumentError

问题原因

你的报错根源是调用时机错误:Absinthe的middleware/3回调属于编译期执行逻辑,仅在Schema模块编译时运行,用于组装整个Schema的中间件列表,并不会在每次GraphQL请求时触发。
你直接在middleware/3顶层调用FunWithFlags.enabled?(:some_flag),相当于代码编译阶段就会执行这个调用,此时应用还没完成启动流程,FunWithFlags依赖的ETS缓存表、Redis/数据库连接都还没初始化,自然会抛出ETS查找失败的错误。
你修改配置关闭缓存不生效也是同理:编译阶段配置还没完成加载,哪怕缓存关了,此时连持久化存储的连接都不存在,调用依然会失败。

解决方法

把特征开关的判断逻辑移到运行时执行的中间件函数内部即可,middleware/3回调仅用于注册中间件,不要在这一层执行运行时逻辑。
两种常用实现方案:

方案1:直接匿名函数实现

defmodule MyApp.Schema do
  use Absinthe.Schema
  # ... 其他Schema代码

  def middleware(middleware, field, object) do
    # 编译阶段仅组装中间件列表,不执行开关判断
    flag_check_middleware = fn resolution ->
      # 这里的逻辑会在每次请求处理时运行,此时应用已完全启动
      if FunWithFlags.enabled?(:some_flag) do
        # 开关开启时的处理逻辑
        resolution
      else
        # 开关关闭时的处理逻辑,比如返回错误
        Absinthe.Resolution.put_result(resolution, {:error, "该功能暂未开放"})
      end
    end

    [flag_check_middleware | middleware]
  end
end

方案2:封装为独立中间件模块(更适合复用)

# 单独定义中间件模块
defmodule MyApp.Middleware.SomeFlagCheck do
  @behaviour Absinthe.Middleware

  @impl true
  def call(resolution, _opts) do
    if FunWithFlags.enabled?(:some_flag) do
      resolution
    else
      Absinthe.Resolution.put_result(resolution, {:error, "feature not available"})
    end
  end
end

# 在Schema中注册
defmodule MyApp.Schema do
  use Absinthe.Schema
  # ... 其他代码

  def middleware(middleware, field, object) do
    # 仅注册中间件,不执行实际判断
    [MyApp.Middleware.SomeFlagCheck | middleware]
  end
end

如果你的需求确实是编译阶段根据开关做分支逻辑裁剪,可以直接使用Elixir自带的编译时环境变量,不要依赖FunWithFlags这类运行时特征开关工具。


内容的提问来源于stack exchange,提问作者catra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 17:36:03