focalboard/server/services/store/sqlstore/cloud.go
Miguel de la Cruz fa6de94070
Adds limits implementation to the server (#3213)
* Adds limits implementation to the server

* Add test for deleted boards on active card count
2022-06-15 12:17:44 +02:00

117 lines
3 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package sqlstore
import (
"database/sql"
"errors"
"strconv"
sq "github.com/Masterminds/squirrel"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/store"
)
var ErrInvalidCardLimitValue = errors.New("card limit value is invalid")
// activeCardsQuery applies the necessary filters to the query for it
// to fetch an active cards window if the cardLimit is set, or all the
// active cards if it's 0.
func (s *SQLStore) activeCardsQuery(builder sq.StatementBuilderType, selectStr string, cardLimit int) sq.SelectBuilder {
query := builder.
Select(selectStr).
From(s.tablePrefix + "blocks b").
Join(s.tablePrefix + "boards bd on b.board_id=bd.id").
Where(sq.Eq{
"b.delete_at": 0,
"b.type": model.TypeCard,
"bd.is_template": false,
})
if cardLimit != 0 {
query = query.
Limit(1).
Offset(uint64(cardLimit - 1))
}
return query
}
// getUsedCardsCount returns the amount of active cards in the server.
func (s *SQLStore) getUsedCardsCount(db sq.BaseRunner) (int, error) {
row := s.activeCardsQuery(s.getQueryBuilder(db), "count(b.id)", 0).
QueryRow()
var usedCards int
err := row.Scan(&usedCards)
if err != nil {
return 0, err
}
return usedCards, nil
}
// getCardLimitTimestamp returns the timestamp value from the
// system_settings table or zero if it doesn't exist.
func (s *SQLStore) getCardLimitTimestamp(db sq.BaseRunner) (int64, error) {
scanner := s.getQueryBuilder(db).
Select("value").
From(s.tablePrefix + "system_settings").
Where(sq.Eq{"id": store.CardLimitTimestampSystemKey}).
QueryRow()
var result string
err := scanner.Scan(&result)
if errors.Is(sql.ErrNoRows, err) {
return 0, nil
}
if err != nil {
return 0, err
}
cardLimitTimestamp, err := strconv.Atoi(result)
if err != nil {
return 0, ErrInvalidCardLimitValue
}
return int64(cardLimitTimestamp), nil
}
// updateCardLimitTimestamp updates the card limit value in the
// system_settings table with the timestamp of the nth last updated
// card, being nth the value of the cardLimit parameter. If cardLimit
// is zero, the timestamp will be set to zero.
func (s *SQLStore) updateCardLimitTimestamp(db sq.BaseRunner, cardLimit int) (int64, error) {
query := s.getQueryBuilder(db).
Insert(s.tablePrefix+"system_settings").
Columns("id", "value")
var value interface{} = 0
if cardLimit != 0 {
value = s.activeCardsQuery(sq.StatementBuilder, "b.update_at", cardLimit).
OrderBy("b.update_at DESC").
Prefix("COALESCE((").Suffix("), 0)")
}
query = query.Values(store.CardLimitTimestampSystemKey, value)
if s.dbType == model.MysqlDBType {
query = query.Suffix("ON DUPLICATE KEY UPDATE value = ?", value)
} else {
query = query.Suffix(
`ON CONFLICT (id)
DO UPDATE SET value = EXCLUDED.value`,
)
}
result, err := query.Exec()
if err != nil {
return 0, err
}
if _, err := result.RowsAffected(); err != nil {
return 0, err
}
return s.getCardLimitTimestamp(db)
}