From e8d15f82d2e2c4ef75806228d92a106bf42cba72 Mon Sep 17 00:00:00 2001 From: purevoice <57848060+purevoice@users.noreply.github.com> Date: Sun, 4 May 2025 15:00:45 +0100 Subject: [PATCH] Update sample.go added input validation, graceful shutdown, and structured JSON proof - Added error handling for user input with `bufio.ReadString`. - Wrapped proof data in a JSON struct for clarity and future extensibility. - Replaced `fmt.Printf` with structured `log.Printf` for consistent logging. - Made endpoint configurable via `PROOF_ENDPOINT` environment variable. - Added graceful shutdown on SIGINT (Ctrl+C). - Used a `select` with timeout for non-blocking channel send. --- sample.go | 67 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/sample.go b/sample.go index 6179684..76f1813 100644 --- a/sample.go +++ b/sample.go @@ -2,46 +2,79 @@ package main import ( "bufio" + "encoding/json" "fmt" "gopkg.in/zeromq/goczmq.v4" "log" "os" + "os/signal" "strings" "time" ) +const ( + defaultProofHeader = "proofblock" + defaultHash = "0x0000000000000000000" +) + +type Proof struct { + Type string `json:"type"` + Timestamp string `json:"timestamp,omitempty"` + Data string `json:"data"` +} + func main() { - ep := "tcp://34.71.52.251:40000" + ep := os.Getenv("PROOF_ENDPOINT") + if ep == "" { + ep = "tcp://34.71.52.251:40000" + } + sample := goczmq.NewReqChanneler(ep) if sample == nil { - log.Fatal("Failed to subscribe to endpoint: ", ep) + log.Fatalf("Failed to subscribe to endpoint: %s", ep) } defer sample.Destroy() - // Prompt the user for input + // Graceful shutdown on Ctrl+C + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + go func() { + <-c + log.Println("Interrupt received, shutting down.") + sample.Destroy() + os.Exit(0) + }() + reader := bufio.NewReader(os.Stdin) fmt.Print("Enter proof data (or press Enter to use default): ") - input, _ := reader.ReadString('\n') + input, err := reader.ReadString('\n') + if err != nil { + log.Fatalf("Failed to read input: %v", err) + } input = strings.TrimSpace(input) - // Let the socket connect - time.Sleep(5 * time.Second) + time.Sleep(5 * time.Second) // Wait for connection - // Prepare the proof data - var proof [][]byte + var proof Proof if input == "" { - // Use default value if no input is provided - proof = [][]byte{[]byte("proofblock"), []byte("timestamp :" + time.Now().String()), []byte("0x0000000000000000000")} + proof = Proof{Type: defaultProofHeader, Timestamp: time.Now().String(), Data: defaultHash} } else { - // Use user-provided input - proof = [][]byte{[]byte("proofblock"), []byte(input), []byte("!!!!!")} + proof = Proof{Type: defaultProofHeader, Data: input} } - // Send the proof - sample.SendChan <- proof - fmt.Printf("Proof sent: %s\n", proof) + jsonProof, err := json.Marshal(proof) + if err != nil { + log.Fatalf("Failed to encode proof as JSON: %v", err) + } + + select { + case sample.SendChan <- [][]byte{jsonProof}: + log.Printf("Proof sent: %s", jsonProof) + case <-time.After(5 * time.Second): + log.Println("Timed out while trying to send proof.") + return + } - // Receive the response resp := <-sample.RecvChan - fmt.Printf("Response received: %s\n", resp) + log.Printf("Response received: %s", resp) }