chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1 @@
export * from './types'
+159
View File
@@ -0,0 +1,159 @@
import { getPlanTypeForLimits } from '@/lib/billing/plan-helpers'
import { env } from '@/lib/core/config/env'
import { isBillingEnabled } from '@/lib/core/config/env-flags'
import type { SubscriptionPlan } from '@/lib/core/rate-limiter/types'
interface ExecutionTimeoutConfig {
sync: number
async: number
}
const DEFAULT_SYNC_TIMEOUTS_SECONDS = {
free: 300,
pro: 3000,
team: 3000,
enterprise: 3000,
} as const
const DEFAULT_ASYNC_TIMEOUTS_SECONDS = {
free: 5400,
pro: 5400,
team: 5400,
enterprise: 5400,
} as const
function getSyncTimeoutForPlan(plan: SubscriptionPlan): number {
const envVarMap: Record<SubscriptionPlan, string | undefined> = {
free: env.EXECUTION_TIMEOUT_FREE,
pro: env.EXECUTION_TIMEOUT_PRO,
team: env.EXECUTION_TIMEOUT_TEAM,
enterprise: env.EXECUTION_TIMEOUT_ENTERPRISE,
}
return (Number.parseInt(envVarMap[plan] || '') || DEFAULT_SYNC_TIMEOUTS_SECONDS[plan]) * 1000
}
function getAsyncTimeoutForPlan(plan: SubscriptionPlan): number {
const envVarMap: Record<SubscriptionPlan, string | undefined> = {
free: env.EXECUTION_TIMEOUT_ASYNC_FREE,
pro: env.EXECUTION_TIMEOUT_ASYNC_PRO,
team: env.EXECUTION_TIMEOUT_ASYNC_TEAM,
enterprise: env.EXECUTION_TIMEOUT_ASYNC_ENTERPRISE,
}
return (Number.parseInt(envVarMap[plan] || '') || DEFAULT_ASYNC_TIMEOUTS_SECONDS[plan]) * 1000
}
const EXECUTION_TIMEOUTS: Record<SubscriptionPlan, ExecutionTimeoutConfig> = {
free: {
sync: getSyncTimeoutForPlan('free'),
async: getAsyncTimeoutForPlan('free'),
},
pro: {
sync: getSyncTimeoutForPlan('pro'),
async: getAsyncTimeoutForPlan('pro'),
},
team: {
sync: getSyncTimeoutForPlan('team'),
async: getAsyncTimeoutForPlan('team'),
},
enterprise: {
sync: getSyncTimeoutForPlan('enterprise'),
async: getAsyncTimeoutForPlan('enterprise'),
},
}
export function getExecutionTimeout(
plan: SubscriptionPlan | string | undefined,
type: 'sync' | 'async' = 'sync'
): number {
if (!isBillingEnabled) {
return EXECUTION_TIMEOUTS.free[type]
}
return EXECUTION_TIMEOUTS[getPlanTypeForLimits(plan)][type]
}
export function getMaxExecutionTimeout(): number {
return EXECUTION_TIMEOUTS.enterprise.async
}
/** Safety buffer added beyond the max execution timeout for execution-lifetime TTLs. */
export const RESERVATION_TTL_BUFFER_MS = 60_000
/**
* TTL (ms) bounding how long a single execution can remain in flight: the max
* execution timeout plus a safety buffer. Shared source of truth for the
* admission-reservation key and the live progress-marker key so they expire on
* the same timeline.
*/
export function getExecutionReservationTtlMs(): number {
return getMaxExecutionTimeout() + RESERVATION_TTL_BUFFER_MS
}
export const DEFAULT_EXECUTION_TIMEOUT_MS = EXECUTION_TIMEOUTS.free.sync
export function isTimeoutError(error: unknown): boolean {
if (!error) return false
if (error instanceof Error) {
return error.name === 'TimeoutError'
}
if (typeof error === 'object' && 'name' in error) {
return (error as { name: string }).name === 'TimeoutError'
}
return false
}
export function getTimeoutErrorMessage(error: unknown, timeoutMs?: number): string {
if (timeoutMs) {
const timeoutSeconds = Math.floor(timeoutMs / 1000)
const timeoutMinutes = Math.floor(timeoutSeconds / 60)
const displayTime =
timeoutMinutes > 0
? `${timeoutMinutes} minute${timeoutMinutes > 1 ? 's' : ''}`
: `${timeoutSeconds} seconds`
return `Execution timed out after ${displayTime}`
}
return 'Execution timed out'
}
/**
* Helper to create an AbortController with timeout handling.
* Centralizes the timeout abort pattern used across execution paths.
*/
export interface TimeoutAbortController {
/** The AbortSignal to pass to execution functions */
signal: AbortSignal
/** Returns true if the abort was triggered by timeout (not user cancellation) */
isTimedOut: () => boolean
/** Cleanup function - call in finally block to clear the timeout */
cleanup: () => void
/** Manually abort the execution (for user cancellation) */
abort: () => void
/** The timeout duration in milliseconds (undefined if no timeout) */
timeoutMs: number | undefined
}
export function createTimeoutAbortController(timeoutMs?: number): TimeoutAbortController {
const abortController = new AbortController()
let isTimedOut = false
let timeoutId: NodeJS.Timeout | undefined
if (timeoutMs) {
timeoutId = setTimeout(() => {
isTimedOut = true
abortController.abort()
}, timeoutMs)
}
return {
signal: abortController.signal,
isTimedOut: () => isTimedOut,
cleanup: () => {
if (timeoutId) clearTimeout(timeoutId)
},
abort: () => abortController.abort(),
timeoutMs,
}
}