This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 4.0 kB View raw
1package notella 2 3import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "log" 8 "net/http" 9 _ "net/http/pprof" 10 11 "firebase.google.com/go/v4/messaging" 12 ll "github.com/gwennlbh/label-logger-go" 13 "github.com/nats-io/nats.go" 14 "github.com/nats-io/nats.go/jetstream" 15) 16 17type HealthResponse struct { 18 Redis bool `json:"redis"` 19 NATS bool `json:"nats"` 20 ChurrosDatabase bool `json:"churros_db"` 21 Firebase bool `json:"firebase"` 22} 23 24func (r HealthResponse) AllGood() bool { 25 return r.Redis && r.NATS && r.ChurrosDatabase && r.Firebase 26} 27 28func healthHandler(w http.ResponseWriter, r *http.Request) { 29 ll.Debug("Checking health due to request from %s", r.RemoteAddr) 30 // Set the content type to JSON 31 w.Header().Set("Content-Type", "application/json") 32 33 // Example response (you can modify this with your own business logic) 34 response := CheckHealth() 35 36 // Marshal the response to JSON and write it to the response writer 37 if err := json.NewEncoder(w).Encode(response); err != nil { 38 http.Error(w, "Unable to encode JSON", http.StatusInternalServerError) 39 return 40 } 41} 42 43func CheckHealth() HealthResponse { 44 response := HealthResponse{} 45 46 if err := CheckRedisHealth(); err != nil { 47 ll.ErrorDisplay("while checking Redis health", err) 48 } else { 49 response.Redis = true 50 } 51 52 if err := CheckNATSHealth(); err != nil { 53 ll.ErrorDisplay("while checking NATS health", err) 54 } else { 55 response.NATS = true 56 } 57 58 if err := CheckChurrosDatabaseHealth(); err != nil { 59 ll.ErrorDisplay("while checking Churros database health", err) 60 } else { 61 response.ChurrosDatabase = true 62 } 63 64 if err := CheckFirebaseHealth(); err != nil { 65 ll.ErrorDisplay("while checking Firebase Cloud Messaging health", err) 66 } else { 67 response.Firebase = true 68 } 69 return response 70} 71 72func StartHealthCheckEndpoint(port int) { 73 // Set up route for the /health endpoint 74 http.HandleFunc("/health", healthHandler) 75 76 // Start the server and log any errors 77 ll.Log("Starting", "cyan", "health check endpoint on :%d/health", port) 78 if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil { 79 log.Fatalf("Server failed to start: %v", err) 80 } 81} 82 83func CheckRedisHealth() error { 84 return redisClient.Ping(context.Background()).Err() 85} 86 87func CheckNATSHealth() error { 88 nc, err := nats.Connect(config.NatsURL) 89 if err != nil { 90 return fmt.Errorf("could not connect to NATS at %s: %w", config.NatsURL, err) 91 } 92 93 defer nc.Close() 94 95 js, err := jetstream.New(nc) 96 if err != nil { 97 return fmt.Errorf("could not connect to Jetstream: %w", err) 98 } 99 100 stream, err := js.CreateStream(context.Background(), jetstream.StreamConfig{ 101 Name: StreamName, 102 Subjects: []string{SubjectName}, 103 }) 104 if err != nil { 105 return fmt.Errorf("could not create stream: %w", err) 106 } 107 108 consumers := stream.ListConsumers(context.Background()) 109 if consumers.Err() != nil { 110 return fmt.Errorf("could not list consumers: %w", consumers.Err()) 111 } 112 113 for info := range consumers.Info() { 114 if consumers.Err() != nil { 115 return fmt.Errorf("could not get consumer info: %w", consumers.Err()) 116 } 117 if info.Name == ConsumerName { 118 return nil 119 } 120 } 121 122 return fmt.Errorf("%s not connected to stream", ConsumerName) 123} 124 125func CheckChurrosDatabaseHealth() error { 126 return prisma.Prisma.QueryRaw("SELECT 1").Exec(context.Background(), nil) 127} 128 129func CheckFirebaseHealth() error { 130 if !config.HasValidFirebaseServiceAccount() { 131 return nil 132 } 133 134 fcm, err := firebaseClient.Messaging(firebaseCtx) 135 if err != nil { 136 return fmt.Errorf("while initializing messaging client: %w", err) 137 } 138 139 _, err = fcm.SendDryRun(firebaseCtx, &messaging.Message{ 140 Notification: &messaging.Notification{ 141 Title: "Health check attempt", 142 Body: "This is a health check attempt to ensure that the FCM service is working properly. The notification is not supposed to be displayed to the user.", 143 }, 144 Token: "invalid", 145 }) 146 if err != nil && err.Error() == "The registration token is not a valid FCM registration token" { 147 return nil 148 } 149 return err 150}