From 9dca7627b64937d2f168d2de1db6c205849539eb Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Wed, 22 Nov 2017 20:10:13 +0000 Subject: [PATCH] filter unconnected nodes after applying user-specified filters ...rather than before. That way, nodes which become unconnected during filtering are removed, which is what we want. ATM we are depending on some 'unconnected' filtering inside every filter, which is expensive and largely redundant. We should soon be able to remove that. downside: 'unconnected' filtering is no longer memoised. --- app/api_topologies.go | 12 ++++++------ render/filters.go | 30 ++++++++++++------------------ 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/app/api_topologies.go b/app/api_topologies.go index f27b93023..5aaff9d18 100644 --- a/app/api_topologies.go +++ b/app/api_topologies.go @@ -318,7 +318,7 @@ type APITopologyDesc struct { id string parent string renderer render.Renderer - filter func(render.Renderer) render.Renderer + filter render.Transformer Name string `json:"name"` Rank int `json:"rank"` @@ -447,7 +447,7 @@ func (r *Registry) Add(ts ...APITopologyDesc) { defer r.Unlock() for _, t := range ts { t.URL = apiTopologyURL + t.id - t.renderer = render.Memoise(t.filter(t.renderer)) + t.renderer = render.Memoise(t.renderer) if t.parent != "" { parent := r.items[t.parent] @@ -541,8 +541,8 @@ func (r *Registry) RendererForTopology(topologyID string, values url.Values, rpt topology = updateFilters(rpt, []APITopologyDesc{topology})[0] if len(values) == 0 { - // Do not apply filtering if no options where provided - return topology.renderer, render.Transformers(nil), nil + // if no options where provided, only apply base filter + return topology.renderer, topology.filter, nil } var filters []render.FilterFunc @@ -553,9 +553,9 @@ func (r *Registry) RendererForTopology(topologyID string, values url.Values, rpt } } if len(filters) > 0 { - return topology.renderer, render.ComposeFilterFuncs(filters...), nil + return topology.renderer, render.Transformers([]render.Transformer{render.ComposeFilterFuncs(filters...), topology.filter}), nil } - return topology.renderer, render.Transformers(nil), nil + return topology.renderer, topology.filter, nil } type reporterHandler func(context.Context, Reporter, http.ResponseWriter, *http.Request) diff --git a/render/filters.go b/render/filters.go index 7093c84bf..5ffe6dc3d 100644 --- a/render/filters.go +++ b/render/filters.go @@ -175,12 +175,17 @@ func ColorConnected(r Renderer) Renderer { } } -func filterUnconnected(input Nodes, onlyPseudo bool) Nodes { +type filterUnconnected struct { + onlyPseudo bool +} + +// Transform implements Transformer +func (f filterUnconnected) Transform(input Nodes) Nodes { connected := connected(input.Nodes) output := report.Nodes{} filtered := input.Filtered for id, node := range input.Nodes { - if _, ok := connected[id]; ok || (onlyPseudo && !IsPseudoTopology(node)) { + if _, ok := connected[id]; ok || (f.onlyPseudo && !IsPseudoTopology(node)) { output[id] = node } else { filtered++ @@ -200,23 +205,12 @@ func filterUnconnected(input Nodes, onlyPseudo bool) Nodes { return Nodes{Nodes: output, Filtered: filtered} } -// FilterUnconnected produces a renderer that filters unconnected nodes -// from the given renderer -func FilterUnconnected(r Renderer) Renderer { - return CustomRenderer{ - Renderer: r, - RenderFunc: func(input Nodes) Nodes { return filterUnconnected(input, false) }, - } -} +// FilterUnconnected is a transformer that filters unconnected nodes +var FilterUnconnected = filterUnconnected{onlyPseudo: false} -// FilterUnconnectedPseudo produces a renderer that filters -// unconnected pseudo nodes from the given renderer -func FilterUnconnectedPseudo(r Renderer) Renderer { - return CustomRenderer{ - Renderer: r, - RenderFunc: func(input Nodes) Nodes { return filterUnconnected(input, true) }, - } -} +// FilterUnconnectedPseudo is a transformer that filters unconnected +// pseudo nodes +var FilterUnconnectedPseudo = filterUnconnected{onlyPseudo: true} // Noop allows all nodes through func Noop(_ report.Node) bool { return true }