Add BulkExistsFunc() to LikeStore.

Add AddScheduledDayTask() and ScheduledDayTaskCount()
Reduce boilerplate.
This commit is contained in:
Azareal 2021-04-29 22:59:48 +10:00
parent ea4da062c3
commit 39ace845b7
4 changed files with 78 additions and 40 deletions

View File

@ -10,6 +10,7 @@ var Likes LikeStore
type LikeStore interface { type LikeStore interface {
BulkExists(ids []int, sentBy int, targetType string) ([]int, error) BulkExists(ids []int, sentBy int, targetType string) ([]int, error)
BulkExistsFunc(ids []int, sentBy int, targetType string, f func(int) error) error
Delete(targetID int, targetType string) error Delete(targetID int, targetType string) error
Count() (count int) Count() (count int)
} }
@ -56,6 +57,36 @@ func (s *DefaultLikeStore) BulkExists(ids []int, sentBy int, targetType string)
return eids, rows.Err() return eids, rows.Err()
} }
// TODO: Write a test for this
func (s *DefaultLikeStore) BulkExistsFunc(ids []int, sentBy int, targetType string, f func(id int) error) (e error) {
if len(ids) == 0 {
return nil
}
var rows *sql.Rows
if len(ids) == 1 {
rows, e = s.singleExists.Query(sentBy, targetType, ids[0])
} else {
rows, e = qgen.NewAcc().Select("likes").Columns("targetItem").Where("sentBy=? AND targetType=?").In("targetItem", ids).Query(sentBy, targetType)
}
if e == sql.ErrNoRows {
return nil
} else if e != nil {
return e
}
defer rows.Close()
var id int
for rows.Next() {
if e := rows.Scan(&id); e != nil {
return e
}
if e := f(id); e != nil {
return e
}
}
return rows.Err()
}
func (s *DefaultLikeStore) Delete(targetID int, targetType string) error { func (s *DefaultLikeStore) Delete(targetID int, targetType string) error {
_, err := s.delete.Exec(targetID, targetType) _, err := s.delete.Exec(targetID, targetType)
return err return err

View File

@ -77,32 +77,32 @@ func init() {
} }
func (i MenuItem) Commit() error { func (i MenuItem) Commit() error {
_, err := menuItemStmts.update.Exec(i.Name, i.HTMLID, i.CSSClass, i.Position, i.Path, i.Aria, i.Tooltip, i.TmplName, i.GuestOnly, i.MemberOnly, i.SuperModOnly, i.AdminOnly, i.ID) _, e := menuItemStmts.update.Exec(i.Name, i.HTMLID, i.CSSClass, i.Position, i.Path, i.Aria, i.Tooltip, i.TmplName, i.GuestOnly, i.MemberOnly, i.SuperModOnly, i.AdminOnly, i.ID)
Menus.Load(i.MenuID) Menus.Load(i.MenuID)
return err return e
} }
func (i MenuItem) Create() (int, error) { func (i MenuItem) Create() (int, error) {
res, err := menuItemStmts.insert.Exec(i.MenuID, i.Name, i.HTMLID, i.CSSClass, i.Position, i.Path, i.Aria, i.Tooltip, i.TmplName, i.GuestOnly, i.MemberOnly, i.SuperModOnly, i.AdminOnly) res, e := menuItemStmts.insert.Exec(i.MenuID, i.Name, i.HTMLID, i.CSSClass, i.Position, i.Path, i.Aria, i.Tooltip, i.TmplName, i.GuestOnly, i.MemberOnly, i.SuperModOnly, i.AdminOnly)
if err != nil { if e != nil {
return 0, err return 0, e
} }
Menus.Load(i.MenuID) Menus.Load(i.MenuID)
miid64, err := res.LastInsertId() miid64, e := res.LastInsertId()
return int(miid64), err return int(miid64), e
} }
func (i MenuItem) Delete() error { func (i MenuItem) Delete() error {
_, err := menuItemStmts.delete.Exec(i.ID) _, e := menuItemStmts.delete.Exec(i.ID)
Menus.Load(i.MenuID) Menus.Load(i.MenuID)
return err return e
} }
func (h *MenuListHolder) LoadTmpl(name string) (t MenuTmpl, err error) { func (h *MenuListHolder) LoadTmpl(name string) (t MenuTmpl, e error) {
data, err := ioutil.ReadFile("./templates/" + name + ".html") data, e := ioutil.ReadFile("./templates/" + name + ".html")
if err != nil { if e != nil {
return t, err return t, e
} }
return h.Parse(name, []byte(tmpl.Minify(string(data)))), nil return h.Parse(name, []byte(tmpl.Minify(string(data)))), nil
} }
@ -110,31 +110,31 @@ func (h *MenuListHolder) LoadTmpl(name string) (t MenuTmpl, err error) {
// TODO: Make this atomic, maybe with a transaction or store the order on the menu itself? // TODO: Make this atomic, maybe with a transaction or store the order on the menu itself?
func (h *MenuListHolder) UpdateOrder(updateMap map[int]int) error { func (h *MenuListHolder) UpdateOrder(updateMap map[int]int) error {
for miid, order := range updateMap { for miid, order := range updateMap {
_, err := menuItemStmts.updateOrder.Exec(order, miid) _, e := menuItemStmts.updateOrder.Exec(order, miid)
if err != nil { if e != nil {
return err return e
} }
} }
Menus.Load(h.MenuID) Menus.Load(h.MenuID)
return nil return nil
} }
func (h *MenuListHolder) LoadTmpls() (tmpls map[string]MenuTmpl, err error) { func (h *MenuListHolder) LoadTmpls() (tmpls map[string]MenuTmpl, e error) {
tmpls = make(map[string]MenuTmpl) tmpls = make(map[string]MenuTmpl)
load := func(name string) error { load := func(name string) error {
menuTmpl, err := h.LoadTmpl(name) menuTmpl, e := h.LoadTmpl(name)
if err != nil { if e != nil {
return err return e
} }
tmpls[name] = menuTmpl tmpls[name] = menuTmpl
return nil return nil
} }
err = load("menu_item") e = load("menu_item")
if err != nil { if e != nil {
return tmpls, err return tmpls, e
} }
err = load("menu_alerts") e = load("menu_alerts")
return tmpls, err return tmpls, e
} }
// TODO: Run this in main, sync ticks, when the phrase file changes (need to implement the sync for that first), and when the settings are changed // TODO: Run this in main, sync ticks, when the phrase file changes (need to implement the sync for that first), and when the settings are changed
@ -259,8 +259,8 @@ type MenuTmpl struct {
func menuDumpSlice(outerSlice [][]byte) { func menuDumpSlice(outerSlice [][]byte) {
for sliceID, slice := range outerSlice { for sliceID, slice := range outerSlice {
fmt.Print(strconv.Itoa(sliceID) + ":[") fmt.Print(strconv.Itoa(sliceID) + ":[")
for _, char := range slice { for _, ch := range slice {
fmt.Print(string(char)) fmt.Print(string(ch))
} }
fmt.Print("] ") fmt.Print("] ")
} }

View File

@ -23,6 +23,7 @@ var ScheduledHalfSecondTasks []func() error
var ScheduledSecondTasks []func() error var ScheduledSecondTasks []func() error
var ScheduledFifteenMinuteTasks []func() error var ScheduledFifteenMinuteTasks []func() error
var ScheduledHourTasks []func() error var ScheduledHourTasks []func() error
var ScheduledDayTasks []func() error
var ShutdownTasks []func() error var ShutdownTasks []func() error
var taskStmts TaskStmts var taskStmts TaskStmts
var lastSync time.Time var lastSync time.Time
@ -59,6 +60,11 @@ func AddScheduledHourTask(task func() error) {
ScheduledHourTasks = append(ScheduledHourTasks, task) ScheduledHourTasks = append(ScheduledHourTasks, task)
} }
// AddScheduledDayTask is not concurrency safe
func AddScheduledDayTask(task func() error) {
ScheduledDayTasks = append(ScheduledDayTasks, task)
}
// AddShutdownTask is not concurrency safe // AddShutdownTask is not concurrency safe
func AddShutdownTask(task func() error) { func AddShutdownTask(task func() error) {
ShutdownTasks = append(ShutdownTasks, task) ShutdownTasks = append(ShutdownTasks, task)
@ -84,6 +90,11 @@ func ScheduledHourTaskCount() int {
return len(ScheduledHourTasks) return len(ScheduledHourTasks)
} }
// ScheduledDayTaskCount is not concurrency safe
func ScheduledDayTaskCount() int {
return len(ScheduledDayTasks)
}
// ShutdownTaskCount is not concurrency safe // ShutdownTaskCount is not concurrency safe
func ShutdownTaskCount() int { func ShutdownTaskCount() int {
return len(ShutdownTasks) return len(ShutdownTasks)
@ -105,8 +116,7 @@ func HandleExpiredScheduledGroups() error {
// Sneaky way of initialising a *User, please use the methods on the UserStore instead // Sneaky way of initialising a *User, please use the methods on the UserStore instead
user := BlankUser() user := BlankUser()
user.ID = uid user.ID = uid
e = user.RevertGroupUpdate() if e = user.RevertGroupUpdate(); e != nil {
if e != nil {
return e return e
} }
} }
@ -130,20 +140,17 @@ func HandleServerSync() error {
} }
if lastUpdate.After(lastSync) { if lastUpdate.After(lastSync) {
e = Forums.LoadForums() if e = Forums.LoadForums(); e != nil {
if e != nil {
log.Print("Unable to reload the forums") log.Print("Unable to reload the forums")
return e return e
} }
// TODO: Resync the groups // TODO: Resync the groups
// TODO: Resync the permissions // TODO: Resync the permissions
e = LoadSettings() if e = LoadSettings(); e != nil {
if e != nil {
log.Print("Unable to reload the settings") log.Print("Unable to reload the settings")
return e return e
} }
e = WordFilters.ReloadAll() if e = WordFilters.ReloadAll(); e != nil {
if e != nil {
log.Print("Unable to reload the word filters") log.Print("Unable to reload the word filters")
return e return e
} }

View File

@ -1048,12 +1048,12 @@ func (t *TopicUser) Replies(offset int /*pFrag int, */, user *User) (rlist []*Re
// TODO: Add a config setting to disable the liked query for a burst of extra speed // TODO: Add a config setting to disable the liked query for a burst of extra speed
if user.Liked > 0 && len(likedQueryList) > 0 /*&& user.LastLiked <= time.Now()*/ { if user.Liked > 0 && len(likedQueryList) > 0 /*&& user.LastLiked <= time.Now()*/ {
eids, err := Likes.BulkExists(likedQueryList, user.ID, "replies") e := Likes.BulkExistsFunc(likedQueryList, user.ID, "replies", func(eid int) error {
if err != nil {
return nil, externalHead, err
}
for _, eid := range eids {
rlist[likedMap[eid]].Liked = true rlist[likedMap[eid]].Liked = true
return nil
})
if e != nil {
return nil, externalHead, e
} }
} }