FEATURE (cpu): Move CPU settings to DB level from backup config level

This commit is contained in:
Rostislav Dugin
2025-12-27 20:49:43 +03:00
parent 908fe337d4
commit 0ab734f947
33 changed files with 208 additions and 96 deletions

View File

@@ -585,6 +585,7 @@ func createTestDatabase(
Username: "postgres",
Password: "postgres",
Database: &testDbName,
CpuCount: 1,
},
}

View File

@@ -106,6 +106,13 @@ func (uc *CreateMongodbBackupUsecase) buildMongodumpArgs(
"--gzip",
}
// Use numParallelCollections based on CPU count
// Cap between 1 and 16 to balance performance and resource usage
parallelCollections := max(1, min(mdb.CpuCount, 16))
if parallelCollections > 1 {
args = append(args, "--numParallelCollections="+fmt.Sprintf("%d", parallelCollections))
}
return args
}

View File

@@ -139,7 +139,7 @@ func (uc *CreatePostgresqlBackupUsecase) streamToStorage(
cmd := exec.CommandContext(ctx, pgBin, args...)
uc.logger.Info("Executing PostgreSQL backup command", "command", cmd.String())
if err := uc.setupPgEnvironment(cmd, pgpassFile, db.Postgresql.IsHttps, password, backupConfig.CpuCount, pgBin); err != nil {
if err := uc.setupPgEnvironment(cmd, pgpassFile, db.Postgresql.IsHttps, password, db.Postgresql.CpuCount, pgBin); err != nil {
return nil, err
}
@@ -335,6 +335,11 @@ func (uc *CreatePostgresqlBackupUsecase) buildPgDumpArgs(pg *pgtypes.PostgresqlD
"--verbose",
}
// Add parallel jobs based on CPU count
if pg.CpuCount > 1 {
args = append(args, "-j", strconv.Itoa(pg.CpuCount))
}
for _, schema := range pg.IncludeSchemas {
args = append(args, "-n", schema)
}

View File

@@ -109,7 +109,6 @@ func Test_SaveBackupConfig_PermissionsEnforced(t *testing.T) {
SendNotificationsOn: []BackupNotificationType{
NotificationBackupFailed,
},
CpuCount: 2,
IsRetryIfFailed: true,
MaxFailedTriesCount: 3,
}
@@ -129,7 +128,6 @@ func Test_SaveBackupConfig_PermissionsEnforced(t *testing.T) {
assert.Equal(t, database.ID, response.DatabaseID)
assert.True(t, response.IsBackupsEnabled)
assert.Equal(t, period.PeriodWeek, response.StorePeriod)
assert.Equal(t, 2, response.CpuCount)
} else {
assert.Contains(t, string(testResp.Body), "insufficient permissions")
}
@@ -158,7 +156,6 @@ func Test_SaveBackupConfig_WhenUserIsNotWorkspaceMember_ReturnsForbidden(t *test
SendNotificationsOn: []BackupNotificationType{
NotificationBackupFailed,
},
CpuCount: 2,
IsRetryIfFailed: true,
MaxFailedTriesCount: 3,
}
@@ -290,7 +287,6 @@ func Test_GetBackupConfigByDbID_ReturnsDefaultConfigForNewDatabase(t *testing.T)
assert.Equal(t, database.ID, response.DatabaseID)
assert.False(t, response.IsBackupsEnabled)
assert.Equal(t, period.PeriodWeek, response.StorePeriod)
assert.Equal(t, 1, response.CpuCount)
assert.True(t, response.IsRetryIfFailed)
assert.Equal(t, 3, response.MaxFailedTriesCount)
assert.NotNil(t, response.BackupInterval)
@@ -387,7 +383,6 @@ func Test_SaveBackupConfig_WithEncryptionNone_ConfigSaved(t *testing.T) {
SendNotificationsOn: []BackupNotificationType{
NotificationBackupFailed,
},
CpuCount: 2,
IsRetryIfFailed: true,
MaxFailedTriesCount: 3,
Encryption: BackupEncryptionNone,
@@ -427,7 +422,6 @@ func Test_SaveBackupConfig_WithEncryptionEncrypted_ConfigSaved(t *testing.T) {
SendNotificationsOn: []BackupNotificationType{
NotificationBackupFailed,
},
CpuCount: 2,
IsRetryIfFailed: true,
MaxFailedTriesCount: 3,
Encryption: BackupEncryptionEncrypted,
@@ -466,6 +460,7 @@ func createTestDatabaseViaAPI(
Username: "postgres",
Password: "postgres",
Database: &testDbName,
CpuCount: 1,
},
}

View File

@@ -30,8 +30,6 @@ type BackupConfig struct {
IsRetryIfFailed bool `json:"isRetryIfFailed" gorm:"column:is_retry_if_failed;type:boolean;not null"`
MaxFailedTriesCount int `json:"maxFailedTriesCount" gorm:"column:max_failed_tries_count;type:int;not null"`
CpuCount int `json:"cpuCount" gorm:"type:int;not null"`
Encryption BackupEncryption `json:"encryption" gorm:"column:encryption;type:text;not null;default:'NONE'"`
}
@@ -82,10 +80,6 @@ func (b *BackupConfig) Validate() error {
return errors.New("store period is required")
}
if b.CpuCount == 0 {
return errors.New("cpu count is required")
}
if b.IsRetryIfFailed && b.MaxFailedTriesCount <= 0 {
return errors.New("max failed tries count must be greater than 0")
}
@@ -109,7 +103,6 @@ func (b *BackupConfig) Copy(newDatabaseID uuid.UUID) *BackupConfig {
SendNotificationsOn: b.SendNotificationsOn,
IsRetryIfFailed: b.IsRetryIfFailed,
MaxFailedTriesCount: b.MaxFailedTriesCount,
CpuCount: b.CpuCount,
Encryption: b.Encryption,
}
}

View File

@@ -168,7 +168,6 @@ func (s *BackupConfigService) initializeDefaultConfig(
NotificationBackupFailed,
NotificationBackupSuccess,
},
CpuCount: 1,
IsRetryIfFailed: true,
MaxFailedTriesCount: 3,
Encryption: BackupEncryptionNone,

View File

@@ -28,7 +28,6 @@ func EnableBackupsForTestDatabase(
NotificationBackupFailed,
NotificationBackupSuccess,
},
CpuCount: 1,
}
backupConfig, err := GetBackupConfigService().SaveBackupConfig(backupConfig)

View File

@@ -100,6 +100,7 @@ func Test_CreateDatabase_PermissionsEnforced(t *testing.T) {
Username: "postgres",
Password: "postgres",
Database: &testDbName,
CpuCount: 1,
},
}
@@ -143,6 +144,7 @@ func Test_CreateDatabase_WhenUserIsNotWorkspaceMember_ReturnsForbidden(t *testin
Username: "postgres",
Password: "postgres",
Database: &testDbName,
CpuCount: 1,
},
}
@@ -747,6 +749,7 @@ func createTestDatabaseViaAPI(
Username: "postgres",
Password: "postgres",
Database: &testDbName,
CpuCount: 1,
},
}
@@ -790,6 +793,7 @@ func Test_CreateDatabase_PasswordIsEncryptedInDB(t *testing.T) {
Username: "postgres",
Password: plainPassword,
Database: &testDbName,
CpuCount: 1,
},
}
@@ -862,6 +866,7 @@ func Test_DatabaseSensitiveDataLifecycle_AllTypes(t *testing.T) {
Username: "postgres",
Password: "original-password-secret",
Database: &testDbName,
CpuCount: 1,
},
}
},
@@ -879,6 +884,7 @@ func Test_DatabaseSensitiveDataLifecycle_AllTypes(t *testing.T) {
Username: "updated_user",
Password: "",
Database: &testDbName,
CpuCount: 1,
},
}
},
@@ -961,6 +967,7 @@ func Test_DatabaseSensitiveDataLifecycle_AllTypes(t *testing.T) {
Database: "test_db",
AuthDatabase: "admin",
IsHttps: false,
CpuCount: 1,
},
}
},
@@ -979,6 +986,7 @@ func Test_DatabaseSensitiveDataLifecycle_AllTypes(t *testing.T) {
Database: "updated_test_db",
AuthDatabase: "admin",
IsHttps: false,
CpuCount: 1,
},
}
},

View File

@@ -30,6 +30,7 @@ type MongodbDatabase struct {
Database string `json:"database" gorm:"type:text;not null"`
AuthDatabase string `json:"authDatabase" gorm:"type:text;not null;default:'admin'"`
IsHttps bool `json:"isHttps" gorm:"type:boolean;default:false"`
CpuCount int `json:"cpuCount" gorm:"column:cpu_count;type:int;not null;default:1"`
}
func (m *MongodbDatabase) TableName() string {
@@ -52,6 +53,9 @@ func (m *MongodbDatabase) Validate() error {
if m.Database == "" {
return errors.New("database is required")
}
if m.CpuCount <= 0 {
return errors.New("cpu count must be greater than 0")
}
return nil
}
@@ -109,6 +113,7 @@ func (m *MongodbDatabase) Update(incoming *MongodbDatabase) {
m.Database = incoming.Database
m.AuthDatabase = incoming.AuthDatabase
m.IsHttps = incoming.IsHttps
m.CpuCount = incoming.CpuCount
if incoming.Password != "" {
m.Password = incoming.Password

View File

@@ -34,6 +34,7 @@ type PostgresqlDatabase struct {
// backup settings
IncludeSchemas []string `json:"includeSchemas" gorm:"-"`
IncludeSchemasString string `json:"-" gorm:"column:include_schemas;type:text;not null;default:''"`
CpuCount int `json:"cpuCount" gorm:"column:cpu_count;type:int;not null;default:1"`
// restore settings (not saved to DB)
IsExcludeExtensions bool `json:"isExcludeExtensions" gorm:"-"`
@@ -80,6 +81,10 @@ func (p *PostgresqlDatabase) Validate() error {
return errors.New("password is required")
}
if p.CpuCount <= 0 {
return errors.New("cpu count must be greater than 0")
}
return nil
}
@@ -110,6 +115,7 @@ func (p *PostgresqlDatabase) Update(incoming *PostgresqlDatabase) {
p.Database = incoming.Database
p.IsHttps = incoming.IsHttps
p.IncludeSchemas = incoming.IncludeSchemas
p.CpuCount = incoming.CpuCount
if incoming.Password != "" {
p.Password = incoming.Password

View File

@@ -396,15 +396,17 @@ func (s *DatabaseService) CopyDatabase(
case DatabaseTypePostgres:
if existingDatabase.Postgresql != nil {
newDatabase.Postgresql = &postgresql.PostgresqlDatabase{
ID: uuid.Nil,
DatabaseID: nil,
Version: existingDatabase.Postgresql.Version,
Host: existingDatabase.Postgresql.Host,
Port: existingDatabase.Postgresql.Port,
Username: existingDatabase.Postgresql.Username,
Password: existingDatabase.Postgresql.Password,
Database: existingDatabase.Postgresql.Database,
IsHttps: existingDatabase.Postgresql.IsHttps,
ID: uuid.Nil,
DatabaseID: nil,
Version: existingDatabase.Postgresql.Version,
Host: existingDatabase.Postgresql.Host,
Port: existingDatabase.Postgresql.Port,
Username: existingDatabase.Postgresql.Username,
Password: existingDatabase.Postgresql.Password,
Database: existingDatabase.Postgresql.Database,
IsHttps: existingDatabase.Postgresql.IsHttps,
IncludeSchemas: existingDatabase.Postgresql.IncludeSchemas,
CpuCount: existingDatabase.Postgresql.CpuCount,
}
}
case DatabaseTypeMysql:
@@ -448,6 +450,7 @@ func (s *DatabaseService) CopyDatabase(
Database: existingDatabase.Mongodb.Database,
AuthDatabase: existingDatabase.Mongodb.AuthDatabase,
IsHttps: existingDatabase.Mongodb.IsHttps,
CpuCount: existingDatabase.Mongodb.CpuCount,
}
}
}

View File

@@ -25,6 +25,7 @@ func CreateTestDatabase(
Port: 5432,
Username: "postgres",
Password: "postgres",
CpuCount: 1,
},
Notifiers: []notifiers.Notifier{

View File

@@ -217,6 +217,7 @@ func createTestDatabaseViaAPI(
Username: "postgres",
Password: "postgres",
Database: &testDbName,
CpuCount: 1,
},
}

View File

@@ -305,6 +305,7 @@ func createTestDatabaseViaAPI(
Username: "postgres",
Password: "postgres",
Database: &testDbName,
CpuCount: 1,
},
}

View File

@@ -295,6 +295,7 @@ func createTestDatabase(
Username: "postgres",
Password: "postgres",
Database: &testDbName,
CpuCount: 1,
},
}

View File

@@ -111,6 +111,16 @@ func (uc *RestoreMongodbBackupUsecase) buildMongorestoreArgs(
args = append(args, "--nsInclude="+mdb.Database+".*")
}
// Use numInsertionWorkersPerCollection based on CPU count
// Cap between 1 and 16 to balance performance and resource usage
parallelWorkers := max(1, min(mdb.CpuCount, 16))
if parallelWorkers > 1 {
args = append(
args,
"--numInsertionWorkersPerCollection="+fmt.Sprintf("%d", parallelWorkers),
)
}
return args
}

View File

@@ -67,7 +67,7 @@ func (uc *RestorePostgresqlBackupUsecase) Execute(
// Use parallel jobs based on CPU count (same as backup)
// Cap between 1 and 8 to avoid overwhelming the server
parallelJobs := max(1, min(backupConfig.CpuCount, 8))
parallelJobs := max(1, min(restoringToDB.Postgresql.CpuCount, 8))
args := []string{
"-Fc", // expect custom format (same as backup)

View File

@@ -394,6 +394,7 @@ func createMongodbDatabaseViaAPI(
AuthDatabase: authDatabase,
Version: version,
IsHttps: false,
CpuCount: 1,
},
}
@@ -440,6 +441,7 @@ func createMongodbRestoreViaAPI(
AuthDatabase: authDatabase,
Version: version,
IsHttps: false,
CpuCount: 1,
},
}

View File

@@ -1269,6 +1269,7 @@ func createDatabaseViaAPI(
Username: username,
Password: password,
Database: &database,
CpuCount: 1,
},
}
@@ -1387,6 +1388,7 @@ func createRestoreWithOptionsViaAPI(
Password: password,
Database: &database,
IsExcludeExtensions: isExcludeExtensions,
CpuCount: 1,
},
}
@@ -1424,6 +1426,7 @@ func createDatabaseWithSchemasViaAPI(
Password: password,
Database: &database,
IncludeSchemas: includeSchemas,
CpuCount: 1,
},
}
@@ -1476,6 +1479,7 @@ func createSupabaseDatabaseViaAPI(
Database: &database,
IsHttps: true,
IncludeSchemas: includeSchemas,
CpuCount: 1,
},
}
@@ -1522,6 +1526,7 @@ func createSupabaseRestoreViaAPI(
Password: password,
Database: &database,
IsHttps: true,
CpuCount: 1,
},
}

View File

@@ -0,0 +1,25 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE backup_configs DROP COLUMN cpu_count;
-- +goose StatementEnd
-- +goose StatementBegin
ALTER TABLE postgresql_databases ADD COLUMN cpu_count INT NOT NULL DEFAULT 1;
-- +goose StatementEnd
-- +goose StatementBegin
ALTER TABLE mongodb_databases ADD COLUMN cpu_count INT NOT NULL DEFAULT 1;
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
ALTER TABLE backup_configs ADD COLUMN cpu_count INT NOT NULL DEFAULT 1;
-- +goose StatementEnd
-- +goose StatementBegin
ALTER TABLE postgresql_databases DROP COLUMN cpu_count;
-- +goose StatementEnd
-- +goose StatementBegin
ALTER TABLE mongodb_databases DROP COLUMN cpu_count;
-- +goose StatementEnd

View File

@@ -12,7 +12,6 @@ export interface BackupConfig {
backupInterval?: Interval;
storage?: Storage;
sendNotificationsOn: BackupNotificationType[];
cpuCount: number;
isRetryIfFailed: boolean;
maxFailedTriesCount: number;
encryption: BackupEncryption;

View File

@@ -10,4 +10,5 @@ export interface MongodbDatabase {
database: string;
authDatabase: string;
useTls: boolean;
cpuCount: number;
}

View File

@@ -14,6 +14,7 @@ export interface PostgresqlDatabase {
// backup settings
includeSchemas?: string[];
cpuCount: number;
// restore settings (not saved to DB)
isExcludeExtensions?: boolean;

View File

@@ -541,7 +541,7 @@ export const BackupsComponent = ({ database, isCanManageDBs, scrollContainerRef
<h2 className="text-lg font-bold md:text-xl dark:text-white">Backups</h2>
{!isBackupConfigLoading && !backupConfig?.isBackupsEnabled && (
<div className="text-sm text-red-600 md:text-base">
<div className="text-sm text-red-600">
Scheduled backups are disabled (you can enable it back in the backup configuration)
</div>
)}

View File

@@ -154,7 +154,6 @@ export const EditBackupConfigComponent = ({
timeOfDay: '00:00',
},
storage: undefined,
cpuCount: 1,
storePeriod: Period.THREE_MONTH,
sendNotificationsOn: [],
isRetryIfFailed: true,
@@ -201,7 +200,6 @@ export const EditBackupConfigComponent = ({
!backupConfig.isBackupsEnabled ||
(Boolean(backupConfig.storePeriod) &&
Boolean(backupConfig.storage?.id) &&
Boolean(backupConfig.cpuCount) &&
Boolean(backupConfig.encryption) &&
Boolean(backupInterval?.interval) &&
(!backupInterval ||
@@ -211,16 +209,18 @@ export const EditBackupConfigComponent = ({
return (
<div>
<div className="mb-1 flex w-full flex-col items-start sm:flex-row sm:items-center">
<div className="mb-1 min-w-[150px] sm:mb-0">Backups enabled</div>
<Switch
checked={backupConfig.isBackupsEnabled}
onChange={(checked) => {
updateBackupConfig({ isBackupsEnabled: checked });
}}
size="small"
/>
</div>
{database.id && (
<div className="mb-1 flex w-full flex-col items-start sm:flex-row sm:items-center">
<div className="mb-1 min-w-[150px] sm:mb-0">Backups enabled</div>
<Switch
checked={backupConfig.isBackupsEnabled}
onChange={(checked) => {
updateBackupConfig({ isBackupsEnabled: checked });
}}
size="small"
/>
</div>
)}
{backupConfig.isBackupsEnabled && (
<>
@@ -404,27 +404,6 @@ export const EditBackupConfigComponent = ({
</div>
)}
<div className="mt-5 mb-1 flex w-full flex-col items-start sm:flex-row sm:items-center">
<div className="mb-1 min-w-[150px] sm:mb-0">CPU count</div>
<div className="flex items-center">
<InputNumber
min={1}
max={16}
value={backupConfig.cpuCount}
onChange={(value) => updateBackupConfig({ cpuCount: value || 1 })}
size="small"
className="w-full max-w-[200px] grow"
/>
<Tooltip
className="cursor-pointer"
title="Number of CPU cores to use for restore processing. Higher values may speed up restores, but use more resources."
>
<InfoCircleOutlined className="ml-2" style={{ color: 'gray' }} />
</Tooltip>
</div>
</div>
<div className="mb-1 flex w-full flex-col items-start sm:flex-row sm:items-center">
<div className="mb-1 min-w-[150px] sm:mb-0">Store period</div>
<div className="flex items-center">

View File

@@ -31,8 +31,6 @@ const createInitialDatabase = (workspaceId: string): Database =>
workspaceId,
storePeriod: Period.MONTH,
postgresql: {} as PostgresqlDatabase,
type: DatabaseType.POSTGRES,
storage: {} as unknown as Storage,
@@ -52,13 +50,13 @@ const initializeDatabaseTypeData = (db: Database): Database => {
switch (db.type) {
case DatabaseType.POSTGRES:
return { ...base, postgresql: db.postgresql ?? ({} as PostgresqlDatabase) };
return { ...base, postgresql: db.postgresql ?? ({ cpuCount: 1 } as PostgresqlDatabase) };
case DatabaseType.MYSQL:
return { ...base, mysql: db.mysql ?? ({} as MysqlDatabase) };
case DatabaseType.MARIADB:
return { ...base, mariadb: db.mariadb ?? ({} as MariadbDatabase) };
case DatabaseType.MONGODB:
return { ...base, mongodb: db.mongodb ?? ({} as MongodbDatabase) };
return { ...base, mongodb: db.mongodb ?? ({ cpuCount: 1 } as MongodbDatabase) };
default:
return db;
}

View File

@@ -65,7 +65,8 @@ export const EditDatabaseBaseInfoComponent = ({
switch (newType) {
case DatabaseType.POSTGRES:
updatedDatabase.postgresql = editingDatabase.postgresql ?? ({} as PostgresqlDatabase);
updatedDatabase.postgresql =
editingDatabase.postgresql ?? ({ cpuCount: 1 } as PostgresqlDatabase);
break;
case DatabaseType.MYSQL:
updatedDatabase.mysql = editingDatabase.mysql ?? ({} as MysqlDatabase);
@@ -74,7 +75,7 @@ export const EditDatabaseBaseInfoComponent = ({
updatedDatabase.mariadb = editingDatabase.mariadb ?? ({} as MariadbDatabase);
break;
case DatabaseType.MONGODB:
updatedDatabase.mongodb = editingDatabase.mongodb ?? ({} as MongodbDatabase);
updatedDatabase.mongodb = editingDatabase.mongodb ?? ({ cpuCount: 1 } as MongodbDatabase);
break;
}

View File

@@ -1,5 +1,5 @@
import { CopyOutlined, DownOutlined, UpOutlined } from '@ant-design/icons';
import { App, Button, Input, InputNumber, Switch } from 'antd';
import { CopyOutlined, DownOutlined, InfoCircleOutlined, UpOutlined } from '@ant-design/icons';
import { App, Button, Input, InputNumber, Switch, Tooltip } from 'antd';
import { useEffect, useState } from 'react';
import { type Database, databaseApi } from '../../../../entity/databases';
@@ -78,6 +78,7 @@ export const EditMongoDbSpecificDataComponent = ({
database: result.database,
authDatabase: result.authDatabase,
useTls: result.useTls,
cpuCount: 1,
},
};
@@ -285,7 +286,7 @@ export const EditMongoDbSpecificDataComponent = ({
</div>
)}
<div className="mb-3 flex w-full items-center">
<div className="mb-1 flex w-full items-center">
<div className="min-w-[150px]">Use TLS</div>
<Switch
checked={editingDatabase.mongodb?.useTls}
@@ -302,7 +303,36 @@ export const EditMongoDbSpecificDataComponent = ({
/>
</div>
<div className="mt-4 mb-3 flex items-center">
<div className="mb-5 flex w-full items-center">
<div className="min-w-[150px]">CPU count</div>
<div className="flex items-center">
<InputNumber
min={1}
max={16}
value={editingDatabase.mongodb?.cpuCount || 1}
onChange={(value) => {
if (!editingDatabase.mongodb) return;
setEditingDatabase({
...editingDatabase,
mongodb: { ...editingDatabase.mongodb, cpuCount: value || 1 },
});
setIsConnectionTested(false);
}}
size="small"
className="max-w-[200px] grow"
/>
<Tooltip
className="cursor-pointer"
title="Number of CPU cores to use for backup and restore operations. Higher values may speed up operations but use more resources."
>
<InfoCircleOutlined className="ml-2" style={{ color: 'gray' }} />
</Tooltip>
</div>
</div>
<div className="mt-4 mb-1 flex items-center">
<div
className="flex cursor-pointer items-center text-sm text-blue-600 hover:text-blue-800"
onClick={() => setShowAdvanced(!isShowAdvanced)}
@@ -318,24 +348,26 @@ export const EditMongoDbSpecificDataComponent = ({
</div>
{isShowAdvanced && (
<div className="mb-1 flex w-full items-center">
<div className="min-w-[150px]">Auth database</div>
<Input
value={editingDatabase.mongodb?.authDatabase}
onChange={(e) => {
if (!editingDatabase.mongodb) return;
<>
<div className="mb-1 flex w-full items-center">
<div className="min-w-[150px]">Auth database</div>
<Input
value={editingDatabase.mongodb?.authDatabase}
onChange={(e) => {
if (!editingDatabase.mongodb) return;
setEditingDatabase({
...editingDatabase,
mongodb: { ...editingDatabase.mongodb, authDatabase: e.target.value.trim() },
});
setIsConnectionTested(false);
}}
size="small"
className="max-w-[200px] grow"
placeholder="admin"
/>
</div>
setEditingDatabase({
...editingDatabase,
mongodb: { ...editingDatabase.mongodb, authDatabase: e.target.value.trim() },
});
setIsConnectionTested(false);
}}
size="small"
className="max-w-[200px] grow"
placeholder="admin"
/>
</div>
</>
)}
<div className="mt-5 flex">

View File

@@ -82,6 +82,7 @@ export const EditPostgreSqlSpecificDataComponent = ({
password: result.password,
database: result.database,
isHttps: result.isHttps,
cpuCount: 1,
},
};
@@ -338,7 +339,7 @@ export const EditPostgreSqlSpecificDataComponent = ({
</div>
)}
<div className="mb-3 flex w-full items-center">
<div className="mb-1 flex w-full items-center">
<div className="min-w-[150px]">Use HTTPS</div>
<Switch
checked={editingDatabase.postgresql?.isHttps}
@@ -355,7 +356,38 @@ export const EditPostgreSqlSpecificDataComponent = ({
/>
</div>
<div className="mt-4 mb-3 flex items-center">
{isRestoreMode && (
<div className="mb-5 flex w-full items-center">
<div className="min-w-[150px]">CPU count</div>
<div className="flex items-center">
<InputNumber
min={1}
max={128}
value={editingDatabase.postgresql?.cpuCount || 1}
onChange={(value) => {
if (!editingDatabase.postgresql) return;
setEditingDatabase({
...editingDatabase,
postgresql: { ...editingDatabase.postgresql, cpuCount: value || 1 },
});
setIsConnectionTested(false);
}}
size="small"
className="max-w-[75px] grow"
/>
<Tooltip
className="cursor-pointer"
title="Number of CPU cores to use for backup and restore operations. Higher values may speed up operations but use more resources."
>
<InfoCircleOutlined className="ml-2" style={{ color: 'gray' }} />
</Tooltip>
</div>
</div>
)}
<div className="mt-4 mb-1 flex items-center">
<div
className="flex cursor-pointer items-center text-sm text-blue-600 hover:text-blue-800"
onClick={() => setShowAdvanced(!isShowAdvanced)}

View File

@@ -43,6 +43,11 @@ export const ShowMongoDbSpecificDataComponent = ({ database }: Props) => {
<div>{database.mongodb.authDatabase}</div>
</div>
)}
<div className="mb-1 flex w-full items-center">
<div className="min-w-[150px]">CPU count</div>
<div>{database.mongodb?.cpuCount || 1}</div>
</div>
</div>
);
};

View File

@@ -130,7 +130,7 @@ export function AdminPasswordComponent({
}}
type="primary"
>
Set Password
Set password
</Button>
{adminPasswordError && (

View File

@@ -7,7 +7,7 @@ export function AuthNavbarComponent() {
<div className="flex h-[65px] items-center justify-center px-5 pt-5 sm:justify-start">
<div className="flex items-center gap-3 hover:opacity-80">
<a href="https://databasus.com" target="_blank" rel="noreferrer">
<img className="padding-[2.5px] h-[45px] w-[45px]" src="/logo.svg" />
<img className="h-[45px] w-[45px] p-1" src="/logo.svg" />
</a>
<div className="text-xl font-bold">

View File

@@ -193,10 +193,7 @@ export const MainScreenComponent = () => {
<div className="mb-2 flex h-[50px] items-center rounded bg-white px-2 py-2 shadow md:mb-3 md:h-[60px] md:p-3 dark:bg-gray-800">
<div className="flex items-center gap-2 hover:opacity-80 md:gap-3">
<a href="https://databasus.com" target="_blank" rel="noreferrer">
<img
className="padding-[2.5px] h-[30px] w-[30px] md:h-[40px] md:w-[40px]"
src="/logo.svg"
/>
<img className="h-[30px] w-[30px] p-1 md:h-[40px] md:w-[40px]" src="/logo.svg" />
</a>
</div>