package bootstrap import ( "context" "errors" "strings" "github.com/jackc/pgx/v5" ) const ( materializationNotStarted = "not_started" materializationPending = "pending" materializationRunning = "running" materializationSucceeded = "succeeded" materializationFailed = "failed" ) type bootstrapStructurePrerequisites struct { installation InstallationRecord admin AdminSummary } func (service *Service) GetInstallation(ctx context.Context) (*InstallationRecord, error) { record, err := scanInstallationRecord(service.db.Pool.QueryRow(ctx, ` SELECT id::text, name, mode::text, access::text, protocol::text, host, is_bootstrapped, materialization_status::text, materialization_error FROM installations WHERE singleton = TRUE LIMIT 1; `)) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, nil } return nil, err } return &record, nil } func loadInstallation(ctx context.Context, tx pgx.Tx) (InstallationRecord, error) { return scanInstallationRecord(tx.QueryRow(ctx, ` SELECT id::text, name, mode::text, access::text, protocol::text, host, is_bootstrapped, materialization_status::text, materialization_error FROM installations WHERE singleton = TRUE LIMIT 1; `)) } func updateBootstrappedInstallation(ctx context.Context, tx pgx.Tx) (InstallationRecord, error) { return scanInstallationRecord(tx.QueryRow(ctx, ` UPDATE installations SET is_bootstrapped = TRUE, bootstrapped_at = COALESCE(bootstrapped_at, NOW()), materialization_status = 'pending'::bootstrap_materialization_status, materialization_error = NULL, materialization_requested_at = NOW(), materialization_started_at = NULL, materialization_finished_at = NULL, updated_at = NOW() WHERE singleton = TRUE RETURNING id::text, name, mode::text, access::text, protocol::text, host, is_bootstrapped, materialization_status::text, materialization_error; `)) } func scanInstallationRecord(row pgx.Row) (InstallationRecord, error) { var record InstallationRecord if err := row.Scan( &record.ID, &record.Name, &record.Mode, &record.Access, &record.Protocol, &record.Host, &record.IsBootstrapped, &record.MaterializationStatus, &record.MaterializationError, ); err != nil { return InstallationRecord{}, err } if strings.TrimSpace(record.MaterializationStatus) == "" { record.MaterializationStatus = materializationNotStarted } return record, nil } func loadPrimaryAdmin(ctx context.Context, tx pgx.Tx) (AdminSummary, error) { var admin AdminSummary if err := tx.QueryRow(ctx, ` SELECT id::text, email, display_name FROM users WHERE is_instance_admin = TRUE ORDER BY created_at ASC LIMIT 1; `).Scan(&admin.ID, &admin.Email, &admin.DisplayName); err != nil { return AdminSummary{}, err } return admin, nil } func (service *Service) loadBootstrapStructurePrerequisites( ctx context.Context, tx pgx.Tx, ) (bootstrapStructurePrerequisites, error) { installation, err := loadInstallation(ctx, tx) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return bootstrapStructurePrerequisites{}, ErrInstallationNotConfigured } return bootstrapStructurePrerequisites{}, err } admin, err := loadPrimaryAdmin(ctx, tx) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return bootstrapStructurePrerequisites{}, ErrAdminNotConfigured } return bootstrapStructurePrerequisites{}, err } return bootstrapStructurePrerequisites{ installation: installation, admin: admin, }, nil }