作者 yangfu

feat: data layout v2

... ... @@ -16,6 +16,7 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0
github.com/google/uuid v1.3.0
github.com/gookit/event v1.0.6
github.com/imkira/go-interpol v1.1.0 // indirect
github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7
github.com/moul/http2curl v1.0.0 // indirect
... ...
package command
import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
type TableEventCommand struct {
EventTable *domain.EventTable
}
... ...
package service
import (
"github.com/linmadan/egglib-go/core/application"
"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"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
)
type TableEventService struct {
}
func (tableEventService *TableEventService) Handler(ctx *domain.Context, createFileCommand *command.TableEventCommand) (interface{}, error) {
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return nil, nil
}
func NewTableEventService(options map[string]interface{}) *TableEventService {
svr := &TableEventService{}
return svr
}
... ...
... ... @@ -16,6 +16,7 @@ type TablePreviewCommand struct {
PageNumber int `json:"pageNumber"`
PageSize int `json:"pageSize"`
Where domain.Where `json:"where"`
UseCache bool `json:"useCache"`
}
func (cmd *TablePreviewCommand) Valid(validation *validation.Validation) {
... ...
... ... @@ -6,6 +6,7 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/command"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/dto"
"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/starrocks"
)
... ... @@ -23,13 +24,38 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command
defer func() {
transactionContext.RollbackTransaction()
}()
var dataTable *domain.DataTable
var table *domain.Table
var cacheMiss bool
_, table, err = factory.FastPgTable(transactionContext, cmd.TableId)
if err != nil {
return nil, factory.FastError(err)
}
// 方案 计算项 计算集 做缓存
if cmd.UseCache && table.AssertTableType(domain.SchemaTable, domain.CalculateItem, domain.CalculateSet) {
if d, ok := cache.GetDataTable(table.TableId); ok {
dataTable = d
} else {
cacheMiss = true
}
}
response := &dto.TablePreviewDto{}
if dataTable == nil {
switch table.TableType {
case domain.CalculateSet.ToString():
querySetRepository, _, _ := factory.FastPgQuerySet(transactionContext, 0)
querySet, err := querySetRepository.FindOne(map[string]interface{}{"BindTableId": table.TableId})
if err != nil {
return nil, factory.FastError(err)
}
svr, _ := factory.FastQuerySetServices(transactionContext)
dataTable, err = svr.LoadCalculateSetData(ctx, querySet, querySet.QueryComponents)
if err != nil {
return nil, factory.FastError(err)
}
response.Fields = dataTable.Fields
response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, dataTable.Data, false), int64(len(dataTable.Data)))
default:
var options = starrocks.QueryOptions{
Table: table,
TableName: table.SQLName,
... ... @@ -37,12 +63,19 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command
}
options.SetCondition(cmd.Where.Conditions).SetDefaultOrder()
options.SetOffsetLimit(cmd.Where.PageNumber, cmd.Where.PageSize)
var dataTable *domain.DataTable
dataTable, err = factory.FastDataTable(options)
if err != nil {
return nil, factory.FastError(err)
}
response := (&dto.TablePreviewDto{}).Load(table, dataTable, domain.ObjectMetaTable)
response.Load(table, dataTable, domain.ObjectMetaTable)
}
}
if cacheMiss && dataTable != nil {
// 存储缓存
cache.SetDataTable(table.TableId, dataTable)
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
... ...
package domain
import "github.com/gookit/event"
type EventType string
func (et EventType) ToString() string {
return string(et)
}
const (
TableDataEditEvent EventType = "table.data.edit"
TableDataImportEvent EventType = "table.data.import"
TableDeleteEvent EventType = "table.delete"
QuerySetUpdateEvent EventType = "table.query.set.update"
)
type EventTable struct {
Type EventType
Table *Table
QuerySet *QuerySet
}
func (et *EventTable) WithType(t EventType) *EventTable {
et.Type = t
return et
}
func (et *EventTable) WithTable(t *Table) *EventTable {
et.Table = t
return et
}
func (et *EventTable) WithQuerySet(t *QuerySet) *EventTable {
et.QuerySet = t
return et
}
func (et *EventTable) ResolveEvent(e event.Event) {
et.Type = e.Get("Type").(EventType)
et.Table = e.Get("Table").(*Table)
et.QuerySet = e.Get("QuerySet").(*QuerySet)
}
func (et *EventTable) FireEvent() event.Event {
e := event.M{}
e["Type"] = et.Type
e["Table"] = et.Table
e["QuerySet"] = et.QuerySet
return event.MustFire(et.Type.ToString(), e)
}
... ...
... ... @@ -14,23 +14,28 @@ const (
)
type LayoutRule struct {
Layout
LayoutRuleItem
}
type Layout struct {
Cells [][]*LayoutCell `json:"cells"`
type LayoutRuleItem struct {
Cells []*LayoutCell `json:"cells"`
}
type LayoutCell struct {
Type string `json:"type,omitempty"` // Table TableField Text Null
Data *LayoutCellData `json:"data,omitempty"`
Direction string `json:"direction,omitempty"` // 向右:Right 向下:Down
X int `json:"-,omitempty"`
Y int `json:"-,omitempty"`
Position *Location `json:"position"`
X int `json:"-"`
Y int `json:"-"`
Length int `json:"-"`
BlockData []string `json:"-"`
ImageData string `json:"-"`
}
type Location struct {
X int `json:"x"`
Y int `json:"y"`
}
type LayoutCellData struct {
//Table *Table `json:"table,omitempty"`
... ... @@ -39,17 +44,22 @@ type LayoutCellData struct {
Text string `json:"text,omitempty"`
}
func (l *Layout) LayoutCells() []*LayoutCell {
func (l *LayoutRuleItem) LayoutCells() []*LayoutCell {
var cells = make([]*LayoutCell, 0)
for i, rows := range l.Cells {
for j, item := range rows {
if item.Type == CellTypeNull || item.Type == "" {
continue
}
item.X = i
item.Y = j
//for i, rows := range l.Cells {
// for j, item := range rows {
// if item.Type == CellTypeNull || item.Type == "" {
// continue
// }
// item.X = i
// item.Y = j
// cells = append(cells, item)
// }
//}
for _, item := range l.Cells {
item.X = item.Position.X
item.Y = item.Position.Y
cells = append(cells, item)
}
}
return cells
}
... ...
... ... @@ -123,3 +123,12 @@ func (t *Table) DependencyTables() []int {
}
return t.TableInfo.DependencyTables
}
func (t *Table) AssertTableType(types ...TableType) bool {
for _, item := range types {
if t.TableType == item.ToString() {
return true
}
}
return false
}
... ...
... ... @@ -3,6 +3,7 @@ package cache
import (
"fmt"
cache "github.com/patrickmn/go-cache"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"time"
)
... ... @@ -11,3 +12,37 @@ var DefaultCache = cache.New(12*time.Hour, 1*time.Hour)
func KeyCompanyUser(companyId int, userId int) string {
return fmt.Sprintf("local:cache:user:%d:%d", companyId, userId)
}
func KeyDataTable(tableId int) string {
return DefaultDataTableCacheService.KeyDataTable(tableId)
}
func GetDataTable(tableId int) (*domain.DataTable, bool) {
return DefaultDataTableCacheService.GetDataTable(tableId)
}
func SetDataTable(tableId int, table *domain.DataTable) {
DefaultDataTableCacheService.SetDataTable(tableId, table)
}
var DefaultDataTableCacheService = &DataTableCacheService{}
type DataTableCacheService struct {
}
func (svr *DataTableCacheService) KeyDataTable(tableId int) string {
return fmt.Sprintf("local:cache:table:%d", tableId)
}
func (svr *DataTableCacheService) GetDataTable(tableId int) (*domain.DataTable, bool) {
v, ok := DefaultCache.Get(KeyDataTable(tableId))
if !ok {
return nil, false
}
return v.(*domain.DataTable), true
}
func (svr *DataTableCacheService) SetDataTable(tableId int, table *domain.DataTable) {
DefaultCache.Set(KeyDataTable(tableId), table, 24*time.Hour*30)
}
func (svr *DataTableCacheService) DeleteDataTable(tableId int) {
DefaultCache.Delete(KeyDataTable(tableId))
}
... ...
package event
import (
"github.com/gookit/event"
)
func Start() {
RegisterEvent()
}
func RegisterEvent() {
event.On("table.*", event.ListenerFunc(tableDataChangeHandler), event.High)
}
... ...
package event
import (
"github.com/gookit/event"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/command"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/service"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
)
func tableDataChangeHandler(e event.Event) error {
et := &domain.EventTable{}
et.ResolveEvent(e)
svr := service.NewTableEventService(nil)
_, err := svr.Handler(nil, &command.TableEventCommand{
EventTable: et,
})
return err
}
... ...