diff --git a/controllers/almanach.go b/controllers/almanach.go index c119a70..495fa2b 100644 --- a/controllers/almanach.go +++ b/controllers/almanach.go @@ -2,6 +2,7 @@ package controllers import ( "sort" + "sync" "github.com/Theodor-Springmann-Stiftung/musenalm/app" "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" @@ -17,6 +18,52 @@ const ( TEMPLATE_ALMANACH = "/almanach/" ) +// Simple in-memory cache for sorted entries +var ( + sortedEntriesCache struct { + sync.RWMutex + entries []*dbmodels.Entry + } +) + +// InvalidateSortedEntriesCache clears the cached sorted entries list +func InvalidateSortedEntriesCache() { + sortedEntriesCache.Lock() + defer sortedEntriesCache.Unlock() + sortedEntriesCache.entries = nil +} + +// getSortedEntries returns cached sorted entries or loads and caches them +func getSortedEntries(app core.App) ([]*dbmodels.Entry, error) { + // Try to read from cache first + sortedEntriesCache.RLock() + if sortedEntriesCache.entries != nil { + cached := sortedEntriesCache.entries + sortedEntriesCache.RUnlock() + return cached, nil + } + sortedEntriesCache.RUnlock() + + // Cache miss - load and sort + sortedEntriesCache.Lock() + defer sortedEntriesCache.Unlock() + + // Double-check after acquiring write lock + if sortedEntriesCache.entries != nil { + return sortedEntriesCache.entries, nil + } + + entries := []*dbmodels.Entry{} + if err := app.RecordQuery(dbmodels.ENTRIES_TABLE).All(&entries); err != nil { + return nil, err + } + + dbmodels.Sort_Entries_Title_Year(entries) + sortedEntriesCache.entries = entries + + return entries, nil +} + func init() { rp := &AlmanachPage{ StaticPage: pagemodels.StaticPage{ @@ -197,14 +244,14 @@ func NewAlmanachResult(app core.App, id string, params BeitraegeFilterParameters } func entryNeighborsByPreferredTitle(app core.App, entryID string) (*dbmodels.Entry, *dbmodels.Entry, error) { - entries := []*dbmodels.Entry{} - if err := app.RecordQuery(dbmodels.ENTRIES_TABLE).All(&entries); err != nil { + entries, err := getSortedEntries(app) + if err != nil { return nil, nil, err } if len(entries) == 0 { return nil, nil, nil } - dbmodels.Sort_Entries_Title_Year(entries) + for index, item := range entries { if item.Id != entryID { continue diff --git a/controllers/almanach_edit.go b/controllers/almanach_edit.go index e9e41d0..71459b8 100644 --- a/controllers/almanach_edit.go +++ b/controllers/almanach_edit.go @@ -190,6 +190,9 @@ func (p *AlmanachEditPage) POSTSave(engine *templating.Engine, app core.App) Han }) } + // Invalidate sorted entries cache since entry was modified + InvalidateSortedEntriesCache() + // Check if fields that affect contents changed contentsNeedUpdate := entry.PreferredTitle() != oldPreferredTitle || entry.Year() != oldYear || @@ -290,6 +293,9 @@ func (p *AlmanachEditPage) POSTDelete(engine *templating.Engine, app core.App) H }) } + // Invalidate sorted entries cache since entry was deleted + InvalidateSortedEntriesCache() + // Delete from FTS5 index asynchronously go func(appInstance core.App, entryID string) { if err := dbmodels.DeleteFTS5Entry(appInstance, entryID); err != nil { diff --git a/controllers/almanach_new.go b/controllers/almanach_new.go index 9da6c55..37490d0 100644 --- a/controllers/almanach_new.go +++ b/controllers/almanach_new.go @@ -146,6 +146,9 @@ func (p *AlmanachNewPage) POSTSave(engine *templating.Engine, app core.App) Hand }) } + // Invalidate sorted entries cache since new entry was created + InvalidateSortedEntriesCache() + // Update FTS5 index asynchronously go func(appInstance core.App, entryID string) { freshEntry, err := dbmodels.Entries_ID(appInstance, entryID)