Skip to content

Commit

Permalink
Merge pull request #242 from FleekHQ/develop
Browse files Browse the repository at this point in the history
Release to Master
  • Loading branch information
jsonsivar authored Nov 11, 2020
2 parents b469d73 + 8f94346 commit 9e093b9
Show file tree
Hide file tree
Showing 41 changed files with 2,855 additions and 1,307 deletions.
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ builds:

- id: space-win
# env:
# - CGO_ENABLED=0
# - CGO_ENABLED=1
ldflags:
- -s -w -X main.mongousr={{ .Env.MONGO_USR }}
- -X main.mongopw={{ .Env.MONGO_PW }}
Expand Down
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,12 @@ gen_rest_swagger:
&& statik -src=swagger/ui -f -dest=swagger -p=bin_ui

gen_all: proto_gen gen_rest gen_rest_swagger

## runs jaeger tracing server, should be used when trace is enabled on daemon
jaegar:
docker run \
--rm \
--name jaeger \
-p 6831:6831/udp \
-p 16686:16686 \
jaegertracing/all-in-one:latest
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ ensure everything is up to date **
NOTE: See here for instructions on Reverse Proxy:
https://github.com/grpc-ecosystem/grpc-gateway

### Debugging and Profiling
### Debugging, Profiling and Tracing

The following flags can be run with the binary to output profiling files for debugging.
Flags support a full path to a file.
Expand All @@ -187,6 +187,10 @@ server in localhost:6060. See docs how to interact with pprof server here: https
To disable debug mode add this flag to binary arguments
`-debug=false`

To enable trace in the daemon, pass `-trace` to the binary arguments. The daemon uses [jaegar](https://www.jaegertracing.io/)
for collecting trace information. Run `make jaegar` to quickly start a jaeger agent that collects the daemons trace information.
You can `http://localhost:16686/` to explore the web ui for traces collected.

### CI Secrets

Secrets are set by adding them in Github and then specifying them in `release.yml`. Secrets can be constant across environment/stages or be stage specific.
Expand Down
6 changes: 3 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"os/signal"
"syscall"

"github.com/FleekHQ/space-daemon/core/search/sqlite"
"github.com/FleekHQ/space-daemon/core/search/bleve"

"github.com/FleekHQ/space-daemon/core"
"github.com/FleekHQ/space-daemon/grpc"
Expand Down Expand Up @@ -122,8 +122,8 @@ func (a *App) Start(ctx context.Context) error {
hubAuth := hub.New(appStore, kc, a.cfg)

// setup files search engine
searchEngine := sqlite.NewSearchEngine(sqlite.WithDBPath(a.cfg.GetString(config.SpaceStorePath, "")))
a.Run("SqliteSearchEngine", searchEngine)
searchEngine := bleve.NewSearchEngine(bleve.WithDBPath(a.cfg.GetString(config.SpaceStorePath, "")))
a.Run("FilesSearchEngine", searchEngine)

// setup textile client
uc := textile.CreateUserClient(a.cfg.GetString(config.TextileHubTarget, ""))
Expand Down
13 changes: 13 additions & 0 deletions cmd/space-daemon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"runtime"
"runtime/pprof"

"github.com/FleekHQ/space-daemon/tracing"

"github.com/opentracing/opentracing-go"

"github.com/FleekHQ/space-daemon/log"

"github.com/FleekHQ/space-daemon/app"
Expand All @@ -22,6 +26,7 @@ var (
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
memprofile = flag.String("memprofile", "", "write memory profile to `file`")
debugMode = flag.Bool("debug", true, "run daemon with debug mode for profiling")
enableTracing = flag.Bool("trace", false, "run tracing on daemon rpc")
devMode = flag.Bool("dev", false, "run daemon in dev mode to use .env file")
ipfsaddr = flag.String("ipfsaddr", "/ip4/127.0.0.1/tcp/5001", "IPFS multiaddress to connect to (defaults to local node)")
ipfsnode = flag.Bool("ipfsnode", true, "run IPFS embedded into the daemon (defaults to true)")
Expand Down Expand Up @@ -85,6 +90,14 @@ func main() {
}()
}

// initialize tracing
if *enableTracing {
log.Debug("Enabling Tracing on the Daemon")
tracer, closer := tracing.MustInit("space-daemon")
defer closer.Close()
opentracing.SetGlobalTracer(tracer)
}

if *cpuprofile != "" {
cleanupCpuProfile := runCpuProfiler(*cpuprofile)
defer cleanupCpuProfile()
Expand Down
35 changes: 35 additions & 0 deletions core/search/bleve/analyzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package bleve

import (
"regexp"

"github.com/blevesearch/bleve/analysis"
"github.com/blevesearch/bleve/analysis/analyzer/standard"
filterregex "github.com/blevesearch/bleve/analysis/char/regexp"
"github.com/blevesearch/bleve/registry"
)

const CustomerAnalyzerName = "space_search_analyzer"

/// Customer Analyzer extends the standard analyzer by registering a regexp character filter
func CustomAnalyzerConstructor(config map[string]interface{}, cache *registry.Cache) (*analysis.Analyzer, error) {
rv, err := standard.AnalyzerConstructor(config, cache)
if err != nil {
return nil, err
}

// replace . with white space - helps to improve results on filenames
pattern, err := regexp.Compile("\\.")
if err != nil {
return nil, err
}
replacement := []byte(" ")
regexpCharFilter := filterregex.New(pattern, replacement)
rv.CharFilters = append(rv.CharFilters, regexpCharFilter)

return rv, nil
}

func init() {
registry.RegisterAnalyzer(CustomerAnalyzerName, CustomAnalyzerConstructor)
}
193 changes: 193 additions & 0 deletions core/search/bleve/bleve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package bleve

import (
"context"
"crypto/sha256"
"fmt"
"os/user"
"path/filepath"

"github.com/blevesearch/bleve/mapping"

"github.com/FleekHQ/space-daemon/log"

"github.com/FleekHQ/space-daemon/core/util"

"github.com/FleekHQ/space-daemon/core/search"
"github.com/blevesearch/bleve"
)

const DbFileName = "filesIndex.bleve"

type bleveSearchOption struct {
dbPath string
}

type Option func(o *bleveSearchOption)

// bleveFilesSearchEngine is a files search engine that is backed by bleve
type bleveFilesSearchEngine struct {
opts bleveSearchOption
idx bleve.Index
}

// Creates a new Bleve backed search engine for files and folders
func NewSearchEngine(opts ...Option) *bleveFilesSearchEngine {
usr, _ := user.Current()

searchOptions := bleveSearchOption{
dbPath: filepath.Join(usr.HomeDir, ".fleek-space"),
}

for _, opt := range opts {
opt(&searchOptions)
}

return &bleveFilesSearchEngine{
opts: searchOptions,
}
}

func (b *bleveFilesSearchEngine) Start() error {
path := filepath.Join(b.opts.dbPath, DbFileName)

var (
idx bleve.Index
err error
)

if util.DirEntryExists(path) {
log.Debug("Opening existing search index")
idx, err = bleve.Open(path)
} else {
log.Debug("Creating and opening new search index")
indexMapping, err := getSearchIndexMapping()

if err != nil {
return err
}

idx, err = bleve.New(path, indexMapping)
}

if err != nil {
return err
}

b.idx = idx

return nil
}

func getSearchIndexMapping() (*mapping.IndexMappingImpl, error) {
indexMapping := bleve.NewIndexMapping()
indexMapping.DefaultAnalyzer = CustomerAnalyzerName

filesMapping := bleve.NewDocumentMapping()

// index the following fields
nameFm := bleve.NewTextFieldMapping()
filesMapping.AddFieldMappingsAt("ItemName", nameFm)
extFm := bleve.NewTextFieldMapping()
filesMapping.AddFieldMappingsAt("ItemExtension", extFm)
pathFm := bleve.NewTextFieldMapping()
filesMapping.AddFieldMappingsAt("ItemPath", pathFm)

// ignore indexing the following fields of IndexRecord
idFm := bleve.NewTextFieldMapping()
idFm.Index = false
filesMapping.AddFieldMappingsAt("Id", idFm)

bucketFm := bleve.NewTextFieldMapping()
bucketFm.Index = false
filesMapping.AddFieldMappingsAt("BucketSlug", bucketFm)

dbIdFm := bleve.NewTextFieldMapping()
dbIdFm.Index = false
filesMapping.AddFieldMappingsAt("DbId", dbIdFm)

itemTypeFm := bleve.NewTextFieldMapping()
itemTypeFm.Index = false
filesMapping.AddFieldMappingsAt("ItemType", itemTypeFm)

indexMapping.AddDocumentMapping("files", filesMapping)
indexMapping.DefaultType = "files"

return indexMapping, nil
}

func (b *bleveFilesSearchEngine) InsertFileData(
ctx context.Context,
data *search.InsertIndexRecord,
) (*search.IndexRecord, error) {
indexId := generateIndexId(data.ItemName, data.ItemPath, data.BucketSlug, data.DbId)
record := search.IndexRecord{
Id: indexId,
ItemName: data.ItemName,
ItemExtension: data.ItemExtension,
ItemPath: data.ItemPath,
ItemType: data.ItemType,
BucketSlug: data.BucketSlug,
DbId: data.DbId,
}

if err := b.idx.Index(indexId, record); err != nil {
return nil, err
}

return &record, nil
}

func (b *bleveFilesSearchEngine) DeleteFileData(
ctx context.Context,
data *search.DeleteIndexRecord,
) error {
indexId := generateIndexId(data.ItemName, data.ItemPath, data.BucketSlug, data.DbId)
return b.idx.Delete(indexId)
}

func (b *bleveFilesSearchEngine) QueryFileData(
ctx context.Context,
query string,
limit int,
) ([]*search.IndexRecord, error) {
matchQuery := bleve.NewMatchQuery(query)
matchQuery.Fuzziness = 2

prefixQuery := bleve.NewPrefixQuery(query)
infixRegexQuery := bleve.NewRegexpQuery(fmt.Sprintf(".*%s.*", query)) // TODO: think of escaping invalid regex in query

searchQuery := bleve.NewDisjunctionQuery(matchQuery, prefixQuery, infixRegexQuery)
searchRequest := bleve.NewSearchRequest(searchQuery)
searchRequest.Size = limit
searchRequest.Fields = []string{"*"}

searchResults, err := b.idx.Search(searchRequest)
if err != nil {
return nil, err
}

records := make([]*search.IndexRecord, len(searchResults.Hits))
for i, hit := range searchResults.Hits {
records[i] = &search.IndexRecord{
Id: hit.Fields["Id"].(string),
ItemName: hit.Fields["ItemName"].(string),
ItemExtension: hit.Fields["ItemExtension"].(string),
ItemPath: hit.Fields["ItemPath"].(string),
ItemType: hit.Fields["ItemType"].(string),
BucketSlug: hit.Fields["BucketSlug"].(string),
DbId: hit.Fields["DbId"].(string),
}
}

return records, nil
}

func (b *bleveFilesSearchEngine) Shutdown() error {
return b.idx.Close()
}

func generateIndexId(name, path, bucketSlug, dbId string) string {
bytes := sha256.Sum256([]byte(name + path + bucketSlug + dbId))
return fmt.Sprintf("%x", bytes)
}
Loading

0 comments on commit 9e093b9

Please sign in to comment.