158 lines
3.6 KiB
Go
158 lines
3.6 KiB
Go
package data
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/go-viper/mapstructure/v2"
|
|
"github.com/google/uuid"
|
|
"github.com/meilisearch/meilisearch-go"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type Event struct {
|
|
Id uint `json:"id" gorm:"primarykey;autoincrement"`
|
|
UUID uuid.UUID `json:"uuid" gorm:"type:uuid;uniqueIndex;not null"`
|
|
EventId uuid.UUID `json:"event_id" gorm:"type:uuid;uniqueIndex;not null"`
|
|
Name string `json:"name" gorm:"type:varchar(255);index;not null"`
|
|
Type string `json:"type" gotm:"type:varchar(255);index;not null"`
|
|
Description string `json:"description" gorm:"type:text;not null"`
|
|
StartTime time.Time `json:"start_time" gorm:"index"`
|
|
EndTime time.Time `json:"end_time" gorm:"index"`
|
|
Owner uuid.UUID `json:"owner" gorm:"type:uuid;index;not null"`
|
|
EnableKYC bool `json:"enable_kyc" gorm:"not null"`
|
|
}
|
|
|
|
type EventSearchDoc struct {
|
|
EventId string `json:"event_id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Description string `json:"description"`
|
|
StartTime time.Time `json:"start_time"`
|
|
EndTime time.Time `json:"end_time"`
|
|
}
|
|
|
|
func (self *Event) GetEventById(eventId uuid.UUID) (*Event, error) {
|
|
var event Event
|
|
|
|
err := Database.
|
|
Where("event_id = ?", eventId).
|
|
First(&event).Error
|
|
|
|
if err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &event, nil
|
|
}
|
|
|
|
func (self *Event) UpdateEventById(eventId uuid.UUID) error {
|
|
// DB transaction
|
|
if err := Database.Transaction(func(tx *gorm.DB) error {
|
|
// Update by business key
|
|
if err := tx.
|
|
Model(&Event{}).
|
|
Where("event_id = ?", eventId).
|
|
Updates(self).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// Reload to ensure struct is fresh
|
|
return tx.
|
|
Where("event_id = ?", eventId).
|
|
First(self).Error
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Sync search index
|
|
if err := self.UpdateSearchIndex(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *Event) Create() error {
|
|
self.UUID = uuid.New()
|
|
self.EventId = uuid.New()
|
|
|
|
// DB transaction only
|
|
if err := Database.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Create(self).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Search index (eventual consistency)
|
|
if err := self.UpdateSearchIndex(); err != nil {
|
|
// TODO: async retry / log
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *Event) GetFullTable() (*[]Event, error) {
|
|
var events []Event
|
|
err := Database.Find(&events).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &events, err
|
|
}
|
|
|
|
func (self *Event) FastListEvents(limit, offset int64) (*[]EventSearchDoc, error) {
|
|
index := MeiliSearch.Index("event")
|
|
|
|
// Fast read from MeiliSearch (no DB involved)
|
|
result, err := index.Search("", &meilisearch.SearchRequest{
|
|
Limit: limit,
|
|
Offset: offset,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var list []EventSearchDoc
|
|
if err := mapstructure.Decode(result.Hits, &list); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &list, nil
|
|
}
|
|
|
|
func (self *Event) UpdateSearchIndex() error {
|
|
doc := EventSearchDoc{
|
|
EventId: self.EventId.String(),
|
|
Name: self.Name,
|
|
Type: self.Type,
|
|
Description: self.Description,
|
|
StartTime: self.StartTime,
|
|
EndTime: self.EndTime,
|
|
}
|
|
index := MeiliSearch.Index("event")
|
|
|
|
primaryKey := "event_id"
|
|
opts := &meilisearch.DocumentOptions{
|
|
PrimaryKey: &primaryKey,
|
|
}
|
|
|
|
if _, err := index.UpdateDocuments([]EventSearchDoc{doc}, opts); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (self *Event) DeleteSearchIndex() error {
|
|
index := MeiliSearch.Index("event")
|
|
_, err := index.DeleteDocument(self.EventId.String(), nil)
|
|
return err
|
|
}
|