Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions changelog/unreleased/enhancement-search-optimize-command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Enhancement: Add `ocis search optimize` command

Added a new CLI command `ocis search optimize` that compacts the search
index by merging segments without re-indexing content. This is useful for
existing instances where the index has accumulated many small segments
from incremental writes, without needing to run a full re-index.

https://github.com/owncloud/ocis/pull/12136

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions protogen/gen/ocis/services/search/v0/search.pb.micro.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions protogen/gen/ocis/services/search/v0/search.pb.web.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions protogen/proto/ocis/services/search/v0/search.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "protoc-gen-openapiv2/options/annotations.proto";
import "google/api/field_behavior.proto";
import "google/api/annotations.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/empty.proto";

option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
Expand Down Expand Up @@ -47,6 +48,12 @@ service SearchProvider {
body: "*"
};
}
rpc OptimizeIndex(google.protobuf.Empty) returns (google.protobuf.Empty) {
option (google.api.http) = {
post: "/api/v0/search/optimize-index",
body: "*"
};
}
}

service IndexProvider {
Expand Down
54 changes: 54 additions & 0 deletions services/search/pkg/command/optimize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package command

import (
"context"
"fmt"
"time"

"github.com/urfave/cli/v2"
"go-micro.dev/v4/client"
"google.golang.org/protobuf/types/known/emptypb"

"github.com/owncloud/ocis/v2/ocis-pkg/config/configlog"
"github.com/owncloud/ocis/v2/ocis-pkg/service/grpc"
"github.com/owncloud/ocis/v2/ocis-pkg/tracing"
searchsvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/search/v0"
"github.com/owncloud/ocis/v2/services/search/pkg/config"
"github.com/owncloud/ocis/v2/services/search/pkg/config/parser"
)

// Optimize is the entrypoint for the optimize command.
func Optimize(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "optimize",
Usage: "compact the search index by merging segments, without re-indexing content",
Category: "index management",
Before: func(_ *cli.Context) error {
return configlog.ReturnFatal(parser.ParseConfig(cfg))
},
Action: func(_ *cli.Context) error {
traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name)
if err != nil {
return err
}
grpcClient, err := grpc.NewClient(
append(grpc.GetClientOptions(cfg.GRPCClientTLS),
grpc.WithTraceProvider(traceProvider),
)...,
)
if err != nil {
return err
}

c := searchsvc.NewSearchProviderService("com.owncloud.api.search", grpcClient)
_, err = c.OptimizeIndex(context.Background(), &emptypb.Empty{},
func(opts *client.CallOptions) { opts.RequestTimeout = 10 * time.Minute })
if err != nil {
fmt.Println("failed to optimize index: " + err.Error())
return err
}
fmt.Println("index optimization complete")
return nil
},
}
}
1 change: 1 addition & 0 deletions services/search/pkg/command/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func GetCommands(cfg *config.Config) cli.Commands {

// interaction with this service
Index(cfg),
Optimize(cfg),

// infos about this service
Health(cfg),
Expand Down
46 changes: 46 additions & 0 deletions services/search/pkg/search/mocks/searcher.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions services/search/pkg/search/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ var (
type Searcher interface {
Search(ctx context.Context, req *searchsvc.SearchRequest) (*searchsvc.SearchResponse, error)
IndexSpace(rID *provider.StorageSpaceId) error
OptimizeIndex(ctx context.Context) error
TrashItem(rID *provider.ResourceId)
UpsertItem(ref *provider.Reference)
UpdateTags(ref *provider.Reference)
Expand Down Expand Up @@ -501,6 +502,22 @@ func (s *Service) IndexSpace(spaceID *provider.StorageSpaceId) error {
return nil
}

// OptimizeIndex compacts the search index segments without re-indexing content.
func (s *Service) OptimizeIndex(ctx context.Context) error {
opt, ok := s.engine.(engine.Optimizer)
if !ok {
return fmt.Errorf("search engine does not support optimization")
}

logDocCount(s.engine, s.logger)
s.logger.Info().Msg("optimizing search index")
if err := opt.Optimize(ctx); err != nil {
return fmt.Errorf("index optimization failed: %w", err)
}
s.logger.Info().Msg("index optimization complete")
return nil
}

// TrashItem marks the item as deleted.
func (s *Service) TrashItem(rID *provider.ResourceId) {
err := s.engine.Delete(storagespace.FormatResourceID(rID))
Expand Down
Loading