1
This commit is contained in:
@@ -48,3 +48,8 @@ func (c *cAdmin) ListAppVersions(ctx context.Context, req *dto.AdminAppVersionLi
|
||||
func (c *cAdmin) AddAppVersion(ctx context.Context, req *dto.AdminAppVersionAddReq) (*dto.AdminAppVersionAddRes, error) {
|
||||
return service.AppVersion.AdminAddVersion(ctx, req)
|
||||
}
|
||||
|
||||
// DeleteAppVersion 删除版本记录
|
||||
func (c *cAdmin) DeleteAppVersion(ctx context.Context, req *dto.AdminAppVersionDeleteReq) (*dto.AdminAppVersionDeleteRes, error) {
|
||||
return service.AppVersion.AdminDeleteVersion(ctx, req)
|
||||
}
|
||||
|
||||
@@ -64,6 +64,25 @@ func (d *appVersionDao) DeleteByVersion(ctx context.Context, version string) err
|
||||
return err
|
||||
}
|
||||
|
||||
// GetById 按主键查询版本记录,不存在返回 nil
|
||||
func (d *appVersionDao) GetById(ctx context.Context, id int64) (*entity.AppVersion, error) {
|
||||
var e entity.AppVersion
|
||||
err := g.DB().Model(consts.TableAppVersion).Ctx(ctx).Where("id", id).Scan(&e)
|
||||
if err != nil {
|
||||
if common.IsNoRows(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
// DeleteById 按主键删除版本记录
|
||||
func (d *appVersionDao) DeleteById(ctx context.Context, id int64) error {
|
||||
_, err := g.DB().Model(consts.TableAppVersion).Ctx(ctx).Where("id", id).Delete()
|
||||
return err
|
||||
}
|
||||
|
||||
// GetByVersion 按版本号查询(新增前查重,返回 nil 表示不存在)
|
||||
func (d *appVersionDao) GetByVersion(ctx context.Context, version string) (*entity.AppVersion, error) {
|
||||
var e entity.AppVersion
|
||||
|
||||
@@ -124,3 +124,11 @@ type AdminAppVersionAddReq struct {
|
||||
}
|
||||
|
||||
type AdminAppVersionAddRes struct{}
|
||||
|
||||
// AdminAppVersionDeleteReq 删除版本记录(删最新版本联动删除 APK 文件,删历史版本仅删记录)
|
||||
type AdminAppVersionDeleteReq struct {
|
||||
g.Meta `path:"/app-versions/delete" method:"post" summary:"删除版本" tags:"管理端"`
|
||||
Id int64 `json:"id" v:"required|min:1" dc:"版本记录 id"`
|
||||
}
|
||||
|
||||
type AdminAppVersionDeleteRes struct{}
|
||||
|
||||
@@ -94,6 +94,40 @@ func (s *appVersionService) AdminAddVersion(ctx context.Context, req *dto.AdminA
|
||||
return &dto.AdminAppVersionAddRes{}, nil
|
||||
}
|
||||
|
||||
// AdminDeleteVersion 删除版本记录(Serial 串行,防与下发并发交错):
|
||||
// 删最新版本时联动删除 APK 文件(客户端 update 返回空不再提示、下载 404);
|
||||
// 删历史版本仅删记录、不动文件(固定文件永远对应最新版本)。
|
||||
// 先删记录再删文件:记录删除是核心操作,文件删除失败仅记日志不阻断
|
||||
// (记录没了客户端不会误提示更新,残留旧文件无害)。
|
||||
func (s *appVersionService) AdminDeleteVersion(ctx context.Context, req *dto.AdminAppVersionDeleteReq) (*dto.AdminAppVersionDeleteRes, error) {
|
||||
err := common.Serial().Submit(ctx, func() error {
|
||||
v, err := dao.AppVersion.GetById(ctx, req.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v == nil {
|
||||
return gerror.NewCode(common.CodeVersionNotFound)
|
||||
}
|
||||
latest, err := dao.AppVersion.Latest(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dao.AppVersion.DeleteById(ctx, req.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
if latest != nil && latest.Id == v.Id {
|
||||
if err := os.Remove(common.ApkFilePath(ctx)); err != nil && !os.IsNotExist(err) {
|
||||
g.Log().Errorf(ctx, "删除最新版本 %s 后清理 APK 失败: %+v", v.Version, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.AdminAppVersionDeleteRes{}, nil
|
||||
}
|
||||
|
||||
// saveApk 保存 APK:先落临时文件再原子重命名覆盖固定文件名,
|
||||
// 保证目录下永远只保留最新一个文件(异常中断不产生半截正式文件)。
|
||||
func saveApk(ctx context.Context, f *ghttp.UploadFile) error {
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
|
||||
"observer-server/biz/dao"
|
||||
"observer-server/biz/model/dto"
|
||||
"observer-server/common"
|
||||
)
|
||||
@@ -153,3 +154,75 @@ func TestAppVersionList(t *testing.T) {
|
||||
t.Fatalf("latest = %s, want %s", res.List[0].Version, base+"1")
|
||||
}
|
||||
}
|
||||
|
||||
// TestAppVersionDeleteLatest 删除最新版本:记录删除 + APK 文件联动删除
|
||||
func TestAppVersionDeleteLatest(t *testing.T) {
|
||||
ver := uniqueVersion()
|
||||
if _, err := AppVersion.AdminAddVersion(ctx(), &dto.AdminAppVersionAddReq{
|
||||
Version: ver, File: newApkUpload(t, "v.apk", "apk-v1"),
|
||||
}); err != nil {
|
||||
t.Fatalf("add version: %v", err)
|
||||
}
|
||||
latest, err := dao.AppVersion.Latest(ctx())
|
||||
if err != nil || latest == nil {
|
||||
t.Fatalf("latest = %+v, %v", latest, err)
|
||||
}
|
||||
if _, err := AppVersion.AdminDeleteVersion(ctx(), &dto.AdminAppVersionDeleteReq{Id: latest.Id}); err != nil {
|
||||
t.Fatalf("delete version: %v", err)
|
||||
}
|
||||
// 记录已删(测试库有历史残留记录,update 不再返回被删版本即可)
|
||||
gone, err := dao.AppVersion.GetById(ctx(), latest.Id)
|
||||
if err != nil || gone != nil {
|
||||
t.Fatalf("record should be deleted: %+v, %v", gone, err)
|
||||
}
|
||||
res, err := AppVersion.GetUpdate(ctx(), &dto.AppUpdateReq{})
|
||||
if err != nil {
|
||||
t.Fatalf("get update: %v", err)
|
||||
}
|
||||
if res.Version == ver {
|
||||
t.Fatalf("update still returns deleted version %s", ver)
|
||||
}
|
||||
// APK 文件联动删除(下载 404)
|
||||
if _, err := os.Stat(common.ApkFilePath(ctx())); !os.IsNotExist(err) {
|
||||
t.Fatalf("apk file should be removed, stat err = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestAppVersionDeleteHistoric 删除历史版本:仅删记录,APK 文件保留(仍对应最新版本)
|
||||
func TestAppVersionDeleteHistoric(t *testing.T) {
|
||||
ver1 := uniqueVersion()
|
||||
ver2 := uniqueVersion() + "1"
|
||||
for _, v := range []string{ver1, ver2} {
|
||||
if _, err := AppVersion.AdminAddVersion(ctx(), &dto.AdminAppVersionAddReq{
|
||||
Version: v, File: newApkUpload(t, "v.apk", "apk"),
|
||||
}); err != nil {
|
||||
t.Fatalf("add version %s: %v", v, err)
|
||||
}
|
||||
}
|
||||
old, err := dao.AppVersion.GetByVersion(ctx(), ver1)
|
||||
if err != nil || old == nil {
|
||||
t.Fatalf("get by version: %+v, %v", old, err)
|
||||
}
|
||||
if _, err := AppVersion.AdminDeleteVersion(ctx(), &dto.AdminAppVersionDeleteReq{Id: old.Id}); err != nil {
|
||||
t.Fatalf("delete version: %v", err)
|
||||
}
|
||||
// 最新记录仍是 ver2
|
||||
res, err := AppVersion.GetUpdate(ctx(), &dto.AppUpdateReq{})
|
||||
if err != nil {
|
||||
t.Fatalf("get update: %v", err)
|
||||
}
|
||||
if res.Version != ver2 {
|
||||
t.Fatalf("update = %+v, want %s", res, ver2)
|
||||
}
|
||||
// APK 文件保留
|
||||
if _, err := os.Stat(common.ApkFilePath(ctx())); err != nil {
|
||||
t.Fatalf("apk file should remain: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestAppVersionDeleteNotFound 删除不存在的版本报错
|
||||
func TestAppVersionDeleteNotFound(t *testing.T) {
|
||||
if _, err := AppVersion.AdminDeleteVersion(ctx(), &dto.AdminAppVersionDeleteReq{Id: 999999999}); err == nil {
|
||||
t.Fatal("delete missing version should fail")
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
Reference in New Issue
Block a user