eintopf.info@v0.13.16/service/indexo/indexo.go (about)

     1  // Copyright (C) 2022 The Eintopf authors
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  
    16  // Package indexo provides an operator with an index and a delete operation,
    17  // that operates on a search index
    18  package indexo
    19  
    20  import (
    21  	"context"
    22  
    23  	"eintopf.info/service/event"
    24  	"eintopf.info/service/group"
    25  	"eintopf.info/service/oqueue"
    26  	"eintopf.info/service/place"
    27  	"eintopf.info/service/search"
    28  )
    29  
    30  // Service defines an operation indexer service.
    31  type Service interface {
    32  	// Reindex takes all models, that are searchable and indexes them into the
    33  	// search index.
    34  	Reindex(ctx context.Context) error
    35  }
    36  
    37  type service struct {
    38  	queue oqueue.Service
    39  
    40  	searchService search.Service
    41  	eventService  event.Storer
    42  	groupService  group.Service
    43  	placeService  place.Service
    44  }
    45  
    46  // NewService returns a new index operator service.
    47  func NewService(
    48  	queue oqueue.Service,
    49  	searchService search.Service,
    50  	eventService event.Storer,
    51  	groupService group.Service,
    52  	placeService place.Service,
    53  ) Service {
    54  	s := &service{
    55  		queue:         queue,
    56  		searchService: searchService,
    57  		eventService:  eventService,
    58  		groupService:  groupService,
    59  		placeService:  placeService,
    60  	}
    61  
    62  	queue.AddSubscriber(s.consumeOperation, 1)
    63  
    64  	return s
    65  }
    66  
    67  // consumeOperation consumes an event, group and place operations of the type
    68  // create, update and delete. Depending on wether the model is searchable, it
    69  // performs an index or a delete operation on the search index.
    70  func (s *service) consumeOperation(op oqueue.Operation) error {
    71  	switch op := op.(type) {
    72  	case group.CreateOperation:
    73  		if op.Group.Indexable() {
    74  			return s.indexGroup(op.Group)
    75  		}
    76  	case group.UpdateOperation:
    77  		if op.Group.Indexable() {
    78  			return s.indexGroup(op.Group)
    79  		} else {
    80  			return s.searchService.Delete("group", op.Group.ID)
    81  		}
    82  	case group.DeleteOperation:
    83  		return s.searchService.Delete("group", op.ID)
    84  	case place.CreateOperation:
    85  		if op.Place.Indexable() {
    86  			return s.indexPlace(op.Place)
    87  		}
    88  	case place.UpdateOperation:
    89  		if op.Place.Indexable() {
    90  			return s.indexPlace(op.Place)
    91  		} else {
    92  			return s.searchService.Delete("place", op.Place.ID)
    93  		}
    94  	case place.DeleteOperation:
    95  		return s.searchService.Delete("place", op.ID)
    96  	}
    97  	return nil
    98  }
    99  
   100  func (s *service) Reindex(ctx context.Context) error {
   101  	groups, _, err := s.groupService.Find(ctx, nil)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	docs := []search.Indexable{}
   106  	for _, group := range groups {
   107  		if group.Indexable() {
   108  			docs = append(docs, groupDocumentFromGroup(group))
   109  		}
   110  	}
   111  
   112  	places, _, err := s.placeService.Find(ctx, nil)
   113  	if err != nil {
   114  		return err
   115  	}
   116  	for _, place := range places {
   117  		if place.Indexable() {
   118  			docs = append(docs, placeDocumentFromPlace(place))
   119  		}
   120  	}
   121  	return s.searchService.Index(docs...)
   122  }