作者 yangfu

feat: data layout v2

@@ -16,6 +16,7 @@ require ( @@ -16,6 +16,7 @@ require (
16 github.com/google/go-querystring v1.1.0 // indirect 16 github.com/google/go-querystring v1.1.0 // indirect
17 github.com/google/gofuzz v1.2.0 17 github.com/google/gofuzz v1.2.0
18 github.com/google/uuid v1.3.0 18 github.com/google/uuid v1.3.0
  19 + github.com/gookit/event v1.0.6
19 github.com/imkira/go-interpol v1.1.0 // indirect 20 github.com/imkira/go-interpol v1.1.0 // indirect
20 github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 21 github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7
21 github.com/moul/http2curl v1.0.0 // indirect 22 github.com/moul/http2curl v1.0.0 // indirect
  1 +package command
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type TableEventCommand struct {
  6 + EventTable *domain.EventTable
  7 +}
  1 +package service
  2 +
  3 +import (
  4 + "github.com/linmadan/egglib-go/core/application"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/command"
  6 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  8 +)
  9 +
  10 +type TableEventService struct {
  11 +}
  12 +
  13 +func (tableEventService *TableEventService) Handler(ctx *domain.Context, createFileCommand *command.TableEventCommand) (interface{}, error) {
  14 +
  15 + transactionContext, err := factory.CreateTransactionContext(nil)
  16 + if err != nil {
  17 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  18 + }
  19 + if err := transactionContext.StartTransaction(); err != nil {
  20 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  21 + }
  22 + defer func() {
  23 + transactionContext.RollbackTransaction()
  24 + }()
  25 +
  26 + if err := transactionContext.CommitTransaction(); err != nil {
  27 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  28 + }
  29 +
  30 + return nil, nil
  31 +}
  32 +
  33 +func NewTableEventService(options map[string]interface{}) *TableEventService {
  34 + svr := &TableEventService{}
  35 + return svr
  36 +}
@@ -16,6 +16,7 @@ type TablePreviewCommand struct { @@ -16,6 +16,7 @@ type TablePreviewCommand struct {
16 PageNumber int `json:"pageNumber"` 16 PageNumber int `json:"pageNumber"`
17 PageSize int `json:"pageSize"` 17 PageSize int `json:"pageSize"`
18 Where domain.Where `json:"where"` 18 Where domain.Where `json:"where"`
  19 + UseCache bool `json:"useCache"`
19 } 20 }
20 21
21 func (cmd *TablePreviewCommand) Valid(validation *validation.Validation) { 22 func (cmd *TablePreviewCommand) Valid(validation *validation.Validation) {
@@ -6,6 +6,7 @@ import ( @@ -6,6 +6,7 @@ import (
6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/command" 6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/command"
7 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/dto" 7 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/dto"
8 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" 8 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  9 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/cache"
9 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks" 10 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
10 ) 11 )
11 12
@@ -23,26 +24,58 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command @@ -23,26 +24,58 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command
23 defer func() { 24 defer func() {
24 transactionContext.RollbackTransaction() 25 transactionContext.RollbackTransaction()
25 }() 26 }()
26 - 27 + var dataTable *domain.DataTable
27 var table *domain.Table 28 var table *domain.Table
  29 + var cacheMiss bool
28 _, table, err = factory.FastPgTable(transactionContext, cmd.TableId) 30 _, table, err = factory.FastPgTable(transactionContext, cmd.TableId)
29 if err != nil { 31 if err != nil {
30 return nil, factory.FastError(err) 32 return nil, factory.FastError(err)
31 } 33 }
  34 + // 方案 计算项 计算集 做缓存
  35 + if cmd.UseCache && table.AssertTableType(domain.SchemaTable, domain.CalculateItem, domain.CalculateSet) {
  36 + if d, ok := cache.GetDataTable(table.TableId); ok {
  37 + dataTable = d
  38 + } else {
  39 + cacheMiss = true
  40 + }
  41 + }
  42 + response := &dto.TablePreviewDto{}
  43 + if dataTable == nil {
  44 + switch table.TableType {
  45 + case domain.CalculateSet.ToString():
  46 + querySetRepository, _, _ := factory.FastPgQuerySet(transactionContext, 0)
  47 + querySet, err := querySetRepository.FindOne(map[string]interface{}{"BindTableId": table.TableId})
  48 + if err != nil {
  49 + return nil, factory.FastError(err)
  50 + }
  51 + svr, _ := factory.FastQuerySetServices(transactionContext)
  52 + dataTable, err = svr.LoadCalculateSetData(ctx, querySet, querySet.QueryComponents)
  53 + if err != nil {
  54 + return nil, factory.FastError(err)
  55 + }
  56 + response.Fields = dataTable.Fields
  57 + response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, dataTable.Data, false), int64(len(dataTable.Data)))
  58 + default:
  59 + var options = starrocks.QueryOptions{
  60 + Table: table,
  61 + TableName: table.SQLName,
  62 + Select: table.Fields(true),
  63 + }
  64 + options.SetCondition(cmd.Where.Conditions).SetDefaultOrder()
  65 + options.SetOffsetLimit(cmd.Where.PageNumber, cmd.Where.PageSize)
32 66
33 - var options = starrocks.QueryOptions{  
34 - Table: table,  
35 - TableName: table.SQLName,  
36 - Select: table.Fields(true), 67 + dataTable, err = factory.FastDataTable(options)
  68 + if err != nil {
  69 + return nil, factory.FastError(err)
  70 + }
  71 + response.Load(table, dataTable, domain.ObjectMetaTable)
  72 + }
37 } 73 }
38 - options.SetCondition(cmd.Where.Conditions).SetDefaultOrder()  
39 - options.SetOffsetLimit(cmd.Where.PageNumber, cmd.Where.PageSize)  
40 - var dataTable *domain.DataTable  
41 - dataTable, err = factory.FastDataTable(options)  
42 - if err != nil {  
43 - return nil, factory.FastError(err) 74 +
  75 + if cacheMiss && dataTable != nil {
  76 + // 存储缓存
  77 + cache.SetDataTable(table.TableId, dataTable)
44 } 78 }
45 - response := (&dto.TablePreviewDto{}).Load(table, dataTable, domain.ObjectMetaTable)  
46 if err := transactionContext.CommitTransaction(); err != nil { 79 if err := transactionContext.CommitTransaction(); err != nil {
47 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 80 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
48 } 81 }
  1 +package domain
  2 +
  3 +import "github.com/gookit/event"
  4 +
  5 +type EventType string
  6 +
  7 +func (et EventType) ToString() string {
  8 + return string(et)
  9 +}
  10 +
  11 +const (
  12 + TableDataEditEvent EventType = "table.data.edit"
  13 + TableDataImportEvent EventType = "table.data.import"
  14 + TableDeleteEvent EventType = "table.delete"
  15 + QuerySetUpdateEvent EventType = "table.query.set.update"
  16 +)
  17 +
  18 +type EventTable struct {
  19 + Type EventType
  20 + Table *Table
  21 + QuerySet *QuerySet
  22 +}
  23 +
  24 +func (et *EventTable) WithType(t EventType) *EventTable {
  25 + et.Type = t
  26 + return et
  27 +}
  28 +
  29 +func (et *EventTable) WithTable(t *Table) *EventTable {
  30 + et.Table = t
  31 + return et
  32 +}
  33 +
  34 +func (et *EventTable) WithQuerySet(t *QuerySet) *EventTable {
  35 + et.QuerySet = t
  36 + return et
  37 +}
  38 +
  39 +func (et *EventTable) ResolveEvent(e event.Event) {
  40 + et.Type = e.Get("Type").(EventType)
  41 + et.Table = e.Get("Table").(*Table)
  42 + et.QuerySet = e.Get("QuerySet").(*QuerySet)
  43 +}
  44 +
  45 +func (et *EventTable) FireEvent() event.Event {
  46 + e := event.M{}
  47 + e["Type"] = et.Type
  48 + e["Table"] = et.Table
  49 + e["QuerySet"] = et.QuerySet
  50 + return event.MustFire(et.Type.ToString(), e)
  51 +}
@@ -14,23 +14,28 @@ const ( @@ -14,23 +14,28 @@ const (
14 ) 14 )
15 15
16 type LayoutRule struct { 16 type LayoutRule struct {
17 - Layout 17 + LayoutRuleItem
18 } 18 }
19 19
20 -type Layout struct {  
21 - Cells [][]*LayoutCell `json:"cells"` 20 +type LayoutRuleItem struct {
  21 + Cells []*LayoutCell `json:"cells"`
22 } 22 }
23 23
24 type LayoutCell struct { 24 type LayoutCell struct {
25 Type string `json:"type,omitempty"` // Table TableField Text Null 25 Type string `json:"type,omitempty"` // Table TableField Text Null
26 Data *LayoutCellData `json:"data,omitempty"` 26 Data *LayoutCellData `json:"data,omitempty"`
27 Direction string `json:"direction,omitempty"` // 向右:Right 向下:Down 27 Direction string `json:"direction,omitempty"` // 向右:Right 向下:Down
28 - X int `json:"-,omitempty"`  
29 - Y int `json:"-,omitempty"` 28 + Position *Location `json:"position"`
  29 + X int `json:"-"`
  30 + Y int `json:"-"`
30 Length int `json:"-"` 31 Length int `json:"-"`
31 BlockData []string `json:"-"` 32 BlockData []string `json:"-"`
32 ImageData string `json:"-"` 33 ImageData string `json:"-"`
33 } 34 }
  35 +type Location struct {
  36 + X int `json:"x"`
  37 + Y int `json:"y"`
  38 +}
34 39
35 type LayoutCellData struct { 40 type LayoutCellData struct {
36 //Table *Table `json:"table,omitempty"` 41 //Table *Table `json:"table,omitempty"`
@@ -39,17 +44,22 @@ type LayoutCellData struct { @@ -39,17 +44,22 @@ type LayoutCellData struct {
39 Text string `json:"text,omitempty"` 44 Text string `json:"text,omitempty"`
40 } 45 }
41 46
42 -func (l *Layout) LayoutCells() []*LayoutCell { 47 +func (l *LayoutRuleItem) LayoutCells() []*LayoutCell {
43 var cells = make([]*LayoutCell, 0) 48 var cells = make([]*LayoutCell, 0)
44 - for i, rows := range l.Cells {  
45 - for j, item := range rows {  
46 - if item.Type == CellTypeNull || item.Type == "" {  
47 - continue  
48 - }  
49 - item.X = i  
50 - item.Y = j  
51 - cells = append(cells, item)  
52 - } 49 + //for i, rows := range l.Cells {
  50 + // for j, item := range rows {
  51 + // if item.Type == CellTypeNull || item.Type == "" {
  52 + // continue
  53 + // }
  54 + // item.X = i
  55 + // item.Y = j
  56 + // cells = append(cells, item)
  57 + // }
  58 + //}
  59 + for _, item := range l.Cells {
  60 + item.X = item.Position.X
  61 + item.Y = item.Position.Y
  62 + cells = append(cells, item)
53 } 63 }
54 return cells 64 return cells
55 } 65 }
@@ -123,3 +123,12 @@ func (t *Table) DependencyTables() []int { @@ -123,3 +123,12 @@ func (t *Table) DependencyTables() []int {
123 } 123 }
124 return t.TableInfo.DependencyTables 124 return t.TableInfo.DependencyTables
125 } 125 }
  126 +
  127 +func (t *Table) AssertTableType(types ...TableType) bool {
  128 + for _, item := range types {
  129 + if t.TableType == item.ToString() {
  130 + return true
  131 + }
  132 + }
  133 + return false
  134 +}
@@ -3,6 +3,7 @@ package cache @@ -3,6 +3,7 @@ package cache
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 cache "github.com/patrickmn/go-cache" 5 cache "github.com/patrickmn/go-cache"
  6 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
6 "time" 7 "time"
7 ) 8 )
8 9
@@ -11,3 +12,37 @@ var DefaultCache = cache.New(12*time.Hour, 1*time.Hour) @@ -11,3 +12,37 @@ var DefaultCache = cache.New(12*time.Hour, 1*time.Hour)
11 func KeyCompanyUser(companyId int, userId int) string { 12 func KeyCompanyUser(companyId int, userId int) string {
12 return fmt.Sprintf("local:cache:user:%d:%d", companyId, userId) 13 return fmt.Sprintf("local:cache:user:%d:%d", companyId, userId)
13 } 14 }
  15 +
  16 +func KeyDataTable(tableId int) string {
  17 + return DefaultDataTableCacheService.KeyDataTable(tableId)
  18 +}
  19 +
  20 +func GetDataTable(tableId int) (*domain.DataTable, bool) {
  21 + return DefaultDataTableCacheService.GetDataTable(tableId)
  22 +}
  23 +
  24 +func SetDataTable(tableId int, table *domain.DataTable) {
  25 + DefaultDataTableCacheService.SetDataTable(tableId, table)
  26 +}
  27 +
  28 +var DefaultDataTableCacheService = &DataTableCacheService{}
  29 +
  30 +type DataTableCacheService struct {
  31 +}
  32 +
  33 +func (svr *DataTableCacheService) KeyDataTable(tableId int) string {
  34 + return fmt.Sprintf("local:cache:table:%d", tableId)
  35 +}
  36 +func (svr *DataTableCacheService) GetDataTable(tableId int) (*domain.DataTable, bool) {
  37 + v, ok := DefaultCache.Get(KeyDataTable(tableId))
  38 + if !ok {
  39 + return nil, false
  40 + }
  41 + return v.(*domain.DataTable), true
  42 +}
  43 +func (svr *DataTableCacheService) SetDataTable(tableId int, table *domain.DataTable) {
  44 + DefaultCache.Set(KeyDataTable(tableId), table, 24*time.Hour*30)
  45 +}
  46 +func (svr *DataTableCacheService) DeleteDataTable(tableId int) {
  47 + DefaultCache.Delete(KeyDataTable(tableId))
  48 +}
  1 +package event
  2 +
  3 +import (
  4 + "github.com/gookit/event"
  5 +)
  6 +
  7 +func Start() {
  8 + RegisterEvent()
  9 +}
  10 +
  11 +func RegisterEvent() {
  12 + event.On("table.*", event.ListenerFunc(tableDataChangeHandler), event.High)
  13 +}
  1 +package event
  2 +
  3 +import (
  4 + "github.com/gookit/event"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/command"
  6 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/service"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  8 +)
  9 +
  10 +func tableDataChangeHandler(e event.Event) error {
  11 + et := &domain.EventTable{}
  12 + et.ResolveEvent(e)
  13 + svr := service.NewTableEventService(nil)
  14 + _, err := svr.Handler(nil, &command.TableEventCommand{
  15 + EventTable: et,
  16 + })
  17 + return err
  18 +}