index.ts 5.86 KB
Newer Older
duanjinfei's avatar
duanjinfei committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
// Follow this setup guide to integrate the Deno language server with your editor:
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.

// Setup type definitions for built-in Supabase Runtime APIs
import "jsr:@supabase/functions-js/edge-runtime.d.ts"
import { createClient } from 'jsr:@supabase/supabase-js@2'

// 分页查询函数
async function fetchAllData(supabase, table: string, pageSize: number = 1000) {
  let allData: any[] = [];
  let offset = 0;

  while (true) {
    const { data, error } = await supabase
      .from(table)
      .select('*') // 可以根据需要调整字段
      .gt('is_show_num', 0)
      // .eq('is_show', 1)
      .order('created_at', { ascending: true }) // 按照创建时间排序
      .range(offset, offset + pageSize - 1); // 分页范围

    if (error) {
      console.error(`Error fetching data from ${table}:`, error);
      throw error;
    }

    if (data && data.length > 0) {
      allData = allData.concat(data); // 合并当前页数据
      offset += pageSize; // 移动到下一页
    } else {
      break; // 如果没有更多数据,则退出循环
    }
  }

  return allData;
}

const getTimestampForMidnight3AM = () => {
  const timestamp = Math.floor(Date.now() / 3600000) * 3600; // 计算整点的时间戳
  return timestamp

};

async function cacheTaskCount(supabase, directory, bucketName) {
  const pageFileName = `${directory}/task_count.json`;

  // // 获取所有任务组 ID
  // const { data: taskGroupArr, error: groupError } = await supabase
  //   .from('task')
  //   .select('task_group_id');

  // if (groupError) {
  //   console.error("Error fetching task groups:", groupError);
  //   return;
  // }

  // // 提取所有任务组 ID
  // const groupIds = taskGroupArr.map(group => group.task_group_id);

  // // 使用 IN 操作符来一次性查询所有匹配的任务组任务数量
  // const { data, error } = await supabase
  //   .from('taskcenter.task')
  //   .select('group_id, id', { count: 'exact' })
  //   .in('group_id', groupIds);

  // if (error) {
  //   console.error("Error fetching task counts:", error);
  //   return;
  // }
  const pageJson = JSON.stringify({
    total_count: 4,
  });

  const { error: pageUploadError } = await supabase.storage
    .from(bucketName)
    .upload(pageFileName, new Blob([pageJson]), {
      contentType: 'application/json',
      upsert: true,
    });

  if (pageUploadError) {
    console.error(`Error uploading cacheTaskCount JSON:`, pageUploadError);
  } else {
    console.log(`Uploading cacheTaskCount JSON scuccessful`);
  }
}

async function cacheRecommendApp(supabase, allApps, directory, bucketName) {
  const recommendPageSize = 3;
  const recommendApps = allApps.filter(app => app.recommend > 0)
    .sort((a, b) => b.recommend - a.recommend);  // 按 recommend 字段降序排序
  const recommendTotalCount = recommendApps.length;
  const recommendPaginatedApps = [];
  for (let i = 0; i < recommendTotalCount; i += recommendPageSize) {
    recommendPaginatedApps.push(recommendApps.slice(i, i + recommendPageSize));
  }

  console.log("total page:", recommendPaginatedApps.length);

  // 遍历分页后的数据并上传
  for (let pageNum = 1; pageNum <= recommendPaginatedApps.length; pageNum++) {
    const pageApps = recommendPaginatedApps[pageNum - 1];

    const pageJson = JSON.stringify({
      total_count: recommendTotalCount,
      apps: pageApps,
    });

    const pageFileName = `${directory}/app_recommend_${pageNum}.json`;

    const { error: pageUploadError } = await supabase.storage
      .from(bucketName)
      .upload(pageFileName, new Blob([pageJson]), {
        contentType: 'application/json',
        upsert: true,
      });

    if (pageUploadError) {
      console.error(`Error uploading page ${pageNum} JSON:`, pageUploadError);
    } else {
      console.log(`Uploading page app_recommend_${pageNum}.json JSON successful`);
    }
  }
}

// Mark the longRunningTask's returned promise as a background task.
// note: we are not using await because we don't want it to block.

// Use beforeunload event handler to be notified when function is about to shutdown
addEventListener('beforeunload', (ev) => {
  console.log('Function will be shutdown due to', ev.detail?.reason)

  // save state or log the current progress
})

Deno.serve(async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }
  try {
    // const { name } = await req.json()
    const supabase = createClient(
      Deno.env.get('SUPABASE_URL') ?? '',
      Deno.env.get('SUPABASE_ANON_KEY') ?? '',
      { global: { headers: { Authorization: req.headers.get('Authorization')! } } }
    )
    // 获取所有 app 数据
    const allApps = await fetchAllData(supabase, 'app');
    // 获取当前时间的整点时间戳
    const timestamp = getTimestampForMidnight3AM();

    // 上传所有 app 数据到 storage
    const directory = `app-category/${timestamp}`;
    const bucketName = 'cache'; // 替换为存储桶名称

    EdgeRuntime.waitUntil(cacheTaskCount(supabase, directory, bucketName));

    EdgeRuntime.waitUntil(cacheRecommendApp(supabase, allApps, directory, bucketName));

    // (async () => {
    //   try {
    //     await cacheTaskCount(supabase, directory, bucketName)

    //     await cacheRecommendApp(supabase, allApps, directory, bucketName)
    //   } catch (error) {
    //     console.error('Background crawl error:', error)
    //   }
    // })()

    return new Response(
      JSON.stringify({
        message: 'All data uploaded successfully',
      }),
      {
        headers: { 'Content-Type': 'application/json' },
        status: 200
      }
    );
  } catch (err) {
    console.error('Unexpected error:', err);
    return new Response(JSON.stringify({ error: 'Internal server error' }), {
      headers: { 'Content-Type': 'application/json' },
      status: 500,
    });
  }
})