-
Notifications
You must be signed in to change notification settings - Fork 3.8k
fix: resolve self-hosting issues on Ubuntu without Docker #7917
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4eee650
c155996
393ef65
90753e4
d131229
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,7 +35,7 @@ const DEFAULT_TELEMETRY_CONFIG = { | |
| maxQueueSize: 2048, | ||
| maxExportBatchSize: 512, | ||
| scheduledDelayMillis: 5000, | ||
| exportTimeoutMillis: 30000, | ||
| exportTimeoutMillis: 10000, | ||
| }, | ||
| } | ||
|
|
||
|
|
@@ -151,8 +151,12 @@ class MothershipOriginSpanProcessor implements SpanProcessor { | |
|
|
||
| async function initializeOpenTelemetry() { | ||
| try { | ||
| if (env.NEXT_TELEMETRY_DISABLED === '1' || process.env.NEXT_TELEMETRY_DISABLED === '1') { | ||
| logger.info('OpenTelemetry disabled via NEXT_TELEMETRY_DISABLED=1') | ||
| if ( | ||
| process.env.DISABLE_TELEMETRY === '1' || | ||
| env.NEXT_TELEMETRY_DISABLED === '1' || | ||
| process.env.NEXT_TELEMETRY_DISABLED === '1' | ||
| ) { | ||
| logger.info('OpenTelemetry disabled via env var') | ||
| return | ||
| } | ||
|
|
||
|
|
@@ -359,15 +363,19 @@ async function initializeOpenTelemetry() { | |
|
|
||
| const shutdownOtel = async () => { | ||
| try { | ||
| await sdk.shutdown() | ||
| const shutdownPromise = sdk.shutdown() | ||
| const timeoutPromise = new Promise<void>((_, reject) => | ||
| setTimeout(() => reject(new Error('OTel shutdown timed out')), 5000) | ||
| ) | ||
|
Comment on lines
+367
to
+369
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change constructs a delay with Context Used: CLAUDE.md (source) Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||
| await Promise.race([shutdownPromise, timeoutPromise]) | ||
|
Comment on lines
+367
to
+370
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When |
||
| logger.info('OpenTelemetry SDK shut down successfully') | ||
| } catch (err) { | ||
| logger.error('Error shutting down OpenTelemetry SDK', err) | ||
| } | ||
| } | ||
|
|
||
| process.on('SIGTERM', shutdownOtel) | ||
| process.on('SIGINT', shutdownOtel) | ||
| process.once('SIGTERM', shutdownOtel) | ||
| process.once('SIGINT', shutdownOtel) | ||
|
Comment on lines
+377
to
+378
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| logger.info('OpenTelemetry instrumentation initialized', { | ||
| serviceName: telemetryConfig.serviceName, | ||
|
|
@@ -398,8 +406,8 @@ export async function register() { | |
| } | ||
| } | ||
|
|
||
| process.on('SIGTERM', shutdownPostHog) | ||
| process.on('SIGINT', shutdownPostHog) | ||
| process.once('SIGTERM', shutdownPostHog) | ||
| process.once('SIGINT', shutdownPostHog) | ||
|
|
||
| const { startMemoryTelemetry } = await import('./lib/monitoring/memory-telemetry') | ||
| startMemoryTelemetry() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,19 @@ const logger = createLogger('AnonymousAuth') | |
|
|
||
| let anonymousUserEnsured = false | ||
|
|
||
| function isMissingTableError(error: unknown): boolean { | ||
| if (error && typeof error === 'object') { | ||
| const code = (error as Record<string, unknown>).code | ||
| if (code === '42P01') return true | ||
| const cause = (error as Record<string, unknown>).cause | ||
| if (cause && typeof cause === 'object') { | ||
| const innerCode = (cause as Record<string, unknown>).code | ||
| if (innerCode === '42P01') return true | ||
| } | ||
| } | ||
|
Comment on lines
+18
to
+21
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This checks only the top-level error and its immediate |
||
| return false | ||
| } | ||
|
|
||
| /** | ||
| * Ensures the anonymous user and their stats record exist in the database. | ||
| * Called when DISABLE_AUTH is enabled to ensure DB operations work. | ||
|
|
@@ -47,6 +60,11 @@ export async function ensureAnonymousUserExists(): Promise<void> { | |
|
|
||
| anonymousUserEnsured = true | ||
| } catch (error) { | ||
| if (isMissingTableError(error)) { | ||
| throw new Error( | ||
| 'Database tables not found. Run database migrations before starting the app: bun run db:migrate' | ||
| ) | ||
| } | ||
| if ( | ||
| error instanceof Error && | ||
| (error.message.includes('unique') || error.message.includes('duplicate')) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The script now deletes the working target and copies directly into that live directory, so interruption, disk exhaustion, or a copy error can leave a partial installation. A later run checks only whether
pty.nodeexists, so a torn copy containing that file can be treated as valid and reused. Copy into a temporary directory on the destination filesystem first, then atomically rename it into place.