// ReplayHistory sends back the history to a subscriber. // // This should be called before the client goes into active listening. // // Params: // - topic (string): The topic to fetch. // // Returns: // - int: The number of history messages sent to the client. func ReplayHistory(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { req := c.Get("http.Request", nil).(*http.Request) res := c.Get("http.ResponseWriter", nil).(ResponseWriterFlusher) medium, _ := getMedium(c) name := p.Get("topic", "").(string) // This does not manage topics. If there is no topic set, we silently fail. if len(name) == 0 { c.Log("info", "No topic name given to ReplayHistory.") return 0, nil } top, ok := medium.Topic(name) if !ok { c.Logf("info", "No topic named %s exists yet. No history replayed.", name) return 0, nil } topic, ok := top.(HistoriedTopic) if !ok { c.Logf("info", "No history for topic %s.", name) res.Header().Add(XHistoryEnabled, "False") return 0, nil } res.Header().Add(XHistoryEnabled, "True") since := req.Header.Get(XHistorySince) max := req.Header.Get(XHistoryLength) // maxLen can be used either on its own or paired with X-History-Since. maxLen := 0 if len(max) > 0 { m, err := parseHistLen(max) if err != nil { c.Logf("info", "failed to parse X-History-Length %s", max) } else { maxLen = m } } if len(since) > 0 { ts, err := parseSince(since) if err != nil { c.Logf("warn", "Failed to parse X-History-Since field %s: %s", since, err) return 0, nil } toSend := topic.Since(ts) // If maxLen is also set, we trim the list by sending the newest. ls := len(toSend) if maxLen > 0 && ls > maxLen { offset := ls - maxLen - 1 toSend = toSend[offset:] } return sendHistory(c, res, toSend) } else if maxLen > 0 { toSend := topic.Last(maxLen) return sendHistory(c, res, toSend) } return 0, nil }
// KillOnExit kills PIDs when the program exits. // // Otherwise, this blocks until an os.Interrupt or os.Kill is received. // // Params: // This treats Params as a map of process names (unimportant) to PIDs. It then // attempts to kill all of the pids that it receives. func KillOnExit(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { sigs := make(chan os.Signal, 1) signal.Notify(sigs, os.Interrupt, os.Kill) safely.GoDo(c, func() { log.Info(c, "Builder is running.") <-sigs c.Log("info", "Builder received signal to stop.") pids := p.AsMap() killed := 0 for name, pid := range pids { if pid, ok := pid.(int); ok { if proc, err := os.FindProcess(pid); err == nil { log.Infof(c, "Killing %s (pid=%d)", name, pid) proc.Kill() killed++ } } } }) return nil, nil }
func send(c cookoo.Context, l LogLevel, args ...interface{}) { if Level >= l { c.Log(Label[l], args...) } }