Skip to content

Commit 96dca59

Browse files
committed
use db instead of file
1 parent f658eb5 commit 96dca59

File tree

10 files changed

+193
-82
lines changed

10 files changed

+193
-82
lines changed

models/appstate/appstate.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package appstate
6+
7+
import (
8+
"context"
9+
10+
"code.gitea.io/gitea/models/db"
11+
)
12+
13+
// AppState represents a state record in database
14+
// if one day we would make Gitea run as a cluster,
15+
// we can introduce a new field `Scope` here to store different states for different nodes
16+
type AppState struct {
17+
ID string `xorm:"pk varchar(200)"`
18+
Revision int64
19+
Content string `xorm:"LONGTEXT"`
20+
}
21+
22+
// SaveAppStateContent saves the app state item to database
23+
func SaveAppStateContent(key, content string) error {
24+
return db.WithTx(func(ctx context.Context) error {
25+
eng := db.GetEngine(ctx)
26+
// try to update existing row
27+
res, err := eng.Exec("UPDATE app_state SET revision=revision+1, content=? WHERE id=?", content, key)
28+
if err != nil {
29+
return err
30+
}
31+
rows, _ := res.RowsAffected()
32+
if rows != 0 {
33+
// the existing row is updated, so we can return
34+
return nil
35+
}
36+
// if no existing row, insert a new row
37+
_, err = eng.Insert(&AppState{ID: key, Content: content})
38+
return err
39+
})
40+
}
41+
42+
// GetAppStateContent gets an app state from database
43+
func GetAppStateContent(key string) (content string, err error) {
44+
e := db.GetEngine(db.DefaultContext)
45+
appState := &AppState{ID: key}
46+
has, err := e.Get(appState)
47+
if err != nil {
48+
return "", err
49+
} else if !has {
50+
return "", nil
51+
}
52+
return appState.Content, nil
53+
}

models/migrations/migrations.go

+2
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ var migrations = []Migration{
352352
NewMigration("Add issue content history table", addTableIssueContentHistory),
353353
// v199 -> v200
354354
NewMigration("Add remote version table", addRemoteVersionTable),
355+
// v200 -> v201
356+
NewMigration("Add table app_state", addTableAppState),
355357
}
356358

357359
// GetCurrentDBVersion returns the current db version

models/migrations/v200.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"fmt"
9+
10+
"xorm.io/xorm"
11+
)
12+
13+
func addTableAppState(x *xorm.Engine) error {
14+
type AppState struct {
15+
ID string `xorm:"pk varchar(200)"`
16+
Revision int64
17+
Content string `xorm:"LONGTEXT"`
18+
}
19+
if err := x.Sync2(new(AppState)); err != nil {
20+
return fmt.Errorf("Sync2: %v", err)
21+
}
22+
return nil
23+
}

modules/appstate/appstate.go

+9
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,12 @@ type StateStore interface {
1414
type StateItem interface {
1515
Name() string
1616
}
17+
18+
// AppState contains the state items for the app
19+
var AppState StateStore
20+
21+
// Init initialize AppState interface
22+
func Init() error {
23+
AppState = &DBStore{}
24+
return nil
25+
}

modules/appstate/appstate_test.go

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package appstate
6+
7+
import (
8+
"path/filepath"
9+
"testing"
10+
11+
"code.gitea.io/gitea/models/appstate"
12+
"code.gitea.io/gitea/models/db"
13+
14+
"github.com/stretchr/testify/assert"
15+
)
16+
17+
func TestMain(m *testing.M) {
18+
db.MainTest(m, filepath.Join("..", ".."), "")
19+
}
20+
21+
type testItem1 struct {
22+
Val1 string
23+
Val2 int
24+
}
25+
26+
func (*testItem1) Name() string {
27+
return "test-item1"
28+
}
29+
30+
type testItem2 struct {
31+
K string
32+
}
33+
34+
func (*testItem2) Name() string {
35+
return "test-item2"
36+
}
37+
38+
func TestAppStateDB(t *testing.T) {
39+
assert.NoError(t, db.PrepareTestDatabase())
40+
_ = db.GetEngine(db.DefaultContext).Sync2(new(appstate.AppState))
41+
42+
as := &DBStore{}
43+
44+
item1 := new(testItem1)
45+
assert.NoError(t, as.Get(item1))
46+
assert.Equal(t, "", item1.Val1)
47+
assert.EqualValues(t, 0, item1.Val2)
48+
49+
item1 = new(testItem1)
50+
item1.Val1 = "a"
51+
item1.Val2 = 2
52+
assert.NoError(t, as.Set(item1))
53+
54+
item2 := new(testItem2)
55+
item2.K = "V"
56+
assert.NoError(t, as.Set(item2))
57+
58+
item1 = new(testItem1)
59+
assert.NoError(t, as.Get(item1))
60+
assert.Equal(t, "a", item1.Val1)
61+
assert.EqualValues(t, 2, item1.Val2)
62+
63+
item2 = new(testItem2)
64+
assert.NoError(t, as.Get(item2))
65+
assert.Equal(t, "V", item2.K)
66+
}

modules/appstate/db.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package appstate
6+
7+
import (
8+
"code.gitea.io/gitea/models/appstate"
9+
"code.gitea.io/gitea/modules/json"
10+
11+
"github.com/yuin/goldmark/util"
12+
)
13+
14+
// DBStore can be used to store app state items in local filesystem
15+
type DBStore struct {
16+
}
17+
18+
// Get reads the state item
19+
func (f *DBStore) Get(item StateItem) error {
20+
content, err := appstate.GetAppStateContent(item.Name())
21+
if err != nil {
22+
return err
23+
}
24+
if content == "" {
25+
return nil
26+
}
27+
return json.Unmarshal(util.StringToReadOnlyBytes(content), item)
28+
}
29+
30+
// Set saves the state item
31+
func (f *DBStore) Set(item StateItem) error {
32+
b, err := json.Marshal(item)
33+
if err != nil {
34+
return err
35+
}
36+
return appstate.SaveAppStateContent(item.Name(), util.BytesToReadOnlyString(b))
37+
}

modules/appstate/file.go

-54
This file was deleted.

modules/setting/appstate.go

-24
This file was deleted.

modules/setting/setting.go

-1
Original file line numberDiff line numberDiff line change
@@ -1200,7 +1200,6 @@ func CreateOrAppendToCustomConf(callback func(cfg *ini.File)) {
12001200
func NewServices() {
12011201
InitDBConfig()
12021202
newService()
1203-
newAppState()
12041203
newOAuth2Client()
12051204
NewLogServices(false)
12061205
newCacheService()

routers/init.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func InitGitServices() {
7676

7777
func syncAppPathForGit(ctx context.Context) error {
7878
runtimeState := new(appstate.RuntimeState)
79-
if err := setting.AppState.Get(runtimeState); err != nil {
79+
if err := appstate.AppState.Get(runtimeState); err != nil {
8080
return err
8181
}
8282
if runtimeState.LastAppPath != setting.AppPath {
@@ -89,7 +89,7 @@ func syncAppPathForGit(ctx context.Context) error {
8989
mustInit(models.RewriteAllPublicKeys)
9090

9191
runtimeState.LastAppPath = setting.AppPath
92-
return setting.AppState.Set(runtimeState)
92+
return appstate.AppState.Set(runtimeState)
9393
}
9494
return nil
9595
}
@@ -133,7 +133,7 @@ func GlobalInit(ctx context.Context) {
133133

134134
mustInitCtx(ctx, common.InitDBEngine)
135135
log.Info("ORM engine initialization successful!")
136-
136+
mustInit(appstate.Init)
137137
mustInit(oauth2.Init)
138138

139139
models.NewRepoContext()

0 commit comments

Comments
 (0)