feat: search materials through beachcomber

- Material is a beachcomber Searchable (index jz_bm_materials) in the
  hand-written models/material_search.go; jz.bm requires summercms v0.6.4
- classes.MaterialIndexer asks Typesense for up to 250 candidates with
  body highlights; the app-wide Gate is on only for jz.bm-marked contexts
- GET /_bm/api/v1/materials takes q: candidates are re-gated, counted and
  paged in SQL in rank order, each row with at most one plain snippet
- search failure answers 503 Search is unavailable.; without q the list
  is unchanged
This commit is contained in:
Jakub Zych
2026-11-08 19:45:46 +01:00
parent f7c400756f
commit 4ffce6e6ac
18 changed files with 1315 additions and 36 deletions

View File

@@ -17,6 +17,7 @@ import (
"git.golem15.com/golem15/summercms/modules/cooler"
"git.golem15.com/golem15/summercms/modules/phrasebook"
"git.golem15.com/golem15/summercms/modules/wire"
"git.golem15.com/jakub/sm-bm-plugin/classes"
"gocloud.dev/blob"
"gorm.io/gorm"
)
@@ -73,6 +74,10 @@ type Handlers struct {
// Cache returns the application cache that holds the issued upload
// tickets until they are used, or nil while none is available.
Cache func() cooler.Cache
// MaterialIndex searches the materials index and keeps it current. Nil
// means a search (q) answers 503 and the syncs after a write are
// skipped.
MaterialIndex *classes.MaterialIndexer
}
func (h *Handlers) now() time.Time {