package controllers import ( "context" "errors" "sync/atomic" "git.golem15.com/golem15/summercms/modules/cabana" "git.golem15.com/golem15/summercms/modules/pact" "git.golem15.com/jakub/sm-bm-plugin/models" "gorm.io/gorm" ) var ( _ pact.FormAfterCreate = materialsAdmin{} _ pact.FormAfterUpdate = materialsAdmin{} _ pact.FormAfterDelete = materialsAdmin{} ) // MaterialIndex keeps the materials search index current once a write // commits (classes.MaterialIndexer). Its calls never fail the write. type MaterialIndex interface { SyncAfterCommit(ctx context.Context, tx *gorm.DB, id uint) RemoveAfterCommit(ctx context.Context, tx *gorm.DB, id uint) } type materialIndexHolder struct{ ix MaterialIndex } var materialIndex atomic.Value // UseMaterialIndex installs the index the materials admin syncs after a // save or delete; nil turns the syncs off. Boot installs it, because the // generated controller value has no field to carry it. func UseMaterialIndex(ix MaterialIndex) { materialIndex.Store(materialIndexHolder{ix: ix}) } func installedMaterialIndex() MaterialIndex { h, _ := materialIndex.Load().(materialIndexHolder) return h.ix } // FormAfterCreate syncs the new material once the save transaction commits. func (materialsAdmin) FormAfterCreate(ctx context.Context, model any) error { return materialAfterCommit(ctx, model, false) } // FormAfterUpdate syncs the material once the save transaction commits. func (materialsAdmin) FormAfterUpdate(ctx context.Context, model any) error { return materialAfterCommit(ctx, model, false) } // FormAfterDelete removes the material's document once the delete commits. func (materialsAdmin) FormAfterDelete(ctx context.Context, model any) error { return materialAfterCommit(ctx, model, true) } // materialAfterCommit schedules the index work of an admin save on the save // transaction. Only a model that is not a material is an error: the index // never fails a save. func materialAfterCommit(ctx context.Context, model any, remove bool) error { m, ok := model.(*models.Material) if !ok || m == nil { return errors.New("materials admin: form model is not a material") } ix := installedMaterialIndex() if ix == nil || m.ID == 0 { return nil } tx, _ := cabana.TxFromContext(ctx) if remove { ix.RemoveAfterCommit(ctx, tx, m.ID) } else { ix.SyncAfterCommit(ctx, tx, m.ID) } return nil }