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

如何在Postgres数据满足特定条件时触发后台生成Report任务?

用户购完区域所有报告后自动触发后台生成新报告的实现方案

一、先修正表结构语法问题

你提供的SQL存在语法错误,先修正为可执行的生产版本:

-- 定义region枚举类型
create type region as enum (
  'America',
  'Europe',
  'Asia',
  'Africa'
);

-- 创建report表
create table report (
  id serial primary key,
  region region,
  generated_text text  -- 修正冒号语法错误
);

-- 创建report_user关联表(添加外键约束与唯一索引)
create table report_user(
  id serial primary key,
  report_id int not null references report(id),  -- 关联report主键(serial对应int类型)
  user_id uuid not null references auth.users(id),  -- 关联Supabase内置用户表
  unique(report_id, user_id)  -- 防止用户重复购买同一报告
);

二、创建数据库触发器函数(检查购完状态)

编写PostgreSQL函数,在用户插入购买记录后,自动检查该用户是否已购买对应区域的所有报告:

create or replace function check_if_all_reports_purchased()
returns trigger as $$
declare
  target_region region;
  total_region_reports int;
  user_purchased_count int;
begin
  -- 获取当前购买报告所属的区域
  select region into target_region from report where id = new.report_id;

  -- 统计该区域的总报告数量
  select count(*) into total_region_reports from report where region = target_region;

  -- 统计当前用户在该区域已购买的报告数
  select count(distinct ru.report_id) into user_purchased_count
  from report_user ru
  join report r on ru.report_id = r.id
  where ru.user_id = new.user_id and r.region = target_region;

  -- 若用户已购买该区域所有报告,触发后台生成任务
  if user_purchased_count = total_region_reports then
    -- 调用Supabase Edge Function异步执行AI生成逻辑
    perform http_post(
      'https://<你的Supabase项目ID>.functions.supabase.co/generate-new-report',
      json_build_object('region', target_region)::text,
      'application/json'
    );
  end if;

  return new;
end;
$$ language plpgsql security definer;

三、创建触发器绑定购买事件

将触发器函数关联到report_user表的INSERT操作上,确保每次购买后自动执行检查:

create trigger after_report_purchase
after insert on report_user
for each row
execute function check_if_all_reports_purchased();

四、编写Supabase Edge Function处理AI生成逻辑

创建异步Edge Function处理AI调用与报告插入,避免阻塞数据库事务:

// supabase/functions/generate-new-report/index.ts
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

serve(async (req) => {
  const { region } = await req.json();
  const supabase = createClient(
    Deno.env.get("SUPABASE_URL")!,
    Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!
  );

  try {
    // 调用AI API生成报告内容(替换为你的AI接口逻辑)
    const aiResponse = await fetch("https://你的AI服务接口地址", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ prompt: `生成一份关于${region}的行业分析报告` })
    });
    const generatedText = await aiResponse.text();

    // 将新报告插入数据库
    await supabase.from("report").insert({ region, generated_text: generatedText });

    return new Response(JSON.stringify({ success: true }), { status: 200 });
  } catch (error) {
    console.error("报告生成失败:", error);
    return new Response(JSON.stringify({ success: false, error: error.message }), { status: 500 });
  }
});

部署该Edge Function到Supabase:

supabase functions deploy generate-new-report

五、NextJS购买流程调整

在NextJS的购买接口中,保持原有逻辑优先返回未购买报告,无可用报告时直接告知用户后台生成中:

// app/api/purchase/route.ts
import { createClient } from '@supabase/supabase-js';
import { NextResponse } from 'next/server';

const supabase = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!);

export async function POST(req: Request) {
  const { userId, region } = await req.json();

  // 查询用户未购买的该区域报告
  const { data: availableReports } = await supabase
    .from('report')
    .select('id')
    .not('id', 'in', () => 
      supabase.from('report_user')
        .select('report_id')
        .eq('user_id', userId)
    )
    .eq('region', region)
    .limit(1);

  if (availableReports?.length) {
    // 插入购买记录并返回报告ID
    await supabase.from('report_user').insert({
      report_id: availableReports[0].id,
      user_id: userId
    });
    return NextResponse.json({ reportId: availableReports[0].id });
  } else {
    // 无可用报告,告知用户后台生成中(触发器会自动触发生成逻辑)
    return NextResponse.json({ message: '报告正在生成,请稍后刷新查看' }, { status: 202 });
  }
}

关键注意事项

  • 异步优先:必须用Edge Function或异步任务队列处理AI生成,禁止在数据库触发器中直接执行慢操作,避免阻塞事务。
  • 权限安全:触发器函数使用security definer,需严格控制函数权限,避免SQL注入风险。
  • 幂等处理:AI生成逻辑需添加幂等校验,比如生成前检查该区域是否已有待生成的报告,避免重复生成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 08:14:52