Beispiel #1
0
func (provider *ConsulCatalog) healthyNodes(service string) (catalogUpdate, error) {
	health := provider.client.Health()
	opts := &api.QueryOptions{}
	data, _, err := health.Service(service, "", true, opts)
	if err != nil {
		log.WithError(err).Errorf("Failed to fetch details of " + service)
		return catalogUpdate{}, err
	}

	nodes := fun.Filter(func(node *api.ServiceEntry) bool {
		constraintTags := provider.getContraintTags(node.Service.Tags)
		ok, failingConstraint := provider.MatchConstraints(constraintTags)
		if ok == false && failingConstraint != nil {
			log.Debugf("Service %v pruned by '%v' constraint", service, failingConstraint.String())
		}
		return ok
	}, data).([]*api.ServiceEntry)

	//Merge tags of nodes matching constraints, in a single slice.
	tags := fun.Foldl(func(node *api.ServiceEntry, set []string) []string {
		return fun.Keys(fun.Union(
			fun.Set(set),
			fun.Set(node.Service.Tags),
		).(map[string]bool)).([]string)
	}, []string{}, nodes).([]string)

	return catalogUpdate{
		Service: &serviceUpdate{
			ServiceName: service,
			Attributes:  tags,
		},
		Nodes: nodes,
	}, nil
}
Beispiel #2
0
// Returns a list of tables that have indices which are modified by updating
// the lists given.
// Each table name will only appear once.
//
// If the name/atom table has more than 0 rows, then it will not be included
// in the list returned. This prevents rebuilding the indices on each update,
// which usually contains nominal additions to the name/atom table.
func tablesFromLists(db *imdb.DB, lists []string) (tables []string, err error) {
	var pre []string
	for _, name := range lists {
		tablesForList, ok := listTables[name]
		if !ok {
			return nil, ef("BUG: Could not find tables for list %s", name)
		}
		pre = append(pre, tablesForList...)
	}
	pre = fun.Keys(fun.Set(pre)).([]string)

	updatingEmpty := func(table string) bool {
		return rowCount(db, table) == 0 && fun.In(table, pre)
	}
	for _, table := range pre {
		switch table {
		case "atom", "name":
			// This is a little complex. Basically, we want to avoid rebuilding
			// indices for incremental updates. So we only let it happen when
			// we're updating the actor or movie lists from scratch.
			// (In general, this should apply to any table that is updated
			// concurrently with name/atom. We exclude tvshow and episode since
			// they are only updated when movie is updated.)
			if updatingEmpty("actor") || updatingEmpty("movie") {
				tables = append(tables, table)
			}
		default:
			tables = append(tables, table)
		}
	}
	return
}
Beispiel #3
0
func cmd_short(c *command) bool {
	c.assertLeastNArg(1)
	db := openDb(c.dbinfo())
	defer closeDb(db)

	attrs := fun.Keys(attrCommands).([]string)
	sort.Sort(sort.StringSlice(attrs))

	ent, ok := c.oneEntity(db)
	if !ok {
		return false
	}

	tplName := sf("short_%s", ent.Type().String())
	tpl.SetDB(db)
	c.tplExec(c.tpl(tplName), tpl.Args{E: ent, A: nil})
	return true
}
Beispiel #4
0
func cmd_full(c *command) bool {
	c.assertLeastNArg(1)
	db := openDb(c.dbinfo())
	defer closeDb(db)

	attrs := fun.Keys(attrCommands).([]string)
	sort.Sort(sort.StringSlice(attrs))

	ent, ok := c.oneEntity(db)
	if !ok {
		return false
	}

	for _, attr := range attrs {
		if !c.showAttr(db, ent, attr) {
			return false
		}
	}
	return true
}
Beispiel #5
0
func init() {
	less := func(f1, f2 string) bool { return f1 < f2 }
	fields := fun.QuickSort(less, fun.Keys(qualifiedColumns)).([]string)
	sortFields := strings.Join(fields, ", ")
	genres := strings.Join(imdb.EnumGenres, ", ")
	mpaas := strings.Join(imdb.EnumMPAA, ", ")

	commands = []command{
		{
			"movie", nil, false,
			"Restricts results to only include movies. Note that this may " +
				"be combined with other entity types to form a disjunction.",
			func(s *Searcher, v string) error {
				s.Entity(imdb.EntityMovie)
				return nil
			},
		},
		{
			"tvshow", nil, false,
			"Restricts results to only include TV shows. Note that this may " +
				"be combined with other entity types to form a disjunction.",
			func(s *Searcher, v string) error {
				s.Entity(imdb.EntityTvshow)
				return nil
			},
		},
		{
			"episode", nil, false,
			"Restricts results to only include episodes. Note that this may " +
				"be combined with other entity types to form a disjunction.",
			func(s *Searcher, v string) error {
				s.Entity(imdb.EntityEpisode)
				return nil
			},
		},
		{
			"actor", nil, false,
			"Restricts results to only include actors. Note that this may " +
				"be combined with other entity types to form a disjunction.",
			func(s *Searcher, v string) error {
				s.Entity(imdb.EntityActor)
				return nil
			},
		},
		{
			"genre", nil, true,
			"Restricts results to only include entities matching the genre " +
				"given. Multiple genres will be combined disjunctively. " +
				"Available genres: " + genres,
			func(s *Searcher, v string) error {
				s.Genre(v)
				return nil
			},
		},
		{
			"mpaa", nil, true,
			"Restricts results to only include entities with the MPAA rating " +
				"given. Multiple MPAA ratings will be combined " +
				"disjunctively. Available MPAA ratings: " + mpaas,
			func(s *Searcher, v string) error {
				s.MPAA(v)
				return nil
			},
		},
		{
			"credits", nil, true,
			"A sub-search for media entities that restricts results to " +
				"only actors media item returned from this sub-search.",
			func(s *Searcher, v string) error {
				return addSub(s, "credits", v, s.Credits)
			},
		},
		{
			"cast", nil, true,
			"A sub-search for cast entities that restricts results to " +
				"only media entities in which the cast member appeared.",
			func(s *Searcher, v string) error {
				return addSub(s, "cast", v, s.Cast)
			},
		},
		{
			"show", nil, true,
			"A sub-search for TV shows that restricts results to " +
				"only episodes in the TV show.",
			func(s *Searcher, v string) error {
				return addSub(s, "show", v, s.Tvshow)
			},
		},
		{
			"debug", nil, false,
			"When enabled, the SQL queries used in the search will be logged " +
				"to stderr.",
			func(s *Searcher, v string) error {
				s.debug = true
				return nil
			},
		},
		{
			"id", []string{"atom"}, true,
			"Precisely selects a single identity with the atom identifier " +
				"given. e.g., {id:123} returns the entity with id 123." +
				"Note that one SHOULD NOT rely on any specific atom " +
				"identifier to always correspond to a specific entity, since " +
				"identifiers can (sadly) change when updating your database.",
			func(s *Searcher, v string) error {
				n, err := strconv.Atoi(v)
				if err != nil {
					return ef("Invalid integer '%s' for atom id: %s", v, err)
				}
				s.Atom(imdb.Atom(n))
				return nil
			},
		},
		{
			"years", []string{"year"}, true,
			"Only show search results for the year or years specified. " +
				"e.g., {1990-1999} only shows movies in the 90s.",
			func(s *Searcher, v string) error {
				return addRange(v, s.Years)
			},
		},
		{
			"rank", nil, true,
			"Only show search results with the rank or ranks specified. " +
				"e.g., {70-} only shows entities with a rank of 70 or " +
				"better. Ranks are on a scale of 0 to 100, where 100 is the " +
				"best.",
			func(s *Searcher, v string) error {
				return addRange(v, s.Ranks)
			},
		},
		{
			"votes", nil, true,
			"Only show search results with ranks that have the vote count " +
				"specified. e.g., {10000-} only shows entities with a rank " +
				"that has 10,000 or more votes.",
			func(s *Searcher, v string) error {
				return addRange(v, s.Votes)
			},
		},
		{
			"billing", []string{"billed"}, true,
			"Only show search results with credits with the billing position " +
				"specified. e.g., {1-5} only shows movies where the actor " +
				"was in the top 5 billing order (or only shows actors of a " +
				"movie in the top 5 billing positions).",
			func(s *Searcher, v string) error {
				return addRange(v, s.Billed)
			},
		},
		{
			"seasons", []string{"s"}, true,
			"Only show search results for the season or seasons specified. " +
				"e.g., {seasons:1} only shows episodes from the first season " +
				"of a TV show. Note that this only filters episodes---movies " +
				"and TV shows are still returned otherwise.",
			func(s *Searcher, v string) error {
				return addRange(v, s.Seasons)
			},
		},
		{
			"episodes", []string{"e"}, true,
			"Only show search results for the season or seasons specified. " +
				"e.g., {episodes:1-5} only shows the first five episodes of " +
				"a of a season. Note that this only filters " +
				"episodes---movies and TV shows are still returned otherwise.",
			func(s *Searcher, v string) error {
				return addRange(v, s.Episodes)
			},
		},
		{
			"notv", nil, false,
			"Removes 'made for TV' movies from the search results.",
			func(s *Searcher, v string) error {
				s.NoTvMovies()
				return nil
			},
		},
		{
			"novideo", nil, false,
			"Removes 'made for video' movies from the search results.",
			func(s *Searcher, v string) error {
				s.NoVideoMovies()
				return nil
			},
		},
		{
			"similar", nil, true,
			"Sets the threshold at which to return results from a fuzzy text " +
				"search. Results scoring below this threshold are omitted. " +
				"Note that setting this value too low can dramatically " +
				"increase the search time.",
			func(s *Searcher, v string) error {
				n, err := strconv.ParseFloat(v, 64)
				if err != nil {
					return ef("Invalid float '%s' for similar: %s", v, err)
				}
				s.SimilarThreshold(n)
				return nil
			},
		},
		{
			"limit", nil, true,
			"Specifies a limit on the total number of search results returned.",
			func(s *Searcher, v string) error {
				n, err := strconv.Atoi(v)
				if err != nil {
					return ef("Invalid integer '%s' for limit: %s", v, err)
				}
				s.Limit(int(n))
				return nil
			},
		},
		{
			"sort", nil, true,
			"Sorts the search results according to the field given. It may " +
				"be specified multiple times for more specific sorting. Note " +
				"that this doesn't really work with fuzzy searching, since " +
				"results are always sorted by their similarity with the " +
				"query in a fuzzy search. e.g., {sort:episode desc} sorts " +
				"episode in descending (biggest to smallest) order. " +
				"Valid sort fields: " + sortFields + ".",
			func(s *Searcher, v string) error {
				fields := strings.Fields(v)
				if len(fields) != 2 {
					return ef("Invalid sort format "+
						"(must have field and order): '%s'", v)
				}
				s.Sort(fields[0], fields[1])
				return nil
			},
		},
	}

	// Add synonyms of commands to the map of commands.
	for _, cmd := range commands {
		allCommands[cmd.name] = cmd
		for _, synonym := range cmd.synonyms {
			allCommands[synonym] = cmd
		}
		Commands = append(Commands, Command{
			Name:        cmd.name,
			Synonyms:    cmd.synonyms,
			Description: cmd.description,
		})
	}
	fun.Sort(func(c1, c2 Command) bool { return c1.Name < c2.Name }, Commands)
}
Beispiel #6
0
func (c config) Categories() []string {
	cats := fun.Keys(c.Scores).([]string)
	sort.Sort(sort.StringSlice(cats))
	return cats
}