diff --git a/cmd/mothd/main.go b/cmd/mothd/main.go index 61bb823..e575503 100644 --- a/cmd/mothd/main.go +++ b/cmd/mothd/main.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + "log" "mime" "os" "time" @@ -53,15 +54,6 @@ func main() { ) flag.Parse() - // Set random seed - if *seed == "" { - *seed = os.Getenv("SEED") - } - if *seed == "" { - *seed = fmt.Sprintf("%d%d", os.Getpid(), time.Now().Unix()) - } - os.Setenv("SEED", *seed) - osfs := afero.NewOsFs() theme := NewTheme(afero.NewBasePathFs(osfs, *themePath)) state := NewState(afero.NewBasePathFs(osfs, *statePath)) @@ -73,8 +65,19 @@ func main() { if *puzzlePath != "" { provider = NewTranspilerProvider(afero.NewBasePathFs(osfs, *puzzlePath)) config.Devel = true + log.Println("-=- You are in development mode, champ! -=-") } + // Set random seed + if *seed == "" { + *seed = os.Getenv("SEED") + } + if *seed == "" { + *seed = fmt.Sprintf("%d%d", os.Getpid(), time.Now().Unix()) + } + os.Setenv("SEED", *seed) + log.Print("SEED=", *seed) + // Add some MIME extensions // Doing this avoids decompressing a mothball entry twice per request mime.AddExtensionType(".json", "application/json") diff --git a/cmd/mothd/state.go b/cmd/mothd/state.go index 38d3c7e..d8466de 100644 --- a/cmd/mothd/state.go +++ b/cmd/mothd/state.go @@ -2,12 +2,14 @@ package main import ( "bufio" + "encoding/csv" "errors" "fmt" "log" "math/rand" "os" "path/filepath" + "strconv" "strings" "time" @@ -36,9 +38,10 @@ type State struct { // Enabled tracks whether the current State system is processing updates Enabled bool - refreshNow chan bool - eventStream chan string - eventWriter afero.File + refreshNow chan bool + eventStream chan []string + eventWriter *csv.Writer + eventWriterFile afero.File } // NewState returns a new State struct backed by the given Fs @@ -47,7 +50,7 @@ func NewState(fs afero.Fs) *State { Fs: fs, Enabled: true, refreshNow: make(chan bool, 5), - eventStream: make(chan string, 80), + eventStream: make(chan []string, 80), } if err := s.reopenEventLog(); err != nil { log.Fatal(err) @@ -100,12 +103,6 @@ func (s *State) updateEnabled() { } if _, err := s.Stat("enabled"); os.IsNotExist(err) { - dirs, _ := afero.ReadDir(s, ".") - for _, dir := range dirs { - log.Println(dir.Name()) - } - - log.Print(s, err) nextEnabled = false why = "`state/enabled` missing" } @@ -380,34 +377,35 @@ func logstr(s string) string { // LogEvent writes to the event log func (s *State) LogEvent(event, participantID, teamID, cat string, points int, extra ...string) { - event = strings.ReplaceAll(event, " ", "-") - - msg := fmt.Sprintf( - "%s %s %s %s %d", - logstr(event), - logstr(participantID), - logstr(teamID), - logstr(cat), - points, + s.eventStream <- append( + []string{ + strconv.FormatInt(time.Now().Unix(), 10), + event, + participantID, + teamID, + cat, + strconv.Itoa(points), + }, + extra..., ) - for _, x := range extra { - msg = msg + " " + strings.ReplaceAll(x, " ", "-") - } - s.eventStream <- msg } func (s *State) reopenEventLog() error { if s.eventWriter != nil { - if err := s.eventWriter.Close(); err != nil { + s.eventWriter.Flush() + } + if s.eventWriterFile != nil { + if err := s.eventWriterFile.Close(); err != nil { // We're going to soldier on if Close returns error log.Print(err) } } - eventWriter, err := s.OpenFile("events.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + eventWriterFile, err := s.OpenFile("events.csv", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } - s.eventWriter = eventWriter + s.eventWriterFile = eventWriterFile + s.eventWriter = csv.NewWriter(s.eventWriterFile) return nil } @@ -426,8 +424,9 @@ func (s *State) Maintain(updateInterval time.Duration) { for { select { case msg := <-s.eventStream: - fmt.Fprintln(s.eventWriter, time.Now().Unix(), msg) - s.eventWriter.Sync() + s.eventWriter.Write(msg) + s.eventWriter.Flush() + s.eventWriterFile.Sync() case <-ticker.C: s.refresh() case <-s.refreshNow: diff --git a/cmd/mothd/state_test.go b/cmd/mothd/state_test.go index f6635fa..ce19854 100644 --- a/cmd/mothd/state_test.go +++ b/cmd/mothd/state_test.go @@ -127,13 +127,13 @@ func TestStateEvents(t *testing.T) { s.LogEvent("moo", "", "", "", 0) s.LogEvent("moo 2", "", "", "", 0) - if msg := <-s.eventStream; msg != "init - - - 0" { + if msg := <-s.eventStream; strings.Join(msg[1:], ":") != "init::::0" { t.Error("Wrong message from event stream:", msg) } - if msg := <-s.eventStream; msg != "moo - - - 0" { + if msg := <-s.eventStream; strings.Join(msg[1:], ":") != "moo::::0" { t.Error("Wrong message from event stream:", msg) } - if msg := <-s.eventStream; msg != "moo-2 - - - 0" { + if msg := <-s.eventStream; strings.Join(msg[1:], ":") != "moo 2::::0" { t.Error("Wrong message from event stream:", msg) } } @@ -255,7 +255,7 @@ func TestStateMaintainer(t *testing.T) { time.Sleep(updateInterval) - eventLog, err := afero.ReadFile(s.Fs, "events.log") + eventLog, err := afero.ReadFile(s.Fs, "events.csv") if err != nil { t.Error(err) } else if events := strings.Split(string(eventLog), "\n"); len(events) != 3 {