fix: 解决删除网站导致的数据库锁库问题

This commit is contained in:
zhengkunwang223 2022-12-21 15:54:34 +08:00
parent 94ebe4952a
commit 0a8bf98ee9
12 changed files with 66 additions and 57 deletions

View file

@ -1,6 +1,7 @@
package v1
import (
"context"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/constant"
@ -63,7 +64,7 @@ func (b *BaseApi) InstallApp(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
install, err := appService.Install(req.Name, req.AppDetailId, req.Params)
install, err := appService.Install(context.Background(), req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return

View file

@ -1,6 +1,7 @@
package v1
import (
"context"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
@ -18,7 +19,7 @@ func (b *BaseApi) CreateMysql(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := mysqlService.Create(req); err != nil {
if _, err := mysqlService.Create(context.Background(), req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}

View file

@ -1,6 +1,7 @@
package repo
import (
"context"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/global"
"gorm.io/gorm"
@ -17,7 +18,7 @@ type IBackupRepo interface {
CreateRecord(record *model.BackupRecord) error
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error
DeleteRecord(opts ...DBOption) error
DeleteRecord(ctx context.Context, opts ...DBOption) error
WithByDetailName(detailName string) DBOption
}
@ -114,10 +115,6 @@ func (u *BackupRepo) Delete(opts ...DBOption) error {
return db.Delete(&model.BackupAccount{}).Error
}
func (u *BackupRepo) DeleteRecord(opts ...DBOption) error {
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.BackupRecord{}).Error
func (u *BackupRepo) DeleteRecord(ctx context.Context, opts ...DBOption) error {
return getTx(ctx, opts...).Delete(&model.BackupRecord{}).Error
}

View file

@ -1,6 +1,7 @@
package service
import (
"context"
"encoding/base64"
"encoding/json"
"github.com/1Panel-dev/1Panel/backend/buserr"
@ -25,7 +26,6 @@ type AppService struct {
}
func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
var opts []repo.DBOption
opts = append(opts, commonRepo.WithOrderBy("name"))
if req.Name != "" {
@ -139,22 +139,21 @@ func (a AppService) GetAppDetail(appId uint, version string) (response.AppDetail
return appDetailDTO, nil
}
func (a AppService) Install(name string, appDetailId uint, params map[string]interface{}) (*model.AppInstall, error) {
if list, _ := appInstallRepo.GetBy(commonRepo.WithByName(name)); len(list) > 0 {
func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) {
if list, _ := appInstallRepo.GetBy(commonRepo.WithByName(req.Name)); len(list) > 0 {
return nil, buserr.New(constant.ErrNameIsExist)
}
httpPort, err := checkPort("PANEL_APP_PORT_HTTP", params)
httpPort, err := checkPort("PANEL_APP_PORT_HTTP", req.Params)
if err != nil {
return nil, err
}
httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", params)
httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", req.Params)
if err != nil {
return nil, err
}
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(appDetailId))
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(req.AppDetailId))
if err != nil {
return nil, err
}
@ -166,16 +165,16 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int
if err := checkRequiredAndLimit(app); err != nil {
return nil, err
}
if err := copyAppData(app.Key, appDetail.Version, name, params); err != nil {
if err := copyAppData(app.Key, appDetail.Version, req.Name, req.Params); err != nil {
return nil, err
}
paramByte, err := json.Marshal(params)
paramByte, err := json.Marshal(req.Params)
if err != nil {
return nil, err
}
appInstall := model.AppInstall{
Name: name,
Name: req.Name,
AppId: appDetail.AppId,
AppDetailId: appDetail.ID,
Version: appDetail.Version,
@ -216,12 +215,12 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int
return nil, err
}
tx, ctx := getTxAndContext()
tx, ctx := getTxByContext(ctx)
if err := appInstallRepo.Create(ctx, &appInstall); err != nil {
tx.Rollback()
return nil, err
}
if err := createLink(ctx, app, &appInstall, params); err != nil {
if err := createLink(ctx, app, &appInstall, req.Params); err != nil {
tx.Rollback()
return nil, err
}
@ -484,20 +483,16 @@ func (a AppService) SyncAppList() error {
return err
}
}
if err := appTagRepo.DeleteAll(ctx); err != nil {
tx.Rollback()
return err
}
if len(appTags) > 0 {
if err := appTagRepo.BatchCreate(ctx, appTags); err != nil {
tx.Rollback()
return err
}
}
tx.Commit()
return nil
}

View file

@ -130,29 +130,25 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
if err != nil {
return err
}
var database model.DatabaseMysql
database.Name = dbConfig.DbName
database.Username = dbConfig.DbUser
database.Password = dbConfig.Password
database.MysqlName = dbInstall.Name
database.Format = "utf8mb4"
database.Permission = "127.0.0.1"
if err := mysqlRepo.Create(ctx, &database); err != nil {
var createMysql dto.MysqlDBCreate
createMysql.Name = dbConfig.DbName
createMysql.Username = dbConfig.DbUser
createMysql.Format = "utf8mb4"
createMysql.Permission = "%"
createMysql.Password = dbConfig.Password
mysqldb, err := NewIMysqlService().Create(ctx, createMysql)
if err != nil {
return err
}
var installResource model.AppInstallResource
installResource.ResourceId = database.ID
installResource.ResourceId = mysqldb.ID
installResource.AppInstallId = appInstall.ID
installResource.LinkId = dbInstall.ID
installResource.Key = dbInstall.App.Key
if err := appInstallResourceRepo.Create(ctx, &installResource); err != nil {
return err
}
if err := execDockerCommand(database, dbInstall, Add); err != nil {
return err
}
}
return nil
}

View file

@ -1,6 +1,7 @@
package service
import (
"context"
"encoding/json"
"fmt"
"os"
@ -169,7 +170,7 @@ func (u *BackupService) BatchDeleteRecord(ids []uint) error {
}
}
}
return backupRepo.DeleteRecord(commonRepo.WithIdsIn(ids))
return backupRepo.DeleteRecord(context.Background(), commonRepo.WithIdsIn(ids))
}
func (u *BackupService) Update(id uint, upMap map[string]interface{}) error {

View file

@ -1,6 +1,7 @@
package service
import (
"context"
"crypto/tls"
"fmt"
"io/ioutil"
@ -184,7 +185,7 @@ func (u *CronjobService) HandleRmExpired(backType, baseDir, backupDir string, cr
dbCopies++
if dbCopies > cronjob.RetainCopies {
_ = os.Remove(baseDir + "/" + backupDir + "/" + files[i].Name())
_ = backupRepo.DeleteRecord(backupRepo.WithByFileName(files[i].Name()))
_ = backupRepo.DeleteRecord(context.Background(), backupRepo.WithByFileName(files[i].Name()))
}
}
}

View file

@ -31,7 +31,7 @@ type MysqlService struct{}
type IMysqlService interface {
SearchWithPage(search dto.PageInfo) (int64, interface{}, error)
ListDBName() ([]string, error)
Create(mysqlDto dto.MysqlDBCreate) error
Create(ctx context.Context, mysqlDto dto.MysqlDBCreate) (*model.DatabaseMysql, error)
ChangeAccess(info dto.ChangeDBInfo) error
ChangePassword(info dto.ChangeDBInfo) error
UpdateVariables(updatas []dto.MysqlVariablesUpdate) error
@ -153,41 +153,41 @@ func (u *MysqlService) ListDBName() ([]string, error) {
return dbNames, err
}
func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error {
func (u *MysqlService) Create(ctx context.Context, mysqlDto dto.MysqlDBCreate) (*model.DatabaseMysql, error) {
if mysqlDto.Username == "root" {
return errors.New("Cannot set root as user name")
return nil, errors.New("Cannot set root as user name")
}
app, err := appInstallRepo.LoadBaseInfo("mysql", "")
if err != nil {
return err
return nil, err
}
mysql, _ := mysqlRepo.Get(commonRepo.WithByName(mysqlDto.Name))
if mysql.ID != 0 {
return constant.ErrRecordExist
return nil, constant.ErrRecordExist
}
if err := copier.Copy(&mysql, &mysqlDto); err != nil {
return errors.WithMessage(constant.ErrStructTransform, err.Error())
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create database if not exists `%s` character set=%s", mysqlDto.Name, mysqlDto.Format)); err != nil {
return err
return nil,err
}
tmpPermission := mysqlDto.Permission
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user if not exists '%s'@'%s' identified by '%s';", mysqlDto.Username, tmpPermission, mysqlDto.Password)); err != nil {
return err
return nil, err
}
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", mysqlDto.Name, mysqlDto.Username, tmpPermission)
if app.Version == "5.7.39" {
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysqlDto.Password)
}
if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil {
return err
return nil, err
}
mysql.MysqlName = app.Name
if err := mysqlRepo.Create(context.TODO(), &mysql); err != nil {
return err
if err := mysqlRepo.Create(ctx, &mysql); err != nil {
return nil, err
}
return nil
return &mysql, nil
}
func (u *MysqlService) Backup(db dto.BackupDB) error {
@ -281,7 +281,7 @@ func (u *MysqlService) Delete(id uint) error {
if _, err := os.Stat(backupDir); err == nil {
_ = os.RemoveAll(backupDir)
}
_ = backupRepo.DeleteRecord(commonRepo.WithByType("database-mysql"), commonRepo.WithByName(app.Name), backupRepo.WithByDetailName(db.Name))
_ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByType("database-mysql"), commonRepo.WithByName(app.Name), backupRepo.WithByDetailName(db.Name))
_ = mysqlRepo.Delete(context.Background(), commonRepo.WithByID(db.ID))
return nil

View file

@ -12,3 +12,13 @@ func getTxAndContext() (tx *gorm.DB, ctx context.Context) {
ctx = context.WithValue(context.Background(), constant.DB, tx)
return
}
func getTxByContext(ctx context.Context) (*gorm.DB, context.Context) {
tx, ok := ctx.Value(constant.DB).(*gorm.DB)
if ok {
return tx, ctx
}
tx = global.DB.Begin()
ctx = context.WithValue(context.Background(), constant.DB, tx)
return tx, ctx
}

View file

@ -95,7 +95,11 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) error {
switch create.Type {
case constant.Deployment:
if create.AppType == constant.NewApp {
install, err := ServiceGroupApp.Install(create.AppInstall.Name, create.AppInstall.AppDetailId, create.AppInstall.Params)
var req request.AppInstallCreate
req.Name = create.AppInstall.Name
req.AppDetailId = create.AppInstall.AppDetailId
req.Params = create.AppInstall.Params
install, err := ServiceGroupApp.Install(context.Background(), req)
if err != nil {
return err
}
@ -275,9 +279,10 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
for _, b := range backups {
_ = fileOp.DeleteDir(b.FileDir)
}
}
if err := backupRepo.DeleteRecord(backupRepo.WithByType("website-"+website.Type), commonRepo.WithByName(website.PrimaryDomain)); err != nil {
return err
if err := backupRepo.DeleteRecord(ctx, backupRepo.WithByType("website-"+website.Type), commonRepo.WithByName(website.PrimaryDomain)); err != nil {
tx.Rollback()
return err
}
}
}

View file

@ -75,6 +75,7 @@ const acceptParams = async (app: App.AppInstalled) => {
deleteBackup: false,
forceDelete: false,
};
deleteInfo.value = '';
deleteReq.value.installId = app.id;
deleteHelper.value = i18n.global.t('website.deleteConfirmHelper', [app.name]);
appInstallName.value = app.name;

View file

@ -90,6 +90,7 @@ const acceptParams = async (website: Website.Website) => {
deleteBackup: false,
forceDelete: false,
};
deleteInfo.value = '';
deleteReq.value.id = website.id;
websiteName.value = website.primaryDomain;
deleteHelper.value = i18n.global.t('website.deleteConfirmHelper', [website.primaryDomain]);