Example #1
0
func handleWebsocket(
	w http.ResponseWriter,
	r *http.Request,
	rep Reporter,
	renderer render.Renderer,
	loop time.Duration,
) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		// log.Println("Upgrade:", err)
		return
	}
	defer conn.Close()

	quit := make(chan struct{})
	go func(c *websocket.Conn) {
		for { // just discard everything the browser sends
			if _, _, err := c.NextReader(); err != nil {
				close(quit)
				break
			}
		}
	}(conn)

	var (
		previousTopo render.RenderableNodes
		tick         = time.Tick(loop)
		wait         = make(chan struct{}, 1)
	)
	rep.WaitOn(wait)
	defer rep.UnWait(wait)

	for {
		newTopo := renderer.Render(rep.Report()).Prune()
		diff := render.TopoDiff(previousTopo, newTopo)
		previousTopo = newTopo

		if err := conn.SetWriteDeadline(time.Now().Add(websocketTimeout)); err != nil {
			return
		}
		if err := conn.WriteJSON(diff); err != nil {
			return
		}

		select {
		case <-wait:
		case <-tick:
		case <-quit:
			return
		}
	}
}
Example #2
0
func TestTopoDiff(t *testing.T) {
	nodea := render.RenderableNode{
		ID:         "nodea",
		LabelMajor: "Node A",
		LabelMinor: "'ts an a",
		Pseudo:     false,
		Node:       report.MakeNode().WithAdjacent("nodeb"),
	}
	nodeap := nodea
	nodeap.Adjacency = []string{
		"nodeb",
		"nodeq", // not the same anymore
	}
	nodeb := render.RenderableNode{
		ID:         "nodeb",
		LabelMajor: "Node B",
	}

	// Helper to make RenderableNode maps.
	nodes := func(ns ...render.RenderableNode) render.RenderableNodes {
		r := render.RenderableNodes{}
		for _, n := range ns {
			r[n.ID] = n
		}
		return r
	}

	for _, c := range []struct {
		label      string
		have, want render.Diff
	}{
		{
			label: "basecase: empty -> something",
			have:  render.TopoDiff(nodes(), nodes(nodea, nodeb)),
			want: render.Diff{
				Add: []render.RenderableNode{nodea, nodeb},
			},
		},
		{
			label: "basecase: something -> empty",
			have:  render.TopoDiff(nodes(nodea, nodeb), nodes()),
			want: render.Diff{
				Remove: []string{"nodea", "nodeb"},
			},
		},
		{
			label: "add and remove",
			have:  render.TopoDiff(nodes(nodea), nodes(nodeb)),
			want: render.Diff{
				Add:    []render.RenderableNode{nodeb},
				Remove: []string{"nodea"},
			},
		},
		{
			label: "no change",
			have:  render.TopoDiff(nodes(nodea), nodes(nodea)),
			want:  render.Diff{},
		},
		{
			label: "change a single node",
			have:  render.TopoDiff(nodes(nodea), nodes(nodeap)),
			want: render.Diff{
				Update: []render.RenderableNode{nodeap},
			},
		},
	} {
		sort.Strings(c.have.Remove)
		sort.Sort(ByID(c.have.Add))
		sort.Sort(ByID(c.have.Update))
		if !reflect.DeepEqual(c.want, c.have) {
			t.Errorf("%s - %s", c.label, test.Diff(c.want, c.have))
		}
	}
}