Fix: movie cache and movie db consistency

pull/21/head
zijiren233 2 years ago
parent 01ca838a77
commit 50633226f2

@ -25,7 +25,7 @@ func InitRoom(ctx context.Context) error {
return err
}
for _, movie := range m {
err = r.InitMovie(&movie)
err = r.InitMovie(movie)
if err != nil {
log.Errorf("init movie error: %v", err)
return err

@ -9,40 +9,35 @@ func CreateMovie(movie *model.Movie) error {
return db.Create(movie).Error
}
func GetAllMoviesByRoomID(roomID uint) ([]model.Movie, error) {
movies := []model.Movie{}
func GetAllMoviesByRoomID(roomID uint) ([]*model.Movie, error) {
movies := []*model.Movie{}
err := db.Where("room_id = ?", roomID).Order("position ASC").Find(&movies).Error
return movies, err
}
func DeleteMovieByID(roomID, id uint) error {
return db.Where("room_id = ? AND id = ?", roomID, id).Delete(&model.Movie{}).Error
return db.Unscoped().Where("room_id = ? AND id = ?", roomID, id).Delete(&model.Movie{}).Error
}
// TODO: delete error
func LoadAndDeleteMovieByID(roomID, id uint, columns ...clause.Column) (*model.Movie, error) {
movie := &model.Movie{}
err := db.Clauses(clause.Returning{Columns: columns}).Where("room_id = ? AND id = ?", roomID, id).Delete(movie).Error
err := db.Unscoped().Clauses(clause.Returning{Columns: columns}).Where("room_id = ? AND id = ?", roomID, id).Delete(movie).Error
return movie, err
}
func DeleteMoviesByRoomID(roomID uint) error {
return db.Where("room_id = ?", roomID).Delete(&model.Movie{}).Error
return db.Unscoped().Where("room_id = ?", roomID).Delete(&model.Movie{}).Error
}
func LoadAndDeleteMoviesByRoomID(roomID uint, columns ...clause.Column) ([]model.Movie, error) {
movies := []model.Movie{}
err := db.Clauses(clause.Returning{Columns: columns}).Where("room_id = ?", roomID).Delete(&movies).Error
func LoadAndDeleteMoviesByRoomID(roomID uint, columns ...clause.Column) ([]*model.Movie, error) {
movies := []*model.Movie{}
err := db.Unscoped().Clauses(clause.Returning{Columns: columns}).Where("room_id = ?", roomID).Delete(&movies).Error
return movies, err
}
func UpdateMovie(movie model.Movie) error {
return db.Model(&model.Movie{}).Where("room_id = ? AND id = ?", movie.RoomID, movie.ID).Updates(movie).Error
}
func LoadAndUpdateMovie(movie model.Movie, columns ...clause.Column) (*model.Movie, error) {
err := db.Model(&model.Movie{}).Clauses(clause.Returning{Columns: columns}).Where("room_id = ? AND id = ?", movie.RoomID, movie.ID).Updates(&movie).Error
return &movie, err
func UpdateMovie(movie *model.Movie, columns ...clause.Column) error {
return db.Model(movie).Clauses(clause.Returning{Columns: columns}).Where("room_id = ? AND id = ?", movie.RoomID, movie.ID).Updates(movie).Error
}
func SwapMoviePositions(roomID uint, movie1ID uint, movie2ID uint) (err error) {

@ -1,13 +1,11 @@
package model
import (
"gorm.io/gorm"
)
import "gorm.io/gorm"
type Movie struct {
gorm.Model
Position uint `gorm:"not null" json:"-"`
RoomID uint `gorm:"not null;index" json:"roomId"`
Position uint `gorm:"not null"`
RoomID uint `gorm:"not null;index"`
MovieInfo `gorm:"embedded"`
}

@ -7,61 +7,62 @@ import (
"github.com/bluele/gcache"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
"github.com/zijiren233/gencontainer/dllist"
)
var movieCache = gcache.New(2048).
LRU().
Build()
func GetAllMoviesByRoomID(roomID uint) ([]model.Movie, error) {
func GetAllMoviesByRoomID(roomID uint) (*dllist.Dllist[*model.Movie], error) {
i, err := movieCache.Get(roomID)
if err == nil {
return i.([]model.Movie), nil
return i.(*dllist.Dllist[*model.Movie]), nil
}
m, err := db.GetAllMoviesByRoomID(roomID)
if err != nil {
return nil, err
}
return m, movieCache.SetWithExpire(roomID, m, time.Hour)
d := dllist.New[*model.Movie]()
for i := range m {
d.PushBack(m[i])
}
return d, movieCache.SetWithExpire(roomID, d, time.Hour)
}
func GetMoviesByRoomIDWithPage(roomID uint, page, pageSize int) ([]model.Movie, error) {
i, err := movieCache.Get(roomID)
func GetMoviesByRoomIDWithPage(roomID uint, page, max int) ([]*model.Movie, error) {
ms, err := GetAllMoviesByRoomID(roomID)
if err != nil {
return nil, err
}
ms := i.([]model.Movie)
if page < 1 {
page = 1
}
if pageSize < 1 {
pageSize = 1
start := (page - 1) * max
if start >= ms.Len() {
start = ms.Len()
}
start := (page - 1) * pageSize
end := page * pageSize
if start > len(ms) {
start = len(ms)
end := start + max
if end > ms.Len() {
end = ms.Len()
}
if end > len(ms) {
end = len(ms)
var m []*model.Movie = make([]*model.Movie, 0, end-start)
idx := 0
for i := ms.Front(); i != nil; i = i.Next() {
if idx >= start && idx < end {
m = append(m, i.Value)
}
idx++
}
return ms[start:end], nil
return m, nil
}
func GetMovieByID(roomID, id uint) (*model.Movie, error) {
var m []model.Movie
i, err := movieCache.Get(roomID)
if err == nil {
m = i.([]model.Movie)
} else {
m, err = GetAllMoviesByRoomID(roomID)
if err != nil {
return nil, err
}
ms, err := GetAllMoviesByRoomID(roomID)
if err != nil {
return nil, err
}
for _, v := range m {
if v.ID == id {
return &v, nil
for i := ms.Front(); i != nil; i = i.Next() {
if i.Value.ID == id {
return i.Value, nil
}
}
return nil, errors.New("movie not found")
@ -69,126 +70,102 @@ func GetMovieByID(roomID, id uint) (*model.Movie, error) {
func GetMoviesCountByRoomID(roomID uint) (int, error) {
ms, err := GetAllMoviesByRoomID(roomID)
return len(ms), err
if err != nil {
return 0, err
}
return ms.Len(), nil
}
func DeleteMovieByID(roomID, id uint) error {
err := db.DeleteMovieByID(roomID, id)
if err != nil {
return err
}
i, err := movieCache.Get(roomID)
ms, err := GetAllMoviesByRoomID(roomID)
if err != nil {
return err
}
ms := i.([]model.Movie)
for i, v := range ms {
if v.ID == id {
ms = append(ms[:i], ms[i+1:]...)
break
for i := ms.Front(); i != nil; i = i.Next() {
if i.Value.ID == id {
ms.Remove(i)
return db.DeleteMovieByID(roomID, id)
}
}
return nil
return errors.New("movie not found")
}
func UpdateMovie(movie model.Movie) error {
m, err := db.LoadAndUpdateMovie(movie)
func UpdateMovie(movie *model.Movie) error {
err := db.UpdateMovie(movie)
if err != nil {
return err
}
i, err := movieCache.Get(movie.RoomID)
m, err := GetMovieByID(movie.RoomID, movie.ID)
if err != nil {
return err
}
ms := i.([]model.Movie)
for i, v := range ms {
if v.ID == movie.ID {
ms[i] = *m
break
}
}
*m = *movie
return nil
}
func DeleteMoviesByRoomID(roomID uint) error {
err := db.DeleteMoviesByRoomID(roomID)
if err != nil {
return err
}
movieCache.Remove(roomID)
return nil
return db.DeleteMoviesByRoomID(roomID)
}
func LoadAndDeleteMovieByID(roomID, id uint) (*model.Movie, error) {
m, err := db.LoadAndDeleteMovieByID(roomID, id)
if err != nil {
return nil, err
}
i, err := movieCache.Get(roomID)
ms, err := GetAllMoviesByRoomID(roomID)
if err != nil {
return nil, err
}
ms := i.([]model.Movie)
for i, v := range ms {
if v.ID == id {
ms = append(ms[:i], ms[i+1:]...)
break
for i := ms.Front(); i != nil; i = i.Next() {
if i.Value.ID == id {
ms.Remove(i)
return db.LoadAndDeleteMovieByID(roomID, id)
}
}
return m, nil
return nil, errors.New("movie not found")
}
// data race
func CreateMovie(movie *model.Movie) error {
err := db.CreateMovie(movie)
ms, err := GetAllMoviesByRoomID(movie.RoomID)
if err != nil {
return err
}
i, err := movieCache.Get(movie.RoomID)
err = db.CreateMovie(movie)
if err != nil {
movieCache.Set(movie.RoomID, []model.Movie{*movie})
return nil
return err
}
ms := i.([]model.Movie)
ms = append(ms, *movie)
movieCache.Set(movie.RoomID, ms)
ms.PushBack(movie)
return nil
}
func GetMovieWithPullKey(roomID uint, pullKey string) (*model.Movie, error) {
i, err := movieCache.Get(roomID)
ms, err := GetAllMoviesByRoomID(roomID)
if err != nil {
return nil, err
}
ms := i.([]model.Movie)
for _, v := range ms {
if v.PullKey == pullKey {
return &v, nil
for i := ms.Front(); i != nil; i = i.Next() {
if i.Value.PullKey == pullKey {
return i.Value, nil
}
}
return nil, errors.New("movie not found")
}
func SwapMoviePositions(roomID uint, movie1ID uint, movie2ID uint) error {
err := db.SwapMoviePositions(roomID, movie1ID, movie2ID)
if err != nil {
return err
}
i, err := movieCache.Get(roomID)
ms, err := GetAllMoviesByRoomID(roomID)
if err != nil {
return err
}
ms := i.([]model.Movie)
movie1I, movie2I := 0, 0
for i, v := range ms {
if v.ID == movie1ID {
movie1I = i
var m1, m2 *model.Movie
for i := ms.Front(); i != nil; i = i.Next() {
if i.Value.ID == movie1ID {
m1 = i.Value
}
if v.ID == movie2ID {
movie2I = i
if i.Value.ID == movie2ID {
m2 = i.Value
}
}
ms[movie1I].Position, ms[movie2I].Position = ms[movie2I].Position, ms[movie1I].Position
ms[movie1I], ms[movie2I] = ms[movie2I], ms[movie1I]
return nil
if m1 == nil || m2 == nil {
return errors.New("movie not found")
}
m1.Position, m2.Position = m2.Position, m1.Position
return db.SwapMoviePositions(roomID, movie1ID, movie2ID)
}

@ -77,14 +77,15 @@ func (r *Room) UpdateMovie(movieId uint, movie model.BaseMovieInfo) error {
return err
}
switch {
case (m.RtmpSource && !movie.RtmpSource) || (m.Live && m.Proxy && !movie.Proxy):
case ((m.Live && m.Proxy) || (m.Live && m.RtmpSource)) && (!movie.Live && !movie.Proxy && !movie.RtmpSource):
r.lazyInit()
r.rtmpa.DelChannel(m.PullKey)
m.PullKey = ""
case m.Proxy && !movie.Proxy:
m.PullKey = ""
}
return UpdateMovie(*m)
m.MovieInfo.BaseMovieInfo = movie
return db.UpdateMovie(m)
}
func (r *Room) InitMovie(movie *model.Movie) error {
@ -194,6 +195,7 @@ func (r *Room) InitMovie(movie *model.Movie) error {
func (r *Room) AddMovie(m model.MovieInfo) error {
movie := &model.Movie{
RoomID: r.ID,
Position: uint(time.Now().UnixMilli()),
MovieInfo: m,
}
@ -254,11 +256,19 @@ func (r *Room) GetMoviesCount() (int, error) {
return GetMoviesCountByRoomID(r.ID)
}
func (r *Room) GetAllMoviesByRoomID() ([]model.Movie, error) {
return GetAllMoviesByRoomID(r.ID)
func (r *Room) GetAllMoviesByRoomID() ([]*model.Movie, error) {
ms, err := GetAllMoviesByRoomID(r.ID)
if err != nil {
return nil, err
}
var m []*model.Movie = make([]*model.Movie, ms.Len())
for i := ms.Front(); i != nil; i = i.Next() {
m[i.Value.Position-1] = i.Value
}
return m, nil
}
func (r *Room) GetMoviesByRoomIDWithPage(page, pageSize int) ([]model.Movie, error) {
func (r *Room) GetMoviesByRoomIDWithPage(page, pageSize int) ([]*model.Movie, error) {
return GetMoviesByRoomIDWithPage(r.ID, page, pageSize)
}

Loading…
Cancel
Save