start method
Starts the Serverpod and all Servers that it manages.
Implementation
Future<void> start() async {
_startedTime = DateTime.now().toUtc();
await runZonedGuarded(() async {
// Register cloud store endpoint if we're using the database cloud store
if (storage['public'] is DatabaseCloudStorage ||
storage['private'] is DatabaseCloudStorage) {
CloudStoragePublicEndpoint().register(this);
}
int? maxAttempts =
commandLineArgs.role == ServerpodRole.maintenance ? 6 : null;
Session session;
try {
session = await _connectToDatabase(
enableLogging: false,
maxAttempts: maxAttempts,
);
} catch (e) {
_exitCode = 1;
stderr.writeln(
'Failed to connect to the database. $e',
);
exit(_exitCode);
}
try {
logVerbose('Initializing migration manager.');
migrationManager = MigrationManager();
await migrationManager.initialize(session);
if (commandLineArgs.applyRepairMigration) {
logVerbose('Applying database repair migration');
var appliedRepairMigration =
await migrationManager.applyRepairMigration(session);
if (appliedRepairMigration == null) {
stderr.writeln('Failed to apply database repair migration.');
} else {
stdout.writeln(
'Database repair migration "$appliedRepairMigration" applied.');
}
await migrationManager.initialize(session);
}
if (commandLineArgs.applyMigrations) {
logVerbose('Applying database migrations.');
var migrationsApplied =
await migrationManager.migrateToLatest(session);
if (migrationsApplied == null) {
stdout.writeln('Latest database migration already applied.');
} else {
stdout.writeln(
'Applied database migration${migrationsApplied.length > 1 ? 's' : ''}:');
for (var migration in migrationsApplied) {
stdout.writeln(' - $migration');
}
}
await migrationManager.initialize(session);
}
logVerbose('Verifying database integrity.');
await migrationManager.verifyDatabaseIntegrity(session);
} catch (e) {
_exitCode = 1;
stderr.writeln(
'Failed to apply database migrations. $e',
);
}
logVerbose('Loading runtime settings.');
try {
_runtimeSettings =
await internal.RuntimeSettings.db.findFirstRow(session);
} catch (e) {
_exitCode = 1;
stderr.writeln(
'Failed to load runtime settings. $e',
);
}
if (_runtimeSettings == null) {
logVerbose('Runtime settings not found, creating default settings.');
try {
_runtimeSettings = await RuntimeSettings.db
.insertRow(session, _defaultRuntimeSettings);
} catch (e) {
_exitCode = 1;
stderr.writeln(
'Failed to store runtime settings. $e',
);
}
} else {
logVerbose('Runtime settings loaded.');
}
await session.close();
// Setup log manager.
_logManager = LogManager(_runtimeSettings ?? _defaultRuntimeSettings);
// Connect to Redis
if (redisController != null) {
logVerbose('Connecting to Redis.');
await redisController!.start();
} else {
logVerbose('Redis is disabled, skipping.');
}
// Start servers.
if (commandLineArgs.role == ServerpodRole.monolith ||
commandLineArgs.role == ServerpodRole.serverless) {
var serversStarted = true;
// Serverpod Insights.
if (_isValidSecret(config.serviceSecret)) {
serversStarted &= await _startInsightsServer();
} else {
stderr.write(
'Invalid serviceSecret in password file, Insights server disabled.',
);
}
// Main API server.
serversStarted &= await server.start();
/// Web server.
if (webServer.routes.isNotEmpty) {
logVerbose('Starting web server.');
serversStarted &= await webServer.start();
} else {
logVerbose('No routes configured for web server, skipping.');
}
if (!serversStarted) {
_exitCode = 1;
stderr.writeln('Failed to start servers.');
exit(_exitCode);
}
logVerbose('All servers started.');
}
// Start maintenance tasks. If we are running in maintenance mode, we
// will only run the maintenance tasks once. If we are applying migrations
// no other maintenance tasks will be run.
var appliedMigrations = (commandLineArgs.applyMigrations |
commandLineArgs.applyRepairMigration);
if (commandLineArgs.role == ServerpodRole.monolith ||
(commandLineArgs.role == ServerpodRole.maintenance &&
!appliedMigrations)) {
logVerbose('Starting maintenance tasks.');
// Start future calls
_futureCallManager.start();
// Start health check manager
await _healthCheckManager.start();
}
logVerbose('Serverpod start complete.');
if (commandLineArgs.role == ServerpodRole.maintenance &&
appliedMigrations) {
logVerbose('Finished applying database migrations.');
exit(_exitCode);
}
}, (e, stackTrace) {
_exitCode = 1;
// Last resort error handling
// TODO: Log to database?
stderr.writeln(
'${DateTime.now().toUtc()} Internal server error. Zoned exception.',
);
stderr.writeln('$e');
stderr.writeln('$stackTrace');
});
}