223_group_usage_rollup_timezone.sql 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. -- 让 /admin/groups 分组日汇总跟随服务端配置时区。
  2. -- 222 迁移生成的存量日桶均为北京时间,因此新增状态默认标记为 Asia/Shanghai;
  3. -- 服务启动后若当前 TZ 不同,后台同步会检测到不一致并重建日桶。
  4. ALTER TABLE usage_group_rollup_state
  5. ADD COLUMN IF NOT EXISTS timezone_name TEXT NOT NULL DEFAULT 'Asia/Shanghai';
  6. COMMENT ON COLUMN usage_group_rollup_state.timezone_name IS '当前分组日桶采用的 IANA 时区名称。';
  7. COMMENT ON COLUMN usage_group_rollup_state.closed_before IS '已完整发布日桶的配置时区日期排他上界。';
  8. COMMENT ON COLUMN usage_group_daily_rollups.bucket_date IS 'timezone_name 对应时区的自然日。';
  9. CREATE OR REPLACE FUNCTION invalidate_group_usage_rollup_state()
  10. RETURNS TRIGGER
  11. LANGUAGE plpgsql
  12. AS $$
  13. DECLARE
  14. affected_date DATE;
  15. published_before DATE;
  16. configured_timezone TEXT := current_setting('TimeZone');
  17. BEGIN
  18. IF TG_OP = 'DELETE' THEN
  19. affected_date := (OLD.created_at AT TIME ZONE configured_timezone)::date;
  20. ELSE
  21. IF OLD.group_id IS NULL THEN
  22. affected_date := (NEW.created_at AT TIME ZONE configured_timezone)::date;
  23. ELSIF NEW.group_id IS NULL THEN
  24. affected_date := (OLD.created_at AT TIME ZONE configured_timezone)::date;
  25. ELSE
  26. affected_date := LEAST(
  27. (OLD.created_at AT TIME ZONE configured_timezone)::date,
  28. (NEW.created_at AT TIME ZONE configured_timezone)::date
  29. );
  30. END IF;
  31. END IF;
  32. SELECT closed_before
  33. INTO published_before
  34. FROM usage_group_rollup_state
  35. WHERE id = 1
  36. FOR UPDATE;
  37. IF published_before > affected_date THEN
  38. UPDATE usage_group_rollup_state
  39. SET closed_before = LEAST(closed_before, affected_date),
  40. updated_at = NOW()
  41. WHERE id = 1;
  42. END IF;
  43. IF TG_OP = 'DELETE' THEN
  44. RETURN OLD;
  45. END IF;
  46. RETURN NEW;
  47. END;
  48. $$;
  49. CREATE OR REPLACE FUNCTION invalidate_group_usage_rollup_state_after_insert()
  50. RETURNS TRIGGER
  51. LANGUAGE plpgsql
  52. AS $$
  53. DECLARE
  54. affected_date DATE;
  55. published_before DATE;
  56. configured_timezone TEXT := current_setting('TimeZone');
  57. BEGIN
  58. SELECT MIN((created_at AT TIME ZONE configured_timezone)::date)
  59. INTO affected_date
  60. FROM inserted_usage_logs
  61. WHERE group_id IS NOT NULL;
  62. IF affected_date IS NULL THEN
  63. RETURN NULL;
  64. END IF;
  65. SELECT closed_before
  66. INTO published_before
  67. FROM usage_group_rollup_state
  68. WHERE id = 1
  69. FOR KEY SHARE;
  70. IF published_before > affected_date THEN
  71. UPDATE usage_group_rollup_state
  72. SET closed_before = LEAST(closed_before, affected_date),
  73. updated_at = NOW()
  74. WHERE id = 1;
  75. END IF;
  76. RETURN NULL;
  77. END;
  78. $$;