Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,16 @@ PROBE_INTERVAL_MS=30000
PROBE_TIMEOUT_MS=5000

# Provider Endpoint Probing (always enabled)
# 功能说明:每 10 秒探测所有启用端点的速度与连通性,并刷新端点选择排序。
# 注意:没有 ENABLE 开关,默认启用;可通过下列参数调优。
ENDPOINT_PROBE_INTERVAL_MS=10000
# Probes all enabled endpoints based on dynamic intervals and refreshes endpoint selection ranking.
# Note: No ENABLE switch, enabled by default; tune via parameters below.
#
# Dynamic Interval Rules (in priority order):
# 1. Timeout Override (10s): If endpoint's lastProbeErrorType === "timeout" and not recovered (lastProbeOk !== true)
# 2. Single-Vendor (10min): If vendor has only 1 enabled endpoint
# 3. Base Interval (default): All other endpoints
#
# ENDPOINT_PROBE_INTERVAL_MS controls the base interval. Single-vendor and timeout intervals are fixed.
ENDPOINT_PROBE_INTERVAL_MS=60000
ENDPOINT_PROBE_TIMEOUT_MS=5000
ENDPOINT_PROBE_CONCURRENCY=10
ENDPOINT_PROBE_CYCLE_JITTER_MS=1000
Expand Down
6 changes: 6 additions & 0 deletions drizzle/0048_add_system_timezone.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- Add timezone column to system_settings table
-- Stores IANA timezone identifier (e.g., 'Asia/Shanghai', 'America/New_York')
-- NULL means: use TZ environment variable or fallback to UTC

ALTER TABLE "system_settings"
ADD COLUMN IF NOT EXISTS "timezone" varchar(64);
6 changes: 6 additions & 0 deletions drizzle/0057_conscious_quicksilver.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ALTER TABLE "message_request" ALTER COLUMN "input_tokens" SET DATA TYPE bigint;--> statement-breakpoint
ALTER TABLE "message_request" ALTER COLUMN "output_tokens" SET DATA TYPE bigint;--> statement-breakpoint
ALTER TABLE "message_request" ALTER COLUMN "cache_creation_input_tokens" SET DATA TYPE bigint;--> statement-breakpoint
ALTER TABLE "message_request" ALTER COLUMN "cache_read_input_tokens" SET DATA TYPE bigint;--> statement-breakpoint
ALTER TABLE "message_request" ALTER COLUMN "cache_creation_5m_input_tokens" SET DATA TYPE bigint;--> statement-breakpoint
ALTER TABLE "message_request" ALTER COLUMN "cache_creation_1h_input_tokens" SET DATA TYPE bigint;
6 changes: 6 additions & 0 deletions drizzle/0058_silly_sleepwalker.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ALTER TABLE "system_settings" ADD COLUMN "quota_db_refresh_interval_seconds" integer DEFAULT 10;--> statement-breakpoint
ALTER TABLE "system_settings" ADD COLUMN "quota_lease_percent_5h" numeric(5, 4) DEFAULT '0.05';--> statement-breakpoint
ALTER TABLE "system_settings" ADD COLUMN "quota_lease_percent_daily" numeric(5, 4) DEFAULT '0.05';--> statement-breakpoint
ALTER TABLE "system_settings" ADD COLUMN "quota_lease_percent_weekly" numeric(5, 4) DEFAULT '0.05';--> statement-breakpoint
ALTER TABLE "system_settings" ADD COLUMN "quota_lease_percent_monthly" numeric(5, 4) DEFAULT '0.05';--> statement-breakpoint
ALTER TABLE "system_settings" ADD COLUMN "quota_lease_cap_usd" numeric(10, 2);
2 changes: 2 additions & 0 deletions drizzle/0059_safe_xorn.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE "keys" ALTER COLUMN "expires_at" SET DATA TYPE timestamp with time zone;--> statement-breakpoint
ALTER TABLE "system_settings" ADD COLUMN IF NOT EXISTS "timezone" varchar(64);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This ADD COLUMN statement for the timezone column appears to be redundant. The same column is also added in migration 0048_add_system_timezone.sql. While IF NOT EXISTS prevents an error during execution, having duplicate schema modifications across different migration files can lead to confusion and potential issues with manual rollbacks or out-of-order execution. It would be cleaner to remove this line to ensure each schema change is declared only once.

Comment on lines +1 to +2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd /root && find . -name "0059_safe_xorn.sql" -type f 2>/dev/null | head -5

Repository: ding113/claude-code-hub

Length of output: 122


🏁 Script executed:

find . -path "*/drizzle/*" -name "*.sql" -type f 2>/dev/null | head -20

Repository: ding113/claude-code-hub

Length of output: 802


🏁 Script executed:

find . -name "*.sql" -path "*drizzle*" 2>/dev/null | sort

Repository: ding113/claude-code-hub

Length of output: 2353


🏁 Script executed:

cat -n ./drizzle/0059_safe_xorn.sql

Repository: ding113/claude-code-hub

Length of output: 268


🏁 Script executed:

cat -n ./drizzle/0048_add_system_timezone.sql

Repository: ding113/claude-code-hub

Length of output: 377


🌐 Web query:

PostgreSQL timestamp to timestamptz type conversion behavior timezone

💡 Result:

In PostgreSQL:

  • timestamp (without time zone) is just a calendar date+time with no time zone context.
  • timestamptz (timestamp with time zone) represents a single instant in time; PostgreSQL stores it in UTC internally and displays it in your session TimeZone. [1], [3]

What happens when you cast?

timestamptimestamptz

When you do:

ts::timestamptz

PostgreSQL assumes ts is in the session TimeZone, then converts that local time to UTC for storage as a timestamptz. [1]

So the numeric instant you get depends on TimeZone.

timestamptztimestamp

When you do:

tstz::timestamp

PostgreSQL converts the stored UTC instant into the session TimeZone for display, then drops the time zone, yielding a “local wall clock” timestamp. [1]

How to control the time zone used in conversion

Use AT TIME ZONE:

  • timestamp AT TIME ZONE zonetimestamptz (interprets the timestamp as if it occurred in zone) [2]
  • timestamptz AT TIME ZONE zonetimestamp (shows what the local wall time was in zone at that instant) [2]

Example:

SELECT
  timestamp '2026-01-29 12:00:00' AT TIME ZONE 'America/New_York'  AS as_in_ny,   -- timestamptz
  (timestamptz '2026-01-29 12:00:00+00' AT TIME ZONE 'America/New_York') AS ny_wall_time; -- timestamp

These operators are the explicit, predictable alternative to relying on the session TimeZone during casts. [1], [2]


🌐 Web query:

PostgreSQL ALTER COLUMN timestamp with time zone USING clause conversion

💡 Result:

To convert an existing column to timestamp with time zone (timestamptz) in PostgreSQL, use ALTER ... TYPE ... USING <expression>, where the USING expression computes the new value from the old one. The USING clause is required when PostgreSQL can’t apply an implicit/assignment cast, and it’s also how you control timezone semantics during conversion. [1]

1) timestamp (no time zone) → timestamptz (interpret old values in a specific zone)

If your existing timestamp values represent local wall-clock time in a known zone (common case), convert with AT TIME ZONE:

ALTER TABLE my_table
  ALTER COLUMN ts TYPE timestamptz
  USING ts AT TIME ZONE 'America/New_York';

AT TIME ZONE lets you specify a zone different from the session TimeZone; otherwise, conversions between timestamp and timestamptz normally assume the session TimeZone. [2]

If your timestamp values are actually UTC wall-clock times:

ALTER TABLE my_table
  ALTER COLUMN ts TYPE timestamptz
  USING ts AT TIME ZONE 'UTC';

2) integer/Bigint Unix epoch → timestamptz

PostgreSQL’s docs show converting Unix seconds since epoch like this: [1]

ALTER TABLE foo
  ALTER COLUMN foo_timestamp TYPE timestamptz
  USING timestamptz 'epoch' + foo_timestamp * interval '1 second';

3) If the column has a default that won’t cast cleanly

Because the USING expression is not applied to the existing default, you may need to drop/reset it during the change: [1]

ALTER TABLE foo
  ALTER COLUMN foo_timestamp DROP DEFAULT,
  ALTER COLUMN foo_timestamp TYPE timestamptz
  USING timestamptz 'epoch' + foo_timestamp * interval '1 second',
  ALTER COLUMN foo_timestamp SET DEFAULT now();

Tip: choosing the correct USING ... AT TIME ZONE '...' depends on what your existing data means (which zone it was intended to be in), not where the server runs. Conversions between timestamp and timestamptz otherwise follow the session TimeZone. [2]

Sources: PostgreSQL ALTER TABLE ... ALTER COLUMN ... TYPE ... USING documentation [1]; PostgreSQL date/time and timezone conversion behavior (timestamp vs timestamptz, AT TIME ZONE) [2].

References:
[1] PostgreSQL Docs: ALTER TABLE (current) https://www.postgresql.org/docs/current/sql-altertable.html
[2] PostgreSQL Docs: Date/Time Types (current) https://www.postgresql.org/docs/current/datatype-datetime.html


在不改变数据的前提下,类型转换需显式指定时区

timestamp 转换为 timestamptz 时,PostgreSQL 会根据数据库会话的 TimeZone 来解释原有的值。如果历史数据以 UTC 存储,但转换时会话的时区设置不同,会导致存储的 UTC 时刻被错误地偏移。建议添加 USING 子句明确指定源数据的时区。

修改建议
-ALTER TABLE "keys" ALTER COLUMN "expires_at" SET DATA TYPE timestamp with time zone;--> statement-breakpoint
+ALTER TABLE "keys" ALTER COLUMN "expires_at" SET DATA TYPE timestamp with time zone
+  USING "expires_at" AT TIME ZONE 'UTC';--> statement-breakpoint
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ALTER TABLE "keys" ALTER COLUMN "expires_at" SET DATA TYPE timestamp with time zone;--> statement-breakpoint
ALTER TABLE "system_settings" ADD COLUMN IF NOT EXISTS "timezone" varchar(64);
ALTER TABLE "keys" ALTER COLUMN "expires_at" SET DATA TYPE timestamp with time zone
USING "expires_at" AT TIME ZONE 'UTC';--> statement-breakpoint
ALTER TABLE "system_settings" ADD COLUMN IF NOT EXISTS "timezone" varchar(64);
🤖 Prompt for AI Agents
In `@drizzle/0059_safe_xorn.sql` around lines 1 - 2, 在将 keys 表的 expires_at 列从
timestamp 转为 timestamp with time zone 时,明确在 ALTER TABLE ... ALTER COLUMN
"expires_at" SET DATA TYPE 子句中添加 USING 子句,把现有的 timestamp 值按 UTC 解释后再转为带时区的时间(即使用
expires_at AT TIME ZONE 'UTC' 之类的表达式),以避免会话时区导致的时间偏移;更新相应的 ALTER TABLE "keys"
ALTER COLUMN "expires_at" 语句并保留对 system_settings 表新增 timezone 列的变更。

Comment on lines +1 to +2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify existing expires_at timestamps convert correctly to timestamptz - PostgreSQL will interpret them as being in server timezone. Test with: SELECT timezone('UTC', expires_at) FROM keys WHERE expires_at IS NOT NULL LIMIT 10;

Prompt To Fix With AI
This is a comment left during a code review.
Path: drizzle/0059_safe_xorn.sql
Line: 1:2

Comment:
Verify existing `expires_at` timestamps convert correctly to `timestamptz` - PostgreSQL will interpret them as being in server timezone. Test with: `SELECT timezone('UTC', expires_at) FROM keys WHERE expires_at IS NOT NULL LIMIT 10;`

How can I resolve this? If you propose a fix, please make it concise.

Loading
Loading