Skip to content

Commit 82de848

Browse files
committed
feat: Add revision history limit to proxy configuration
1 parent 6577156 commit 82de848

6 files changed

Lines changed: 65 additions & 29 deletions

File tree

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ GATEWAY_STORAGE_DISK_PATH=
4444
GATEWAY_STORAGE_API_URL=
4545
GATEWAY_STORAGE_API_CONFIG_JSON_PATH=
4646
GATEWAY_STORAGE_API_TIMEOUT=5s
47+
GATEWAY_STORAGE_REVISION_HISTORY_LIMIT=10
4748

4849
# Notifier Configuration
4950
APISERVER_NOTIFIER_ROLE=sender

configs/apiserver.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ database:
3232
# Storage configuration
3333
storage:
3434
type: "${GATEWAY_STORAGE_TYPE:db}" # disk or db
35+
revision_history_limit: ${GATEWAY_STORAGE_REVISION_HISTORY_LIMIT:10} # number of versions to keep
3536
# Database configuration (only used when type is db)
3637
database:
3738
type: "${GATEWAY_DB_TYPE:sqlite}"

internal/common/config/storage.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import "time"
44

55
type (
66
StorageConfig struct {
7-
Type string `yaml:"type"` // disk or db
8-
Database DatabaseConfig `yaml:"database"` // database configuration for db type
9-
Disk DiskStorageConfig `yaml:"disk"` // disk configuration for disk type
10-
API APIStorageConfig `yaml:"api"` // disk configuration for api type
7+
Type string `yaml:"type"` // disk or db
8+
RevisionHistoryLimit int `yaml:"revision_history_limit"` // number of versions to keep
9+
Database DatabaseConfig `yaml:"database"` // database configuration for db type
10+
Disk DiskStorageConfig `yaml:"disk"` // disk configuration for disk type
11+
API APIStorageConfig `yaml:"api"` // disk configuration for api type
1112
}
1213

1314
DiskStorageConfig struct {

internal/mcp/storage/db.go

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,7 @@ import (
1717
"gorm.io/gorm/clause"
1818
)
1919

20-
// DBStore implements the Store interface using a database
21-
type DBStore struct {
22-
logger *zap.Logger
23-
db *gorm.DB
24-
}
25-
26-
var _ Store = (*DBStore)(nil)
27-
28-
// DatabaseType represents the supported database types
20+
// DatabaseType represents the type of database
2921
type DatabaseType string
3022

3123
const (
@@ -34,18 +26,27 @@ const (
3426
SQLite DatabaseType = "sqlite"
3527
)
3628

29+
// DBStore implements the Store interface using a database
30+
type DBStore struct {
31+
logger *zap.Logger
32+
db *gorm.DB
33+
cfg *config.StorageConfig
34+
}
35+
36+
var _ Store = (*DBStore)(nil)
37+
3738
// NewDBStore creates a new database-based store
38-
func NewDBStore(logger *zap.Logger, dbType DatabaseType, dsn string) (*DBStore, error) {
39+
func NewDBStore(logger *zap.Logger, cfg *config.StorageConfig) (*DBStore, error) {
3940
logger = logger.Named("mcp.store.db")
4041

4142
var dialector gorm.Dialector
42-
switch dbType {
43+
switch DatabaseType(cfg.Database.Type) {
4344
case PostgreSQL:
44-
dialector = postgres.Open(dsn)
45+
dialector = postgres.Open(cfg.Database.GetDSN())
4546
case MySQL:
46-
dialector = mysql.Open(dsn)
47+
dialector = mysql.Open(cfg.Database.GetDSN())
4748
case SQLite:
48-
dialector = sqlite.Open(dsn)
49+
dialector = sqlite.Open(cfg.Database.GetDSN())
4950
default:
5051
return nil, gorm.ErrInvalidDB
5152
}
@@ -63,6 +64,7 @@ func NewDBStore(logger *zap.Logger, dbType DatabaseType, dsn string) (*DBStore,
6364
return &DBStore{
6465
logger: logger,
6566
db: db,
67+
cfg: cfg,
6668
}, nil
6769
}
6870

@@ -281,6 +283,23 @@ func (s *DBStore) Update(ctx context.Context, server *config.MCPConfig) error {
281283
return err
282284
}
283285

286+
// Delete old versions if revision history limit is set
287+
if s.cfg.RevisionHistoryLimit > 0 {
288+
var versionsToDelete []MCPConfigVersion
289+
if err := tx.Where("tenant = ? AND name = ?", server.Tenant, server.Name).
290+
Order("version DESC").
291+
Offset(s.cfg.RevisionHistoryLimit).
292+
Find(&versionsToDelete).Error; err != nil {
293+
return err
294+
}
295+
296+
for _, v := range versionsToDelete {
297+
if err := tx.Delete(&v).Error; err != nil {
298+
return err
299+
}
300+
}
301+
}
302+
284303
return nil
285304
})
286305
}

internal/mcp/storage/disk.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,28 @@ type DiskStore struct {
2323
logger *zap.Logger
2424
baseDir string
2525
mu sync.RWMutex
26+
cfg *config.StorageConfig
2627
}
2728

2829
var _ Store = (*DiskStore)(nil)
2930

3031
// NewDiskStore creates a new disk-based store
31-
func NewDiskStore(logger *zap.Logger, baseDir string) (*DiskStore, error) {
32-
logger = logger.Named("mcp.store")
32+
func NewDiskStore(logger *zap.Logger, cfg *config.StorageConfig) (*DiskStore, error) {
33+
logger = logger.Named("mcp.store.disk")
3334

34-
baseDir = getConfigPath(baseDir)
35-
logger.Info("Using configuration directory", zap.String("path", baseDir))
35+
baseDir := cfg.Disk.Path
36+
if baseDir == "" {
37+
baseDir = "./data"
38+
}
3639

3740
if err := os.MkdirAll(baseDir, 0755); err != nil {
3841
return nil, err
3942
}
4043

4144
return &DiskStore{
42-
logger: logger,
4345
baseDir: baseDir,
46+
logger: logger,
47+
cfg: cfg,
4448
}, nil
4549
}
4650

@@ -218,6 +222,20 @@ func (s *DiskStore) Update(_ context.Context, server *config.MCPConfig) error {
218222
return err
219223
}
220224

225+
// Delete old versions if revision history limit is set
226+
if s.cfg.RevisionHistoryLimit > 0 && len(entries) >= s.cfg.RevisionHistoryLimit {
227+
for i := s.cfg.RevisionHistoryLimit; i < len(entries); i++ {
228+
oldVersionPath := filepath.Join(versionsDir, entries[i].Name())
229+
if err := os.Remove(oldVersionPath); err != nil {
230+
s.logger.Error("failed to delete old version",
231+
zap.String("tenant", server.Tenant),
232+
zap.String("name", server.Name),
233+
zap.String("version", entries[i].Name()),
234+
zap.Error(err))
235+
}
236+
}
237+
}
238+
221239
return os.WriteFile(path, data, 0644)
222240
}
223241

internal/mcp/storage/factory.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,9 @@ func NewStore(logger *zap.Logger, cfg *config.StorageConfig) (Store, error) {
1313
logger.Info("Initializing storage", zap.String("type", cfg.Type))
1414
switch cfg.Type {
1515
case "disk":
16-
return NewDiskStore(logger, cfg.Disk.Path)
16+
return NewDiskStore(logger, cfg)
1717
case "db":
18-
dsn, err := buildDSN(&cfg.Database)
19-
if err != nil {
20-
return nil, err
21-
}
22-
return NewDBStore(logger, DatabaseType(cfg.Database.Type), dsn)
18+
return NewDBStore(logger, cfg)
2319
case "api":
2420
return NewAPIStore(logger, cfg.API.Url, cfg.API.ConfigJSONPath, cfg.API.Timeout)
2521
default:

0 commit comments

Comments
 (0)