A rebuild takes the transaction-scoped advisory lock golem15.sitemap.rebuild before it reads the settings and collects, and applies in the same transaction, so a second rebuild collects only after the first has committed. apply no longer writes the lastmod of a content row it did not create, so a lastmod RecordSaved moved meanwhile stays.
78 lines
2.1 KiB
Go
78 lines
2.1 KiB
Go
package sitemap_test
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"sync"
|
|
|
|
"git.golem15.com/golem15/sm-sitemap-plugin/contract"
|
|
"git.golem15.com/golem15/summercms/modules/backpack"
|
|
"git.golem15.com/golem15/summercms/modules/party"
|
|
)
|
|
|
|
// filterPluginID is a fake plugin that publishes a contract.Filter, as the
|
|
// SEO plugin does: it imports only the contract package.
|
|
const filterPluginID = "acme.filter"
|
|
|
|
// fakeFilter excludes addresses containing "noindex" (reason noindex) and
|
|
// puts addresses containing "promo" into the group offers. It records the
|
|
// batches it was asked; hook, when set, runs at the start of every Decide
|
|
// (a test blocks a rebuild there).
|
|
type fakeFilter struct {
|
|
mu sync.Mutex
|
|
batches [][]contract.Candidate
|
|
hook func()
|
|
}
|
|
|
|
// setHook sets the Decide hook for one test.
|
|
func (f *fakeFilter) setHook(t interface{ Cleanup(func()) }, fn func()) {
|
|
f.mu.Lock()
|
|
f.hook = fn
|
|
f.mu.Unlock()
|
|
t.Cleanup(func() {
|
|
f.mu.Lock()
|
|
f.hook = nil
|
|
f.mu.Unlock()
|
|
})
|
|
}
|
|
|
|
func (f *fakeFilter) Decide(_ context.Context, batch []contract.Candidate) ([]contract.Decision, error) {
|
|
f.mu.Lock()
|
|
f.batches = append(f.batches, append([]contract.Candidate(nil), batch...))
|
|
hook := f.hook
|
|
f.mu.Unlock()
|
|
if hook != nil {
|
|
hook()
|
|
}
|
|
out := make([]contract.Decision, len(batch))
|
|
for i, c := range batch {
|
|
switch {
|
|
case strings.Contains(c.URL, "noindex"):
|
|
out[i] = contract.Decision{Exclude: true, Reason: contract.ReasonNoindex}
|
|
case strings.Contains(c.URL, "promo"):
|
|
out[i] = contract.Decision{Group: "offers"}
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (f *fakeFilter) Groups(context.Context) ([]contract.Group, error) {
|
|
return []contract.Group{{Key: "offers", Titles: map[string]string{"en": "Offers", "pl": "Oferty"}}}, nil
|
|
}
|
|
|
|
var theFilter = &fakeFilter{}
|
|
|
|
// filterPlugin is acme.filter.
|
|
type filterPlugin struct{}
|
|
|
|
func (filterPlugin) ID() string { return filterPluginID }
|
|
func (filterPlugin) Requires() []string { return nil }
|
|
func (filterPlugin) Register(app *backpack.App) error {
|
|
return app.Publish[contract.Filter](theFilter)
|
|
}
|
|
func (filterPlugin) Boot(*backpack.App) error { return nil }
|
|
|
|
func init() {
|
|
party.Register(filterPlugin{})
|
|
}
|