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 }
// 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 }
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 }
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 }
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) }
func (c config) Categories() []string { cats := fun.Keys(c.Scores).([]string) sort.Sort(sort.StringSlice(cats)) return cats }