Ctrl K
ComunidadGuías…

server/db/operate/daily.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// 每日精选配置操作

'use server'

import { db } from '~/server/lib/db'
import { fetchConfigsByKeys } from '~/server/db/query/configs'
import { revalidateConfigCache, revalidateGalleryCache } from '~/server/lib/cache'
import { toDailyConfig } from '~/server/lib/config-transform'

/**
 * 检查并刷新每日精选图片
 * 根据配置的刷新间隔,判断是否需要刷新物化视图
 */
export async function checkAndRefreshDailyImages() {
  const rows = await fetchConfigsByKeys([
    'daily_enabled',
    'daily_refresh_interval',
    'daily_last_refresh',
  ])
  const { dailyEnabled, dailyRefreshInterval, dailyLastRefresh } = toDailyConfig(rows)

  if (!dailyEnabled) {
    return
  }

  const intervalHours = parseInt(dailyRefreshInterval, 10)
  const lastRefresh = dailyLastRefresh ? new Date(dailyLastRefresh).getTime() : 0

  const now = Date.now()
  const intervalMs = intervalHours * 60 * 60 * 1000

  if (now > lastRefresh + intervalMs) {
    const lockResult = await db.$queryRaw<Array<{ pg_try_advisory_lock: boolean }>>`SELECT pg_try_advisory_lock(42)`
    if (!lockResult[0]?.pg_try_advisory_lock) return
    try {
      await refreshDailyImages()
    } finally {
      await db.$executeRaw`SELECT pg_advisory_unlock(42)`
    }
  }
}

/**
 * 刷新每日精选物化视图
 * 并发刷新物化视图,更新最后刷新时间
 */
export async function refreshDailyImages() {
  await db.$executeRaw`REFRESH MATERIALIZED VIEW CONCURRENTLY "daily_images"`
  await db.configs.update({
    where: { config_key: 'daily_last_refresh' },
    data: {
      config_value: new Date().toISOString(),
      updatedAt: new Date(),
    },
  })
}

/**
 * 更新 daily 配置
 */
export async function updateDailyConfig(payload: {
  dailyEnabled: boolean
  dailyRefreshInterval: string
  dailyTotalCount: number
}) {
  const { dailyEnabled, dailyRefreshInterval, dailyTotalCount } = payload
  const updates = [
    db.configs.update({
      where: { config_key: 'daily_enabled' },
      data: { config_value: dailyEnabled ? 'true' : 'false', updatedAt: new Date() }
    }),
    db.configs.update({
      where: { config_key: 'daily_refresh_interval' },
      data: { config_value: dailyRefreshInterval, updatedAt: new Date() }
    }),
    db.configs.update({
      where: { config_key: 'daily_total_count' },
      data: { config_value: dailyTotalCount.toString(), updatedAt: new Date() }
    }),
  ]
  const result = await db.$transaction(updates)
  // daily_enabled flips the homepage between the daily view and the album list,
  // and the count/interval change the daily list — bust config + gallery.
  revalidateConfigCache()
  return result
}

/**
 * 批量更新相册 daily 权重
 */
export async function updateAlbumsDailyWeight(
  albums: Array<{ id: string, dailyWeight: number }>
) {
  const updates = albums.map(album =>
    db.albums.update({
      where: { id: album.id },
      data: { daily_weight: album.dailyWeight, updatedAt: new Date() }
    })
  )
  const result = await db.$transaction(updates)
  revalidateGalleryCache()
  return result
}