mirror of
https://github.com/eiblog/eiblog.git
synced 2026-02-10 16:42:26 +08:00
chore: add rdbms store
This commit is contained in:
34
pkg/cache/cache.go
vendored
34
pkg/cache/cache.go
vendored
@@ -29,6 +29,11 @@ var (
|
||||
PagesCh = make(chan string, 2)
|
||||
PageSeries = "series-md"
|
||||
PageArchive = "archive-md"
|
||||
|
||||
// ArticleStartID article start id
|
||||
ArticleStartID = 11
|
||||
// TrashArticleExp trash article timeout
|
||||
TrashArticleExp = time.Duration(-48) * time.Hour
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -40,6 +45,7 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
// init store
|
||||
logrus.Info("store drivers: ", store.Drivers())
|
||||
store, err := store.NewStore(config.Conf.Database.Driver,
|
||||
config.Conf.Database.Source)
|
||||
if err != nil {
|
||||
@@ -86,8 +92,7 @@ func (c *Cache) AddArticle(article *model.Article) error {
|
||||
defer c.lock.Unlock()
|
||||
|
||||
// store
|
||||
err := c.InsertArticle(context.Background(), article,
|
||||
config.Conf.EiBlogApp.General.StartID)
|
||||
err := c.InsertArticle(context.Background(), article, ArticleStartID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -107,7 +112,7 @@ func (c *Cache) RepArticle(oldArticle, newArticle *model.Article) {
|
||||
|
||||
c.ArticlesMap[newArticle.Slug] = newArticle
|
||||
render.GenerateExcerptMarkdown(newArticle)
|
||||
if newArticle.ID < config.Conf.EiBlogApp.General.StartID {
|
||||
if newArticle.ID < ArticleStartID {
|
||||
return
|
||||
}
|
||||
if oldArticle != nil { // 移除旧文章
|
||||
@@ -180,7 +185,7 @@ func (c *Cache) PageArticleFE(page int, pageSize int) (prev,
|
||||
|
||||
var l int
|
||||
for l = len(c.Articles); l > 0; l-- {
|
||||
if c.Articles[l-1].ID >= config.Conf.EiBlogApp.General.StartID {
|
||||
if c.Articles[l-1].ID >= ArticleStartID {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -293,12 +298,10 @@ func (c *Cache) recalcLinkedList(article *model.Article, del bool) {
|
||||
}
|
||||
// 添加操作
|
||||
_, idx := c.FindArticleByID(article.ID)
|
||||
if idx == 0 && c.Articles[idx+1].ID >=
|
||||
config.Conf.EiBlogApp.General.StartID {
|
||||
if idx == 0 && c.Articles[idx+1].ID >= ArticleStartID {
|
||||
article.Next = c.Articles[idx+1]
|
||||
c.Articles[idx+1].Prev = article
|
||||
} else if idx > 0 && c.Articles[idx-1].ID >=
|
||||
config.Conf.EiBlogApp.General.StartID {
|
||||
} else if idx > 0 && c.Articles[idx-1].ID >= ArticleStartID {
|
||||
article.Prev = c.Articles[idx-1]
|
||||
if c.Articles[idx-1].Next != nil {
|
||||
article.Next = c.Articles[idx-1].Next
|
||||
@@ -418,8 +421,7 @@ func (c *Cache) loadOrInit() error {
|
||||
Slug: "about",
|
||||
CreatedAt: time.Time{},
|
||||
}
|
||||
err = c.InsertArticle(context.Background(), about,
|
||||
config.Conf.EiBlogApp.General.StartID)
|
||||
err = c.InsertArticle(context.Background(), about, ArticleStartID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -432,8 +434,7 @@ func (c *Cache) loadOrInit() error {
|
||||
Slug: "blogroll",
|
||||
CreatedAt: time.Time{}.AddDate(0, 0, 7),
|
||||
}
|
||||
err = c.InsertArticle(context.Background(), blogroll,
|
||||
config.Conf.EiBlogApp.General.StartID)
|
||||
err = c.InsertArticle(context.Background(), blogroll, ArticleStartID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -473,14 +474,14 @@ func (c *Cache) loadOrInit() error {
|
||||
|
||||
c.ArticlesMap[v.Slug] = v
|
||||
// 分析文章
|
||||
if v.ID < blogapp.General.StartID {
|
||||
if v.ID < ArticleStartID {
|
||||
continue
|
||||
}
|
||||
if i > 0 {
|
||||
v.Prev = articles[i-1]
|
||||
}
|
||||
if i < len(articles)-1 &&
|
||||
articles[i+1].ID >= blogapp.General.StartID {
|
||||
articles[i+1].ID >= ArticleStartID {
|
||||
v.Next = articles[i+1]
|
||||
}
|
||||
c.readdArticle(v, false)
|
||||
@@ -557,8 +558,9 @@ func (c *Cache) regeneratePages() {
|
||||
func (c *Cache) timerClean() {
|
||||
ticker := time.NewTicker(time.Hour)
|
||||
|
||||
for range ticker.C {
|
||||
err := c.CleanArticles(context.Background())
|
||||
for now := range ticker.C {
|
||||
exp := now.Add(TrashArticleExp)
|
||||
err := c.CleanArticles(context.Background(), exp)
|
||||
if err != nil {
|
||||
logrus.Error("cache.timerClean.CleanArticles: ", err)
|
||||
}
|
||||
|
||||
7
pkg/cache/store/mongodb.go
vendored
7
pkg/cache/store/mongodb.go
vendored
@@ -185,8 +185,9 @@ func (db *mongodb) UpdateSerie(ctx context.Context, id int,
|
||||
func (db *mongodb) LoadAllSerie(ctx context.Context) (model.SortedSeries, error) {
|
||||
collection := db.Database(mongoDBName).Collection(collectionSerie)
|
||||
|
||||
opts := options.Find().SetSort(bson.M{"id": -1})
|
||||
filter := bson.M{}
|
||||
cur, err := collection.Find(ctx, filter)
|
||||
cur, err := collection.Find(ctx, filter, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -201,7 +202,6 @@ func (db *mongodb) LoadAllSerie(ctx context.Context) (model.SortedSeries, error)
|
||||
}
|
||||
series = append(series, &obj)
|
||||
}
|
||||
sort.Sort(series)
|
||||
return series, nil
|
||||
}
|
||||
|
||||
@@ -232,11 +232,10 @@ func (db *mongodb) RemoveArticle(ctx context.Context, id int) error {
|
||||
}
|
||||
|
||||
// CleanArticles 清理回收站文章
|
||||
func (db *mongodb) CleanArticles(ctx context.Context) error {
|
||||
func (db *mongodb) CleanArticles(ctx context.Context, exp time.Time) error {
|
||||
collection := db.Database(mongoDBName).Collection(collectionArticle)
|
||||
|
||||
// 超过两天自动删除
|
||||
exp := time.Now().Add(-48 * time.Hour)
|
||||
filter := bson.M{"deleted_at": bson.M{"$gt": time.Time{}, "$lt": exp}}
|
||||
_, err := collection.DeleteMany(ctx, filter)
|
||||
return err
|
||||
|
||||
242
pkg/cache/store/rdbms.go
vendored
242
pkg/cache/store/rdbms.go
vendored
@@ -1,80 +1,170 @@
|
||||
// Package store provides ...
|
||||
package store
|
||||
|
||||
type rdbms struct{}
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
// // Init 数据库初始化, 建表, 加索引操作等
|
||||
// func (db *rdbms) Init(source string) (Store, error) {
|
||||
// gorm.
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // LoadInsertBlogger 读取或创建博客
|
||||
// func (db *rdbms) LoadInsertBlogger(ctx context.Context, blogger *model.Blogger) (bool, error) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // UpdateBlogger 更新博客
|
||||
// func (db *rdbms) UpdateBlogger(ctx context.Context, fields map[string]interface{}) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // LoadInsertAccount 读取或创建账户
|
||||
// func (db *rdbms) LoadInsertAccount(ctx context.Context, acct *model.Account) (bool, error) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // UpdateAccount 更新账户
|
||||
// func (db *rdbms) UpdateAccount(ctx context.Context, name string, fields map[string]interface{}) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // InsertSerie 创建专题
|
||||
// func (db *rdbms) InsertSerie(ctx context.Context, series *model.Serie) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // RemoveSerie 删除专题
|
||||
// func (db *rdbms) RemoveSerie(ctx context.Context, id int) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // UpdateSerie 更新专题
|
||||
// func (db *rdbms) UpdateSerie(ctx context.Context, id int, fields map[string]interface{}) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // LoadAllSerie 读取所有专题
|
||||
// func (db *rdbms) LoadAllSerie(ctx context.Context) (model.SortedSeries, error) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // InsertArticle 创建文章
|
||||
// func (db *rdbms) InsertArticle(ctx context.Context, article *model.Article) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // RemoveArticle 硬删除文章
|
||||
// func (db *rdbms) RemoveArticle(ctx context.Context, id int) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // CleanArticles 清理回收站文章
|
||||
// func (db *rdbms) CleanArticles(ctx context.Context) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // UpdateArticle 更新文章
|
||||
// func (db *rdbms) UpdateArticle(ctx context.Context, id int, fields map[string]interface{}) error {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // LoadArticle 查找文章
|
||||
// func (db *rdbms) LoadArticle(ctx context.Context, id int) (*model.Article, error) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // LoadArticleList 查找文章列表
|
||||
// func (db *rdbms) LoadArticleList(ctx context.Context, search SearchArticles) (model.SortedArticles, int, error) {
|
||||
//
|
||||
// }
|
||||
"github.com/eiblog/eiblog/pkg/model"
|
||||
|
||||
"gorm.io/driver/clickhouse"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/driver/sqlserver"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type rdbms struct {
|
||||
*gorm.DB
|
||||
}
|
||||
|
||||
// Init 数据库初始化, 建表, 加索引操作等
|
||||
// name 应该为具体的关系数据库驱动名
|
||||
func (db *rdbms) Init(name, source string) (Store, error) {
|
||||
var (
|
||||
gormDB *gorm.DB
|
||||
err error
|
||||
)
|
||||
switch name {
|
||||
case "mysql":
|
||||
// https://github.com/go-sql-driver/mysql
|
||||
gormDB, err = gorm.Open(mysql.Open(source), &gorm.Config{})
|
||||
case "postgres":
|
||||
// https://github.com/go-gorm/postgres
|
||||
gormDB, err = gorm.Open(postgres.Open(source), &gorm.Config{})
|
||||
case "sqlite":
|
||||
// github.com/mattn/go-sqlite3
|
||||
gormDB, err = gorm.Open(sqlite.Open(source), &gorm.Config{})
|
||||
case "sqlserver":
|
||||
// github.com/denisenkom/go-mssqldb
|
||||
gormDB, err = gorm.Open(sqlserver.Open(source), &gorm.Config{})
|
||||
case "clickhouse":
|
||||
gormDB, err = gorm.Open(clickhouse.Open(source), &gorm.Config{})
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// auto migrate
|
||||
gormDB.AutoMigrate(
|
||||
&model.Account{},
|
||||
&model.Blogger{},
|
||||
&model.Article{},
|
||||
&model.Serie{},
|
||||
)
|
||||
db.DB = gormDB
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// LoadInsertBlogger 读取或创建博客
|
||||
func (db *rdbms) LoadInsertBlogger(ctx context.Context, blogger *model.Blogger) (bool, error) {
|
||||
result := db.FirstOrCreate(blogger)
|
||||
return result.RowsAffected > 0, result.Error
|
||||
}
|
||||
|
||||
// UpdateBlogger 更新博客
|
||||
func (db *rdbms) UpdateBlogger(ctx context.Context, fields map[string]interface{}) error {
|
||||
return db.Model(model.Blogger{}).Updates(fields).Error
|
||||
}
|
||||
|
||||
// LoadInsertAccount 读取或创建账户
|
||||
func (db *rdbms) LoadInsertAccount(ctx context.Context, acct *model.Account) (bool, error) {
|
||||
result := db.Where("username=?", acct.Username).FirstOrCreate(acct)
|
||||
return result.RowsAffected > 0, result.Error
|
||||
}
|
||||
|
||||
// UpdateAccount 更新账户
|
||||
func (db *rdbms) UpdateAccount(ctx context.Context, name string, fields map[string]interface{}) error {
|
||||
return db.Model(model.Account{}).Where("username=?", name).Updates(fields).Error
|
||||
}
|
||||
|
||||
// InsertSerie 创建专题
|
||||
func (db *rdbms) InsertSerie(ctx context.Context, serie *model.Serie) error {
|
||||
return db.Create(serie).Error
|
||||
}
|
||||
|
||||
// RemoveSerie 删除专题
|
||||
func (db *rdbms) RemoveSerie(ctx context.Context, id int) error {
|
||||
return db.Where("id=?", id).Delete(model.Serie{}).Error
|
||||
}
|
||||
|
||||
// UpdateSerie 更新专题
|
||||
func (db *rdbms) UpdateSerie(ctx context.Context, id int, fields map[string]interface{}) error {
|
||||
return db.Model(model.Serie{}).Where("id=?", id).Updates(fields).Error
|
||||
}
|
||||
|
||||
// LoadAllSerie 读取所有专题
|
||||
func (db *rdbms) LoadAllSerie(ctx context.Context) (model.SortedSeries, error) {
|
||||
var series model.SortedSeries
|
||||
err := db.Order("id DESC").Find(&series).Error
|
||||
return series, err
|
||||
}
|
||||
|
||||
// InsertArticle 创建文章
|
||||
func (db *rdbms) InsertArticle(ctx context.Context, article *model.Article, startID int) error {
|
||||
// TODO id stting
|
||||
return db.Create(article).Error
|
||||
}
|
||||
|
||||
// RemoveArticle 硬删除文章
|
||||
func (db *rdbms) RemoveArticle(ctx context.Context, id int) error {
|
||||
return db.Where("id=?", id).Delete(model.Article{}).Error
|
||||
}
|
||||
|
||||
// CleanArticles 清理回收站文章
|
||||
func (db *rdbms) CleanArticles(ctx context.Context, exp time.Time) error {
|
||||
return db.Where("deleted_at BETWEEN ? AND ?", time.Time{}, exp).Delete(model.Article{}).Error
|
||||
}
|
||||
|
||||
// UpdateArticle 更新文章
|
||||
func (db *rdbms) UpdateArticle(ctx context.Context, id int, fields map[string]interface{}) error {
|
||||
return db.Model(model.Article{}).Where("id=?", id).Updates(fields).Error
|
||||
}
|
||||
|
||||
// LoadArticle 查找文章
|
||||
func (db *rdbms) LoadArticle(ctx context.Context, id int) (*model.Article, error) {
|
||||
article := &model.Article{}
|
||||
err := db.Where("id=?", id).First(article).Error
|
||||
return article, err
|
||||
}
|
||||
|
||||
// LoadArticleList 查找文章列表
|
||||
func (db *rdbms) LoadArticleList(ctx context.Context, search SearchArticles) (model.SortedArticles, int, error) {
|
||||
gormDB := db.Model(model.Article{})
|
||||
for k, v := range search.Fields {
|
||||
switch k {
|
||||
case SearchArticleDraft:
|
||||
if ok := v.(bool); ok {
|
||||
gormDB = gormDB.Where("is_draft=?", true)
|
||||
} else {
|
||||
gormDB = gormDB.Where("is_draft=? AND deleted_at=?", false, time.Time{})
|
||||
}
|
||||
case SearchArticleTitle:
|
||||
gormDB = gormDB.Where("title LIKE ?", "%"+v.(string)+"%")
|
||||
case SearchArticleSerieID:
|
||||
gormDB = gormDB.Where("serie_id=?", v.(int))
|
||||
case SearchArticleTrash:
|
||||
gormDB = gormDB.Where("deleted_at!=?", time.Time{})
|
||||
}
|
||||
}
|
||||
// search count
|
||||
var count int64
|
||||
err := gormDB.Count(&count).Error
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
var articles model.SortedArticles
|
||||
err = db.Limit(search.Limit).
|
||||
Offset((search.Page - 1) * search.Limit).
|
||||
Order("created_at DESC").Find(&articles).Error
|
||||
return articles, int(count), err
|
||||
}
|
||||
|
||||
// register store
|
||||
func init() {
|
||||
Register("mysql", &rdbms{})
|
||||
Register("postgres", &rdbms{})
|
||||
Register("sqlite", &rdbms{})
|
||||
Register("sqlserver", &rdbms{})
|
||||
Register("clickhouse", &rdbms{})
|
||||
}
|
||||
|
||||
5
pkg/cache/store/store.go
vendored
5
pkg/cache/store/store.go
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/eiblog/eiblog/pkg/model"
|
||||
)
|
||||
@@ -43,7 +44,7 @@ type Store interface {
|
||||
UpdateAccount(ctx context.Context, name string, fields map[string]interface{}) error
|
||||
|
||||
// InsertSerie 创建专题
|
||||
InsertSerie(ctx context.Context, series *model.Serie) error
|
||||
InsertSerie(ctx context.Context, serie *model.Serie) error
|
||||
// RemoveSerie 删除专题
|
||||
RemoveSerie(ctx context.Context, id int) error
|
||||
// UpdateSerie 更新专题
|
||||
@@ -56,7 +57,7 @@ type Store interface {
|
||||
// RemoveArticle 硬删除文章
|
||||
RemoveArticle(ctx context.Context, id int) error
|
||||
// CleanArticles 清理回收站文章
|
||||
CleanArticles(ctx context.Context) error
|
||||
CleanArticles(ctx context.Context, exp time.Time) error
|
||||
// UpdateArticle 更新文章
|
||||
UpdateArticle(ctx context.Context, id int, fields map[string]interface{}) error
|
||||
// LoadArticle 查找文章
|
||||
|
||||
Reference in New Issue
Block a user