作者 yangfu

feat: table data cache v1

... ... @@ -13,6 +13,7 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
_ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
_ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/event"
)
const Version = "v1.2.0"
... ... @@ -34,7 +35,7 @@ func main() {
cron := crontab.NewCrontabService(nil)
cron.StartCrontabTask()
defer cron.StopCrontabTask()
event.Start()
log.Logger.Info("Service:" + constant.SERVICE_NAME)
log.Logger.Info("Version:" + Version)
log.Logger.Info("server start!")
... ...
... ... @@ -2,16 +2,20 @@ package service
import (
"github.com/linmadan/egglib-go/core/application"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/command"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
tablecommand "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/command"
tableservice "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/service"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/cache"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
)
type TableEventService struct {
}
func (tableEventService *TableEventService) Handler(ctx *domain.Context, createFileCommand *command.TableEventCommand) (interface{}, error) {
func (tableEventService *TableEventService) Handler(ctx *domain.Context, cmd *command.TableEventCommand) (interface{}, error) {
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
... ... @@ -23,10 +27,44 @@ func (tableEventService *TableEventService) Handler(ctx *domain.Context, createF
transactionContext.RollbackTransaction()
}()
data := cmd.EventTable
tableId := 0
switch data.Type {
case domain.TableDataImportEvent, domain.TableDataEditEvent, domain.TableDeleteEvent:
tableId = data.Table.TableId
case domain.QuerySetUpdateEvent:
tableId = data.QuerySet.QuerySetInfo.BindTableId
}
if tableId == 0 {
return nil, nil
}
// tableId 相关联的
tableRepository, _, _ := factory.FastPgTable(transactionContext, 0)
_, tables, err := tableRepository.Find(map[string]interface{}{"context": data.Context, "tableTypesNotIn": []string{domain.TemporaryTable.ToString(), domain.ExcelTable.ToString()}})
if err != nil {
return nil, err
}
tableDependencyService, _ := domainService.NewTableDependencyService(transactionContext.(*pgTransaction.TransactionContext))
tableDependTree := tableDependencyService.TableDependTree(tables, tableId)
tree := tableDependTree.Tree
tableService := tableservice.NewTableService(nil)
for i := range tree {
cache.DefaultDataTableCacheService.DeleteDataTable(tree[i])
// fresh cache
tableService.TablePreview(data.Context, &tablecommand.TablePreviewCommand{
TableId: tree[i],
ObjectType: domain.ObjectMetaTable,
PageSize: 10000,
PageNumber: 0,
UseCache: true,
})
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return nil, nil
}
... ...
... ... @@ -72,6 +72,14 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command
}
}
switch table.TableType {
case domain.CalculateSet.ToString():
response.Fields = dataTable.Fields
response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, dataTable.Data, false), int64(len(dataTable.Data)))
default:
response.Load(table, dataTable, domain.ObjectMetaTable)
}
if cacheMiss && dataTable != nil {
// 存储缓存
cache.SetDataTable(table.TableId, dataTable)
... ...
... ... @@ -16,11 +16,22 @@ const (
)
type EventTable struct {
Context *Context
Type EventType
Table *Table
QuerySet *QuerySet
}
func NewEventTable(ctx *Context, t EventType) *EventTable {
return &EventTable{
Context: ctx,
Type: t,
}
}
func (et *EventTable) WithContext(t *Context) *EventTable {
et.Context = t
return et
}
func (et *EventTable) WithType(t EventType) *EventTable {
et.Type = t
return et
... ... @@ -37,6 +48,7 @@ func (et *EventTable) WithQuerySet(t *QuerySet) *EventTable {
}
func (et *EventTable) ResolveEvent(e event.Event) {
et.Context = e.Get("Context").(*Context)
et.Type = e.Get("Type").(EventType)
et.Table = e.Get("Table").(*Table)
et.QuerySet = e.Get("QuerySet").(*QuerySet)
... ... @@ -44,6 +56,7 @@ func (et *EventTable) ResolveEvent(e event.Event) {
func (et *EventTable) FireEvent() event.Event {
e := event.M{}
e["Context"] = et.Context
e["Type"] = et.Type
e["Table"] = et.Table
e["QuerySet"] = et.QuerySet
... ...
... ... @@ -4,6 +4,7 @@ import (
"fmt"
cache "github.com/patrickmn/go-cache"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
"time"
)
... ... @@ -36,13 +37,17 @@ func (svr *DataTableCacheService) KeyDataTable(tableId int) string {
func (svr *DataTableCacheService) GetDataTable(tableId int) (*domain.DataTable, bool) {
v, ok := DefaultCache.Get(KeyDataTable(tableId))
if !ok {
log.Logger.Info(fmt.Sprintf("【缓存】 miss cache %v", KeyDataTable(tableId)))
return nil, false
}
log.Logger.Info(fmt.Sprintf("【缓存】 hit cache %v", KeyDataTable(tableId)))
return v.(*domain.DataTable), true
}
func (svr *DataTableCacheService) SetDataTable(tableId int, table *domain.DataTable) {
log.Logger.Info(fmt.Sprintf("【缓存】 set cache %v", KeyDataTable(tableId)))
DefaultCache.Set(KeyDataTable(tableId), table, 24*time.Hour*30)
}
func (svr *DataTableCacheService) DeleteDataTable(tableId int) {
log.Logger.Info(fmt.Sprintf("【缓存】 delete cache %v", KeyDataTable(tableId)))
DefaultCache.Delete(KeyDataTable(tableId))
}
... ...
package domainService
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
"time"
)
func AsyncEvent(e *domain.EventTable) {
go func() {
defer func() {
if p := recover(); p != nil {
log.Logger.Error(fmt.Sprintf("%v", p))
}
}()
time.Sleep(time.Second * 1)
e.FireEvent()
}()
}
... ...
... ... @@ -95,6 +95,9 @@ func (ptr *QuerySetService) Update(ctx *domain.Context, querySetId int, queryCom
if err != nil {
return err
}
defer func() {
AsyncEvent(domain.NewEventTable(ctx, domain.QuerySetUpdateEvent).WithQuerySet(qs))
}()
if qs.Type == domain.SchemaTable.ToString() || qs.Type == domain.SubProcessTable.ToString() {
return ptr.UpdateDefault(ctx, qs, queryComponents)
}
... ...
... ... @@ -409,6 +409,34 @@ func TestDataLayout(t *testing.T) {
},
flag: Location{X: 2, Y: 1},
},
{
title: "测试用例6",
cells: []*domain.LayoutCell{
// 分组一
{
X: 0,
Y: 0,
Length: 1,
ImageData: "a",
Direction: domain.DirectionNone,
},
{
X: 1,
Y: 1,
Length: 5,
ImageData: "c",
Direction: domain.DirectionRight,
},
{
X: 2,
Y: 1,
Length: 5,
ImageData: "d",
Direction: domain.DirectionRight,
},
},
flag: Location{X: 0, Y: 0},
},
}
padding := func(cells []*domain.LayoutCell) {
for _, cell := range cells {
... ... @@ -472,7 +500,9 @@ b | | | | | | | | |
b | | | | | | | | |
| | | | | d | d | d | d | d
a | | | | |
| c | c | c | c | c
| d | d | d | d | d
*/
func printRes(res *domain.DataTable) {
... ...
... ... @@ -24,7 +24,9 @@ func (ptr *AppendDataToTableService) AppendData(ctx *domain.Context, fileId int,
if err != nil {
return nil, fmt.Errorf("表不存在")
}
defer func() {
AsyncEvent(domain.NewEventTable(ctx, domain.TableDataImportEvent).WithTable(table))
}()
excelTable, err := tableRepository.FindOne(map[string]interface{}{"tableId": file.FileInfo.TableId})
if err != nil {
return nil, fmt.Errorf("文件未校验")
... ...
... ... @@ -170,6 +170,9 @@ func (ptr *TableDependencyService) makeParentMap(tables []*domain.Table) map[int
if _, ok := res[tables[i].TableId]; !ok {
res[tables[i].TableId] = make([]int, 0)
}
if tables[i].TableInfo == nil {
continue
}
for _, t := range tables[i].TableInfo.DependencyTables {
if _, ok := res[t]; !ok {
res[t] = make([]int, 0)
... ... @@ -186,7 +189,9 @@ func (ptr *TableDependencyService) makeChildMap(tables []*domain.Table) map[int]
if _, ok := res[id]; !ok {
res[id] = make([]int, 0)
}
if tables[i].TableInfo == nil {
continue
}
res[id] = append(res[id], tables[i].TableInfo.DependencyTables...)
}
return res
... ... @@ -250,7 +255,7 @@ func (ptr *TableDependencyService) makeTrees(childMap map[int][]int, rootNodes [
func TableHasDependency(transactionContext *pgTransaction.TransactionContext, ctx *domain.Context, dependencyTable int) ([]*domain.Table, bool) {
tableRepository, _ := repository.NewTableRepository(transactionContext)
_, tables, err := tableRepository.Find(map[string]interface{}{"context": ctx, "dependencyTable": dependencyTable})
_, tables, err := tableRepository.Find(map[string]interface{}{"context": ctx, "dependencyTable": dependencyTable, "tableTypesNotIn": []string{domain.TemporaryTable.ToString()}})
if errors.Is(err, domain.ErrorNotFound) {
return nil, false
}
... ...
... ... @@ -37,6 +37,9 @@ func (ptr *TableEditDataService) RowEdit(ctx *domain.Context, request domain.Edi
if table.TableType != domain.SideTable.ToString() {
return nil, fmt.Errorf("副表才允许编辑数据")
}
defer func() {
AsyncEvent(domain.NewEventTable(ctx, domain.TableDataEditEvent).WithTable(table))
}()
for _, l := range request.AddList {
if addErr := ptr.add(ctx, table, l, request.Where); addErr != nil {
... ...
... ... @@ -175,6 +175,9 @@ func (repository *TableRepository) Find(queryOptions map[string]interface{}) (in
if v, ok := queryOptions["tableTypes"]; ok && len(v.([]string)) > 0 {
query.Where(`table_type in (?)`, pg.In(v.([]string)))
}
if v, ok := queryOptions["tableTypesNotIn"]; ok && len(v.([]string)) > 0 {
query.Where(`table_type not in (?)`, pg.In(v.([]string)))
}
if v, ok := queryOptions["module"]; ok && v.(int) > 0 {
query.Where(`(cast(table_info->>'module' as integer) & ?) >0`, v)
}
... ...
... ... @@ -2,6 +2,7 @@ package event
import (
"github.com/gookit/event"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
)
func Start() {
... ... @@ -9,5 +10,8 @@ func Start() {
}
func RegisterEvent() {
event.On("table.*", event.ListenerFunc(tableDataChangeHandler), event.High)
event.On(domain.TableDataEditEvent.ToString(), event.ListenerFunc(tableDataChangeHandler), event.High)
event.On(domain.TableDataImportEvent.ToString(), event.ListenerFunc(tableDataChangeHandler), event.High)
event.On(domain.TableDeleteEvent.ToString(), event.ListenerFunc(tableDataChangeHandler), event.High)
event.On(domain.QuerySetUpdateEvent.ToString(), event.ListenerFunc(tableDataChangeHandler), event.High)
}
... ...