format output in client instead of server

This commit is contained in:
Max Erenberg 2023-04-04 02:52:47 -04:00 committed by Mirror
parent 65e152ad2f
commit af8beafd9e
3 changed files with 110 additions and 48 deletions

View File

@ -1,6 +1,8 @@
package arthur
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
@ -9,14 +11,24 @@ import (
"path/filepath"
"sort"
"strings"
"text/tabwriter"
"time"
"git.csclub.uwaterloo.ca/public/merlin/config"
"git.csclub.uwaterloo.ca/public/merlin/logger"
"git.csclub.uwaterloo.ca/public/merlin/sync"
)
type RepoStatusInfo struct {
Name string `json:"name"`
IsRunning bool `json:"is_running"`
LastAttemptStartTime int64 `json:"last_attempt_time"`
LastAttemptExit int `json:"last_attempt_exit"`
LastSuccessfulAttemptStartTime int64 `json:"last_successful_attempt_time"`
NextSyncTime int64 `json:"next_sync_time"`
}
type StatusInfo struct {
Repos []*RepoStatusInfo `json:"repos"`
}
// Reads and parses the message sent over the accepted connection
func GetCommand(conn net.Conn) (command, repoName string) {
command = ""
@ -44,30 +56,8 @@ func SendAndLog(conn net.Conn, msg string) {
conn.Write([]byte(msg))
}
var location *time.Location
func unixTimeToStr(unixTime int64) string {
if unixTime == 0 {
return "unknown"
}
if location == nil {
var err error
// Force arthur to send back time information in America/Toronto time
location, err = time.LoadLocation("America/Toronto")
if err != nil {
logger.ErrLog(err)
location = time.UTC
}
}
// for other ways to format the time see: https://pkg.go.dev/time#pkg-constants
return time.Unix(unixTime, 0).In(location).Format(time.RFC1123)
}
// Writes the status of the repos to the accepted connection
func SendStatus(conn net.Conn) {
status := tabwriter.NewWriter(conn, 5, 5, 5, ' ', 0)
fmt.Fprintf(status, "Repository\tLast Synced\tNext Expected Sync\tLast Exit\tRunning\n")
// get the names of all of the repos in the config
var keys []string
for name := range config.RepoMap {
@ -75,22 +65,32 @@ func SendStatus(conn net.Conn) {
}
sort.Strings(keys)
// print out the state of each repo in the config (last and next sync time + if it is currently running)
for _, name := range keys {
repoStatuses := make([]*RepoStatusInfo, len(keys))
for i, name := range keys {
repo := config.RepoMap[name]
lastSync := repo.State.LastAttemptStartTime
nextSync := lastSync + int64(repo.Frequency)
lastExit := repo.State.LastAttemptExit
fmt.Fprintf(status, "%s\t%s\t%s\t%s\t%t\n",
name,
unixTimeToStr(lastSync),
unixTimeToStr(nextSync),
config.StatusToString(lastExit),
repo.State.IsRunning,
)
repoStatuses[i] = &RepoStatusInfo{
Name: name,
IsRunning: repo.State.IsRunning,
LastAttemptStartTime: repo.State.LastAttemptStartTime,
LastAttemptExit: repo.State.LastAttemptExit,
LastSuccessfulAttemptStartTime: repo.State.LastSuccessfulAttemptStartTime,
}
if repo.State.LastAttemptStartTime != 0 {
repoStatuses[i].NextSyncTime = repo.State.LastAttemptStartTime + int64(repo.Frequency)
}
}
statusInfo := StatusInfo{Repos: repoStatuses}
marshaledStatusInfo, err := json.Marshal(&statusInfo)
if err != nil {
logger.ErrLog(err)
return
}
writer := bufio.NewWriter(conn)
writer.Write(marshaledStatusInfo)
err = writer.Flush()
if err != nil {
logger.ErrLog(err)
}
status.Flush()
}
// Attempt to force the sync of the repo. Returns true iff a sync was started.

View File

@ -1,9 +1,11 @@
package arthur
import (
"encoding/json"
"io/ioutil"
"net"
"os"
"reflect"
"testing"
"time"
@ -92,14 +94,34 @@ func TestSendStatus(t *testing.T) {
if err != nil {
t.Errorf(err.Error())
}
expected := (`
Repository Last Synced Next Expected Sync Last Exit Running
alinux Sun, 02 May 2021 20:00:00 EDT Sun, 09 May 2021 20:00:03 EDT completed true
eeeee Sun, 13 Sep 2020 08:26:40 EDT Tue, 13 Oct 2020 08:26:40 EDT completed true
lnux Mon, 20 Dec 2021 06:33:20 EST Tue, 21 Dec 2021 06:33:20 EST completed false
`)[1:]
if expected != string(msg) {
t.Errorf("Expected:\n" + expected + "\nGot:\n" + string(msg))
statusInfo := StatusInfo{}
err = json.Unmarshal(msg, &statusInfo)
if err != nil {
t.Errorf(err.Error())
}
expected := StatusInfo{
Repos: []*RepoStatusInfo{
{
Name: "alinux",
IsRunning: true,
LastAttemptStartTime: 1620000000,
NextSyncTime: 1620604803,
},
{
Name: "eeeee",
IsRunning: true,
LastAttemptStartTime: 1600000000,
NextSyncTime: 1602592000,
},
{
Name: "lnux",
LastAttemptStartTime: 1640000000,
NextSyncTime: 1640086400,
},
},
}
if !reflect.DeepEqual(&expected, &statusInfo) {
t.Errorf("Expected:\n%v\nGot:%v\n", &expected, &statusInfo)
}
}

View File

@ -1,12 +1,18 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"os"
"text/tabwriter"
"time"
serverArthurPkg "git.csclub.uwaterloo.ca/public/merlin/arthur"
"git.csclub.uwaterloo.ca/public/merlin/config"
)
// var DEFAULT_SOCKET_PATH = "/home/mirror/merlin/merlin.sock"
@ -23,7 +29,6 @@ FLAGS:
`
func main() {
log.SetPrefix("[ERROR]: ")
log.SetFlags(0)
@ -59,6 +64,41 @@ func main() {
if err != nil {
log.Fatal(err)
}
fmt.Println(string(response))
statusInfo := serverArthurPkg.StatusInfo{}
err = json.Unmarshal(response, &statusInfo)
if err != nil {
log.Fatal(err)
}
writer := tabwriter.NewWriter(os.Stdout, 5, 5, 5, ' ', 0)
// print out the state of each repo in the config (last and next sync time + if it is currently running)
fmt.Fprintf(writer, "Repository\tLast Synced\tNext Expected Sync\tLast Exit\tRunning\n")
for _, repo := range statusInfo.Repos {
fmt.Fprintf(writer, "%s\t%s\t%s\t%s\t%t\n",
repo.Name,
unixTimeToStr(repo.LastAttemptStartTime),
unixTimeToStr(repo.NextSyncTime),
config.StatusToString(repo.LastAttemptExit),
repo.IsRunning,
)
}
writer.Flush()
}
var location *time.Location
func unixTimeToStr(unixTime int64) string {
if unixTime == 0 {
return "unknown"
}
if location == nil {
var err error
// Force arthur to send back time information in America/Toronto time
location, err = time.LoadLocation("America/Toronto")
if err != nil {
location = time.UTC
}
}
// for other ways to format the time see: https://pkg.go.dev/time#pkg-constants
return time.Unix(unixTime, 0).In(location).Format(time.RFC1123)
}