From d055daa444f16f2899aae13edc61e30ea62c95fa Mon Sep 17 00:00:00 2001 From: Ignat Harczuk Date: Tue, 1 Mar 2022 10:19:48 +0100 Subject: [PATCH 1/8] feat: Alive interface for reporting Liveliness --- options.go | 23 ++++++++++++++++++++++- svc.go | 3 +++ worker.go | 5 +++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/options.go b/options.go index 51855d0..dec1d14 100644 --- a/options.go +++ b/options.go @@ -125,8 +125,29 @@ func WithHealthz() Option { return func(s *SVC) error { // Register live probe handler s.Router.HandleFunc("/live", func(w http.ResponseWriter, r *http.Request) { + var errs []error + for n, w := range s.workers { + if hw, ok := w.(Aliver); ok { + if err := hw.Alive(); err != nil { + errs = append(errs, fmt.Errorf("worker %s: %s", n, err)) + } + } + } + if len(errs) == 0 { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"status": "Still Alive!"}`)) + return + } + + s.logger.Warn("liveliness probe failed", zap.Errors("errors", errs)) + b, err := json.Marshal(map[string]interface{}{"errors": errs}) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusServiceUnavailable) w.Header().Set("Content-Type", "application/json") - _, _ = w.Write([]byte(`{"status": "Still Alive!"}`)) + _, _ = w.Write(b) }) // Register ready probe handler diff --git a/svc.go b/svc.go index 5138b1e..eac4ebf 100644 --- a/svc.go +++ b/svc.go @@ -93,6 +93,9 @@ func (s *SVC) AddWorker(name string, w Worker) { if _, ok := w.(Healther); !ok { s.logger.Warn("Worker does not implement Healther interface", zap.String("worker", name)) } + if _, ok := w.(Aliver); !ok { + s.logger.Warn("Worker does not implement Aliver interface", zap.String("worker", name)) + } if g, ok := w.(Gatherer); ok { s.AddGatherer(g.Gatherer()) } else { diff --git a/worker.go b/worker.go index 4116c18..278850c 100644 --- a/worker.go +++ b/worker.go @@ -12,6 +12,11 @@ type Worker interface { Terminate() error } +// Aliver defines a worker that can report his livez status. +type Aliver interface { + Alive() error +} + // Healther defines a worker that can report his healthz status. type Healther interface { Healthy() error From 05c6aab969668b87a3d43884219b8bf4fc3b2098 Mon Sep 17 00:00:00 2001 From: Ignat Harczuk Date: Tue, 1 Mar 2022 14:18:10 +0100 Subject: [PATCH 2/8] chore: test live endpoint --- coverage.txt | 211 +++++++++++++++++++++++++----------------------- options_test.go | 69 ++++++++++++++++ svc_test.go | 8 ++ 3 files changed, 188 insertions(+), 100 deletions(-) create mode 100644 options_test.go diff --git a/coverage.txt b/coverage.txt index 7bf2e05..8a17d45 100644 --- a/coverage.txt +++ b/coverage.txt @@ -1,17 +1,78 @@ mode: atomic -github.com/voi-oss/svc/config.go:10.44,11.42 1 0 -github.com/voi-oss/svc/config.go:14.2,14.55 1 0 -github.com/voi-oss/svc/config.go:17.2,17.12 1 0 -github.com/voi-oss/svc/config.go:11.42,13.3 1 0 -github.com/voi-oss/svc/config.go:14.55,16.3 1 0 -github.com/voi-oss/svc/http.go:21.87,31.2 2 0 -github.com/voi-oss/svc/http.go:34.53,38.2 2 0 +github.com/voi-oss/svc/svc.go:54.62,70.51 2 13 +github.com/voi-oss/svc/svc.go:74.2,78.25 3 13 +github.com/voi-oss/svc/svc.go:84.2,84.15 1 13 +github.com/voi-oss/svc/svc.go:70.51,72.3 1 0 +github.com/voi-oss/svc/svc.go:78.25,79.30 1 12 +github.com/voi-oss/svc/svc.go:79.30,81.4 1 0 +github.com/voi-oss/svc/svc.go:89.48,90.42 1 9 +github.com/voi-oss/svc/svc.go:93.2,93.32 1 9 +github.com/voi-oss/svc/svc.go:96.2,96.30 1 9 +github.com/voi-oss/svc/svc.go:99.2,99.31 1 9 +github.com/voi-oss/svc/svc.go:105.2,106.21 2 9 +github.com/voi-oss/svc/svc.go:90.42,92.3 1 0 +github.com/voi-oss/svc/svc.go:93.32,95.3 1 7 +github.com/voi-oss/svc/svc.go:96.30,98.3 1 2 +github.com/voi-oss/svc/svc.go:99.31,101.3 1 0 +github.com/voi-oss/svc/svc.go:101.8,103.3 1 9 +github.com/voi-oss/svc/svc.go:109.57,112.2 2 0 +github.com/voi-oss/svc/svc.go:116.21,119.15 2 5 +github.com/voi-oss/svc/svc.go:128.2,128.38 1 5 +github.com/voi-oss/svc/svc.go:138.2,140.33 3 5 +github.com/voi-oss/svc/svc.go:151.2,153.9 2 5 +github.com/voi-oss/svc/svc.go:119.15,125.3 5 4 +github.com/voi-oss/svc/svc.go:128.38,131.54 3 9 +github.com/voi-oss/svc/svc.go:135.3,135.60 1 9 +github.com/voi-oss/svc/svc.go:131.54,134.4 2 0 +github.com/voi-oss/svc/svc.go:140.33,142.34 2 9 +github.com/voi-oss/svc/svc.go:142.34,144.34 2 9 +github.com/voi-oss/svc/svc.go:144.34,147.5 2 1 +github.com/voi-oss/svc/svc.go:154.21,155.40 1 1 +github.com/voi-oss/svc/svc.go:158.3,158.59 1 1 +github.com/voi-oss/svc/svc.go:159.26,160.69 1 1 +github.com/voi-oss/svc/svc.go:161.30,162.45 1 2 +github.com/voi-oss/svc/svc.go:155.40,157.4 1 0 +github.com/voi-oss/svc/svc.go:171.26,173.2 1 1 +github.com/voi-oss/svc/svc.go:176.39,177.16 1 0 +github.com/voi-oss/svc/svc.go:184.2,184.10 1 0 +github.com/voi-oss/svc/svc.go:177.16,178.34 1 0 +github.com/voi-oss/svc/svc.go:181.3,182.13 2 0 +github.com/voi-oss/svc/svc.go:178.34,179.14 1 0 +github.com/voi-oss/svc/svc.go:188.36,190.2 1 0 +github.com/voi-oss/svc/svc.go:192.34,198.12 4 4 +github.com/voi-oss/svc/svc.go:213.2,214.41 2 4 +github.com/voi-oss/svc/svc.go:198.12,201.45 3 4 +github.com/voi-oss/svc/svc.go:201.45,202.28 1 7 +github.com/voi-oss/svc/svc.go:202.28,204.41 2 7 +github.com/voi-oss/svc/svc.go:209.5,209.67 1 7 +github.com/voi-oss/svc/svc.go:204.41,208.6 1 0 +github.com/voi-oss/svc/svc.go:217.60,218.9 1 4 +github.com/voi-oss/svc/svc.go:219.29,219.29 0 4 +github.com/voi-oss/svc/svc.go:220.23,220.23 0 0 +github.com/voi-oss/svc/svc.go:224.58,226.12 2 9 +github.com/voi-oss/svc/svc.go:230.2,230.10 1 9 +github.com/voi-oss/svc/svc.go:226.12,229.3 2 9 +github.com/voi-oss/svc/svc.go:233.81,235.30 2 8 +github.com/voi-oss/svc/svc.go:235.30,236.31 1 0 +github.com/voi-oss/svc/svc.go:236.31,240.4 2 0 +github.com/voi-oss/svc/svc.go:240.9,242.4 1 0 +github.com/voi-oss/svc/svc.go:246.70,247.25 1 0 +github.com/voi-oss/svc/svc.go:250.2,250.30 1 0 +github.com/voi-oss/svc/svc.go:247.25,249.3 1 0 +github.com/voi-oss/svc/config.go:11.44,13.2 1 2 +github.com/voi-oss/svc/config.go:17.96,18.60 1 3 +github.com/voi-oss/svc/config.go:21.2,21.55 1 2 +github.com/voi-oss/svc/config.go:24.2,24.12 1 1 +github.com/voi-oss/svc/config.go:18.60,20.3 1 1 +github.com/voi-oss/svc/config.go:21.55,23.3 1 1 +github.com/voi-oss/svc/http.go:21.87,31.2 2 2 +github.com/voi-oss/svc/http.go:34.53,38.2 2 2 github.com/voi-oss/svc/http.go:41.38,43.2 1 0 -github.com/voi-oss/svc/http.go:46.34,48.71 2 0 -github.com/voi-oss/svc/http.go:51.2,51.12 1 0 -github.com/voi-oss/svc/http.go:48.71,50.3 1 0 -github.com/voi-oss/svc/http.go:55.40,57.2 1 0 -github.com/voi-oss/svc/logger.go:13.102,28.2 5 19 +github.com/voi-oss/svc/http.go:46.34,48.71 2 2 +github.com/voi-oss/svc/http.go:51.2,51.12 1 1 +github.com/voi-oss/svc/http.go:48.71,50.3 1 1 +github.com/voi-oss/svc/http.go:55.40,57.2 1 1 +github.com/voi-oss/svc/logger.go:13.102,28.2 5 21 github.com/voi-oss/svc/logger.go:32.30,33.28 1 0 github.com/voi-oss/svc/logger.go:33.28,41.59 2 0 github.com/voi-oss/svc/logger.go:45.3,46.42 1 0 @@ -22,17 +83,17 @@ github.com/voi-oss/svc/logger.go:51.5,52.15 2 0 github.com/voi-oss/svc/logger.go:48.19,50.6 1 0 github.com/voi-oss/svc/logger.go:59.66,60.28 1 0 github.com/voi-oss/svc/logger.go:60.28,62.3 1 0 -github.com/voi-oss/svc/logger.go:67.55,68.28 1 13 -github.com/voi-oss/svc/logger.go:68.28,76.3 4 13 +github.com/voi-oss/svc/logger.go:67.55,68.28 1 15 +github.com/voi-oss/svc/logger.go:68.28,76.3 4 15 github.com/voi-oss/svc/logger.go:81.54,82.28 1 2 github.com/voi-oss/svc/logger.go:82.28,90.3 4 2 github.com/voi-oss/svc/logger.go:95.72,96.28 1 2 github.com/voi-oss/svc/logger.go:96.28,106.3 5 2 github.com/voi-oss/svc/logger.go:111.76,112.28 1 2 github.com/voi-oss/svc/logger.go:112.28,120.3 4 2 -github.com/voi-oss/svc/logger.go:123.75,125.16 2 19 -github.com/voi-oss/svc/logger.go:128.2,129.16 2 19 -github.com/voi-oss/svc/logger.go:133.2,138.12 5 19 +github.com/voi-oss/svc/logger.go:123.75,125.16 2 21 +github.com/voi-oss/svc/logger.go:128.2,129.16 2 21 +github.com/voi-oss/svc/logger.go:133.2,138.12 5 21 github.com/voi-oss/svc/logger.go:125.16,127.3 1 0 github.com/voi-oss/svc/logger.go:129.16,131.3 1 0 github.com/voi-oss/svc/options.go:19.56,20.28 1 0 @@ -41,86 +102,36 @@ github.com/voi-oss/svc/options.go:28.57,29.28 1 0 github.com/voi-oss/svc/options.go:29.28,33.3 2 0 github.com/voi-oss/svc/options.go:38.47,39.28 1 0 github.com/voi-oss/svc/options.go:39.28,42.3 2 0 -github.com/voi-oss/svc/options.go:47.36,48.28 1 0 -github.com/voi-oss/svc/options.go:48.28,52.3 2 0 -github.com/voi-oss/svc/options.go:57.41,58.28 1 0 -github.com/voi-oss/svc/options.go:58.28,63.3 3 0 -github.com/voi-oss/svc/options.go:67.27,68.28 1 0 -github.com/voi-oss/svc/options.go:68.28,78.56 3 0 -github.com/voi-oss/svc/options.go:82.3,82.13 1 0 -github.com/voi-oss/svc/options.go:78.56,80.4 1 0 -github.com/voi-oss/svc/options.go:88.34,89.28 1 0 -github.com/voi-oss/svc/options.go:89.28,96.3 2 0 -github.com/voi-oss/svc/options.go:101.33,102.28 1 0 -github.com/voi-oss/svc/options.go:102.28,118.3 12 0 -github.com/voi-oss/svc/options.go:123.27,124.28 1 0 -github.com/voi-oss/svc/options.go:124.28,126.77 1 0 -github.com/voi-oss/svc/options.go:132.3,132.78 1 0 -github.com/voi-oss/svc/options.go:154.3,154.13 1 0 -github.com/voi-oss/svc/options.go:126.77,129.4 2 0 -github.com/voi-oss/svc/options.go:132.78,134.32 2 0 -github.com/voi-oss/svc/options.go:141.4,141.21 1 0 -github.com/voi-oss/svc/options.go:134.32,135.35 1 0 -github.com/voi-oss/svc/options.go:135.35,136.41 1 0 -github.com/voi-oss/svc/options.go:136.41,138.7 1 0 -github.com/voi-oss/svc/options.go:141.21,144.19 3 0 -github.com/voi-oss/svc/options.go:148.5,150.22 3 0 -github.com/voi-oss/svc/options.go:144.19,147.6 2 0 -github.com/voi-oss/svc/svc.go:54.62,70.51 2 11 -github.com/voi-oss/svc/svc.go:74.2,78.25 3 11 -github.com/voi-oss/svc/svc.go:84.2,84.15 1 11 -github.com/voi-oss/svc/svc.go:70.51,72.3 1 0 -github.com/voi-oss/svc/svc.go:78.25,79.30 1 8 -github.com/voi-oss/svc/svc.go:79.30,81.4 1 0 -github.com/voi-oss/svc/svc.go:89.48,90.42 1 5 -github.com/voi-oss/svc/svc.go:93.2,93.32 1 5 -github.com/voi-oss/svc/svc.go:96.2,96.31 1 5 -github.com/voi-oss/svc/svc.go:102.2,103.21 2 5 -github.com/voi-oss/svc/svc.go:90.42,92.3 1 0 -github.com/voi-oss/svc/svc.go:93.32,95.3 1 5 -github.com/voi-oss/svc/svc.go:96.31,98.3 1 0 -github.com/voi-oss/svc/svc.go:98.8,100.3 1 5 -github.com/voi-oss/svc/svc.go:106.57,109.2 2 0 -github.com/voi-oss/svc/svc.go:113.21,116.15 2 3 -github.com/voi-oss/svc/svc.go:125.2,125.38 1 3 -github.com/voi-oss/svc/svc.go:135.2,137.33 3 3 -github.com/voi-oss/svc/svc.go:148.2,150.9 2 3 -github.com/voi-oss/svc/svc.go:116.15,122.3 5 3 -github.com/voi-oss/svc/svc.go:125.38,128.54 3 5 -github.com/voi-oss/svc/svc.go:132.3,132.60 1 5 -github.com/voi-oss/svc/svc.go:128.54,131.4 2 0 -github.com/voi-oss/svc/svc.go:137.33,139.34 2 5 -github.com/voi-oss/svc/svc.go:139.34,141.34 2 5 -github.com/voi-oss/svc/svc.go:141.34,144.5 2 1 -github.com/voi-oss/svc/svc.go:151.21,152.40 1 1 -github.com/voi-oss/svc/svc.go:155.3,155.59 1 1 -github.com/voi-oss/svc/svc.go:156.26,157.69 1 1 -github.com/voi-oss/svc/svc.go:158.30,159.45 1 1 -github.com/voi-oss/svc/svc.go:152.40,154.4 1 0 -github.com/voi-oss/svc/svc.go:168.26,170.2 1 1 -github.com/voi-oss/svc/svc.go:173.39,174.16 1 0 -github.com/voi-oss/svc/svc.go:181.2,181.10 1 0 -github.com/voi-oss/svc/svc.go:174.16,175.34 1 0 -github.com/voi-oss/svc/svc.go:178.3,179.13 2 0 -github.com/voi-oss/svc/svc.go:175.34,176.14 1 0 -github.com/voi-oss/svc/svc.go:185.36,187.2 1 0 -github.com/voi-oss/svc/svc.go:189.34,195.12 4 3 -github.com/voi-oss/svc/svc.go:210.2,211.41 2 3 -github.com/voi-oss/svc/svc.go:195.12,198.45 3 3 -github.com/voi-oss/svc/svc.go:198.45,199.28 1 5 -github.com/voi-oss/svc/svc.go:199.28,201.41 2 5 -github.com/voi-oss/svc/svc.go:206.5,206.67 1 5 -github.com/voi-oss/svc/svc.go:201.41,205.6 1 0 -github.com/voi-oss/svc/svc.go:214.60,215.9 1 3 -github.com/voi-oss/svc/svc.go:216.29,216.29 0 3 -github.com/voi-oss/svc/svc.go:217.23,217.23 0 0 -github.com/voi-oss/svc/svc.go:221.58,223.12 2 6 -github.com/voi-oss/svc/svc.go:227.2,227.10 1 6 -github.com/voi-oss/svc/svc.go:223.12,226.3 2 6 -github.com/voi-oss/svc/svc.go:230.81,232.30 2 5 -github.com/voi-oss/svc/svc.go:232.30,233.31 1 0 -github.com/voi-oss/svc/svc.go:233.31,237.4 2 0 -github.com/voi-oss/svc/svc.go:237.9,239.4 1 0 -github.com/voi-oss/svc/svc.go:243.70,244.25 1 0 -github.com/voi-oss/svc/svc.go:247.2,247.30 1 0 -github.com/voi-oss/svc/svc.go:244.25,246.3 1 0 +github.com/voi-oss/svc/options.go:48.36,49.28 1 0 +github.com/voi-oss/svc/options.go:49.28,53.3 2 0 +github.com/voi-oss/svc/options.go:58.41,59.28 1 2 +github.com/voi-oss/svc/options.go:59.28,64.3 3 2 +github.com/voi-oss/svc/options.go:68.27,69.28 1 0 +github.com/voi-oss/svc/options.go:69.28,79.56 3 0 +github.com/voi-oss/svc/options.go:83.3,83.13 1 0 +github.com/voi-oss/svc/options.go:79.56,81.4 1 0 +github.com/voi-oss/svc/options.go:89.34,90.28 1 0 +github.com/voi-oss/svc/options.go:90.28,97.3 2 0 +github.com/voi-oss/svc/options.go:102.33,103.28 1 0 +github.com/voi-oss/svc/options.go:103.28,119.3 12 0 +github.com/voi-oss/svc/options.go:124.27,125.28 1 2 +github.com/voi-oss/svc/options.go:125.28,127.77 1 2 +github.com/voi-oss/svc/options.go:154.3,154.78 1 2 +github.com/voi-oss/svc/options.go:176.3,176.13 1 2 +github.com/voi-oss/svc/options.go:127.77,129.32 2 2 +github.com/voi-oss/svc/options.go:136.4,136.22 1 2 +github.com/voi-oss/svc/options.go:142.4,144.18 3 1 +github.com/voi-oss/svc/options.go:148.4,150.21 3 1 +github.com/voi-oss/svc/options.go:129.32,130.33 1 4 +github.com/voi-oss/svc/options.go:130.33,131.39 1 2 +github.com/voi-oss/svc/options.go:131.39,133.7 1 1 +github.com/voi-oss/svc/options.go:136.22,140.5 3 1 +github.com/voi-oss/svc/options.go:144.18,147.5 2 0 +github.com/voi-oss/svc/options.go:154.78,156.32 2 0 +github.com/voi-oss/svc/options.go:163.4,163.21 1 0 +github.com/voi-oss/svc/options.go:156.32,157.35 1 0 +github.com/voi-oss/svc/options.go:157.35,158.41 1 0 +github.com/voi-oss/svc/options.go:158.41,160.7 1 0 +github.com/voi-oss/svc/options.go:163.21,166.19 3 0 +github.com/voi-oss/svc/options.go:170.5,172.22 3 0 +github.com/voi-oss/svc/options.go:166.19,169.6 2 0 diff --git a/options_test.go b/options_test.go new file mode 100644 index 0000000..4ff60ec --- /dev/null +++ b/options_test.go @@ -0,0 +1,69 @@ +package svc + +import ( + "fmt" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stretchr/testify/require" + "go.uber.org/zap" +) + +func TestAlive(t *testing.T) { + + tests := []struct { + name string + givenError error + expectedCode int + }{ + { + name: "return status ok when no error", + + givenError: nil, + + expectedCode: 200, + }, + { + name: "should return status not available when an error", + + givenError: fmt.Errorf("internal error, restart container"), + + expectedCode: 503, + }, + } + + for _, tt := range tests { + tc := tt + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + dummyWorker := &WorkerMock{ + RunFunc: func() error { + return nil + }, + TerminateFunc: func() error { + return nil + }, + InitFunc: func(*zap.Logger) error { return nil }, + aliveFunc: func() error { + return tc.givenError + }, + } + + s, err := New("dummy-service", "v0.0.0", WithHealthz(), WithHTTPServer("9090")) + require.NoError(t, err) + + s.AddWorker("dummy-worker", dummyWorker) + + go s.Run() + + req := httptest.NewRequest("GET", "/live", nil) + rec := httptest.NewRecorder() + s.Router.ServeHTTP(rec, req) + assert.Equal(t, tc.expectedCode, rec.Code) + }) + + } + +} diff --git a/svc_test.go b/svc_test.go index 05bbad8..af59089 100644 --- a/svc_test.go +++ b/svc_test.go @@ -112,6 +112,7 @@ type WorkerMock struct { InitFunc func(*zap.Logger) error RunFunc func() error TerminateFunc func() error + aliveFunc func() error } func (w *WorkerMock) Init(l *zap.Logger) error { @@ -133,3 +134,10 @@ func (w *WorkerMock) Terminate() error { } return w.TerminateFunc() } + +func (w *WorkerMock) Alive() error { + if w.aliveFunc == nil { + panic("WorkerMock: Alive was called but aliveFunc was not mocked!") + } + return w.aliveFunc() +} From 76eb7ac69672a49fb38b2457abd9947730d6ebe2 Mon Sep 17 00:00:00 2001 From: Ignat Harczuk Date: Tue, 1 Mar 2022 14:21:20 +0100 Subject: [PATCH 3/8] chore: test Healtyh as well --- coverage.txt | 172 ++++++++++++++++++++++++------------------------ options_test.go | 59 ++++++++++++++++- svc_test.go | 16 +++-- 3 files changed, 154 insertions(+), 93 deletions(-) diff --git a/coverage.txt b/coverage.txt index 8a17d45..bb38cbf 100644 --- a/coverage.txt +++ b/coverage.txt @@ -1,78 +1,18 @@ mode: atomic -github.com/voi-oss/svc/svc.go:54.62,70.51 2 13 -github.com/voi-oss/svc/svc.go:74.2,78.25 3 13 -github.com/voi-oss/svc/svc.go:84.2,84.15 1 13 -github.com/voi-oss/svc/svc.go:70.51,72.3 1 0 -github.com/voi-oss/svc/svc.go:78.25,79.30 1 12 -github.com/voi-oss/svc/svc.go:79.30,81.4 1 0 -github.com/voi-oss/svc/svc.go:89.48,90.42 1 9 -github.com/voi-oss/svc/svc.go:93.2,93.32 1 9 -github.com/voi-oss/svc/svc.go:96.2,96.30 1 9 -github.com/voi-oss/svc/svc.go:99.2,99.31 1 9 -github.com/voi-oss/svc/svc.go:105.2,106.21 2 9 -github.com/voi-oss/svc/svc.go:90.42,92.3 1 0 -github.com/voi-oss/svc/svc.go:93.32,95.3 1 7 -github.com/voi-oss/svc/svc.go:96.30,98.3 1 2 -github.com/voi-oss/svc/svc.go:99.31,101.3 1 0 -github.com/voi-oss/svc/svc.go:101.8,103.3 1 9 -github.com/voi-oss/svc/svc.go:109.57,112.2 2 0 -github.com/voi-oss/svc/svc.go:116.21,119.15 2 5 -github.com/voi-oss/svc/svc.go:128.2,128.38 1 5 -github.com/voi-oss/svc/svc.go:138.2,140.33 3 5 -github.com/voi-oss/svc/svc.go:151.2,153.9 2 5 -github.com/voi-oss/svc/svc.go:119.15,125.3 5 4 -github.com/voi-oss/svc/svc.go:128.38,131.54 3 9 -github.com/voi-oss/svc/svc.go:135.3,135.60 1 9 -github.com/voi-oss/svc/svc.go:131.54,134.4 2 0 -github.com/voi-oss/svc/svc.go:140.33,142.34 2 9 -github.com/voi-oss/svc/svc.go:142.34,144.34 2 9 -github.com/voi-oss/svc/svc.go:144.34,147.5 2 1 -github.com/voi-oss/svc/svc.go:154.21,155.40 1 1 -github.com/voi-oss/svc/svc.go:158.3,158.59 1 1 -github.com/voi-oss/svc/svc.go:159.26,160.69 1 1 -github.com/voi-oss/svc/svc.go:161.30,162.45 1 2 -github.com/voi-oss/svc/svc.go:155.40,157.4 1 0 -github.com/voi-oss/svc/svc.go:171.26,173.2 1 1 -github.com/voi-oss/svc/svc.go:176.39,177.16 1 0 -github.com/voi-oss/svc/svc.go:184.2,184.10 1 0 -github.com/voi-oss/svc/svc.go:177.16,178.34 1 0 -github.com/voi-oss/svc/svc.go:181.3,182.13 2 0 -github.com/voi-oss/svc/svc.go:178.34,179.14 1 0 -github.com/voi-oss/svc/svc.go:188.36,190.2 1 0 -github.com/voi-oss/svc/svc.go:192.34,198.12 4 4 -github.com/voi-oss/svc/svc.go:213.2,214.41 2 4 -github.com/voi-oss/svc/svc.go:198.12,201.45 3 4 -github.com/voi-oss/svc/svc.go:201.45,202.28 1 7 -github.com/voi-oss/svc/svc.go:202.28,204.41 2 7 -github.com/voi-oss/svc/svc.go:209.5,209.67 1 7 -github.com/voi-oss/svc/svc.go:204.41,208.6 1 0 -github.com/voi-oss/svc/svc.go:217.60,218.9 1 4 -github.com/voi-oss/svc/svc.go:219.29,219.29 0 4 -github.com/voi-oss/svc/svc.go:220.23,220.23 0 0 -github.com/voi-oss/svc/svc.go:224.58,226.12 2 9 -github.com/voi-oss/svc/svc.go:230.2,230.10 1 9 -github.com/voi-oss/svc/svc.go:226.12,229.3 2 9 -github.com/voi-oss/svc/svc.go:233.81,235.30 2 8 -github.com/voi-oss/svc/svc.go:235.30,236.31 1 0 -github.com/voi-oss/svc/svc.go:236.31,240.4 2 0 -github.com/voi-oss/svc/svc.go:240.9,242.4 1 0 -github.com/voi-oss/svc/svc.go:246.70,247.25 1 0 -github.com/voi-oss/svc/svc.go:250.2,250.30 1 0 -github.com/voi-oss/svc/svc.go:247.25,249.3 1 0 github.com/voi-oss/svc/config.go:11.44,13.2 1 2 github.com/voi-oss/svc/config.go:17.96,18.60 1 3 github.com/voi-oss/svc/config.go:21.2,21.55 1 2 github.com/voi-oss/svc/config.go:24.2,24.12 1 1 github.com/voi-oss/svc/config.go:18.60,20.3 1 1 github.com/voi-oss/svc/config.go:21.55,23.3 1 1 -github.com/voi-oss/svc/http.go:21.87,31.2 2 2 -github.com/voi-oss/svc/http.go:34.53,38.2 2 2 -github.com/voi-oss/svc/http.go:41.38,43.2 1 0 -github.com/voi-oss/svc/http.go:46.34,48.71 2 2 -github.com/voi-oss/svc/http.go:51.2,51.12 1 1 -github.com/voi-oss/svc/http.go:48.71,50.3 1 1 -github.com/voi-oss/svc/http.go:55.40,57.2 1 1 -github.com/voi-oss/svc/logger.go:13.102,28.2 5 21 +github.com/voi-oss/svc/http.go:21.87,31.2 2 4 +github.com/voi-oss/svc/http.go:34.53,38.2 2 4 +github.com/voi-oss/svc/http.go:41.38,43.2 1 2 +github.com/voi-oss/svc/http.go:46.34,48.71 2 4 +github.com/voi-oss/svc/http.go:51.2,51.12 1 3 +github.com/voi-oss/svc/http.go:48.71,50.3 1 3 +github.com/voi-oss/svc/http.go:55.40,57.2 1 3 +github.com/voi-oss/svc/logger.go:13.102,28.2 5 23 github.com/voi-oss/svc/logger.go:32.30,33.28 1 0 github.com/voi-oss/svc/logger.go:33.28,41.59 2 0 github.com/voi-oss/svc/logger.go:45.3,46.42 1 0 @@ -83,17 +23,17 @@ github.com/voi-oss/svc/logger.go:51.5,52.15 2 0 github.com/voi-oss/svc/logger.go:48.19,50.6 1 0 github.com/voi-oss/svc/logger.go:59.66,60.28 1 0 github.com/voi-oss/svc/logger.go:60.28,62.3 1 0 -github.com/voi-oss/svc/logger.go:67.55,68.28 1 15 -github.com/voi-oss/svc/logger.go:68.28,76.3 4 15 +github.com/voi-oss/svc/logger.go:67.55,68.28 1 17 +github.com/voi-oss/svc/logger.go:68.28,76.3 4 17 github.com/voi-oss/svc/logger.go:81.54,82.28 1 2 github.com/voi-oss/svc/logger.go:82.28,90.3 4 2 github.com/voi-oss/svc/logger.go:95.72,96.28 1 2 github.com/voi-oss/svc/logger.go:96.28,106.3 5 2 github.com/voi-oss/svc/logger.go:111.76,112.28 1 2 github.com/voi-oss/svc/logger.go:112.28,120.3 4 2 -github.com/voi-oss/svc/logger.go:123.75,125.16 2 21 -github.com/voi-oss/svc/logger.go:128.2,129.16 2 21 -github.com/voi-oss/svc/logger.go:133.2,138.12 5 21 +github.com/voi-oss/svc/logger.go:123.75,125.16 2 23 +github.com/voi-oss/svc/logger.go:128.2,129.16 2 23 +github.com/voi-oss/svc/logger.go:133.2,138.12 5 23 github.com/voi-oss/svc/logger.go:125.16,127.3 1 0 github.com/voi-oss/svc/logger.go:129.16,131.3 1 0 github.com/voi-oss/svc/options.go:19.56,20.28 1 0 @@ -104,8 +44,8 @@ github.com/voi-oss/svc/options.go:38.47,39.28 1 0 github.com/voi-oss/svc/options.go:39.28,42.3 2 0 github.com/voi-oss/svc/options.go:48.36,49.28 1 0 github.com/voi-oss/svc/options.go:49.28,53.3 2 0 -github.com/voi-oss/svc/options.go:58.41,59.28 1 2 -github.com/voi-oss/svc/options.go:59.28,64.3 3 2 +github.com/voi-oss/svc/options.go:58.41,59.28 1 4 +github.com/voi-oss/svc/options.go:59.28,64.3 3 4 github.com/voi-oss/svc/options.go:68.27,69.28 1 0 github.com/voi-oss/svc/options.go:69.28,79.56 3 0 github.com/voi-oss/svc/options.go:83.3,83.13 1 0 @@ -114,10 +54,10 @@ github.com/voi-oss/svc/options.go:89.34,90.28 1 0 github.com/voi-oss/svc/options.go:90.28,97.3 2 0 github.com/voi-oss/svc/options.go:102.33,103.28 1 0 github.com/voi-oss/svc/options.go:103.28,119.3 12 0 -github.com/voi-oss/svc/options.go:124.27,125.28 1 2 -github.com/voi-oss/svc/options.go:125.28,127.77 1 2 -github.com/voi-oss/svc/options.go:154.3,154.78 1 2 -github.com/voi-oss/svc/options.go:176.3,176.13 1 2 +github.com/voi-oss/svc/options.go:124.27,125.28 1 4 +github.com/voi-oss/svc/options.go:125.28,127.77 1 4 +github.com/voi-oss/svc/options.go:154.3,154.78 1 4 +github.com/voi-oss/svc/options.go:176.3,176.13 1 4 github.com/voi-oss/svc/options.go:127.77,129.32 2 2 github.com/voi-oss/svc/options.go:136.4,136.22 1 2 github.com/voi-oss/svc/options.go:142.4,144.18 3 1 @@ -127,11 +67,71 @@ github.com/voi-oss/svc/options.go:130.33,131.39 1 2 github.com/voi-oss/svc/options.go:131.39,133.7 1 1 github.com/voi-oss/svc/options.go:136.22,140.5 3 1 github.com/voi-oss/svc/options.go:144.18,147.5 2 0 -github.com/voi-oss/svc/options.go:154.78,156.32 2 0 -github.com/voi-oss/svc/options.go:163.4,163.21 1 0 -github.com/voi-oss/svc/options.go:156.32,157.35 1 0 -github.com/voi-oss/svc/options.go:157.35,158.41 1 0 -github.com/voi-oss/svc/options.go:158.41,160.7 1 0 -github.com/voi-oss/svc/options.go:163.21,166.19 3 0 -github.com/voi-oss/svc/options.go:170.5,172.22 3 0 +github.com/voi-oss/svc/options.go:154.78,156.32 2 2 +github.com/voi-oss/svc/options.go:163.4,163.21 1 2 +github.com/voi-oss/svc/options.go:156.32,157.35 1 4 +github.com/voi-oss/svc/options.go:157.35,158.41 1 4 +github.com/voi-oss/svc/options.go:158.41,160.7 1 1 +github.com/voi-oss/svc/options.go:163.21,166.19 3 1 +github.com/voi-oss/svc/options.go:170.5,172.22 3 1 github.com/voi-oss/svc/options.go:166.19,169.6 2 0 +github.com/voi-oss/svc/svc.go:54.62,70.51 2 15 +github.com/voi-oss/svc/svc.go:74.2,78.25 3 15 +github.com/voi-oss/svc/svc.go:84.2,84.15 1 15 +github.com/voi-oss/svc/svc.go:70.51,72.3 1 0 +github.com/voi-oss/svc/svc.go:78.25,79.30 1 16 +github.com/voi-oss/svc/svc.go:79.30,81.4 1 0 +github.com/voi-oss/svc/svc.go:89.48,90.42 1 13 +github.com/voi-oss/svc/svc.go:93.2,93.32 1 13 +github.com/voi-oss/svc/svc.go:96.2,96.30 1 13 +github.com/voi-oss/svc/svc.go:99.2,99.31 1 13 +github.com/voi-oss/svc/svc.go:105.2,106.21 2 13 +github.com/voi-oss/svc/svc.go:90.42,92.3 1 0 +github.com/voi-oss/svc/svc.go:93.32,95.3 1 0 +github.com/voi-oss/svc/svc.go:96.30,98.3 1 4 +github.com/voi-oss/svc/svc.go:99.31,101.3 1 0 +github.com/voi-oss/svc/svc.go:101.8,103.3 1 13 +github.com/voi-oss/svc/svc.go:109.57,112.2 2 0 +github.com/voi-oss/svc/svc.go:116.21,119.15 2 7 +github.com/voi-oss/svc/svc.go:128.2,128.38 1 7 +github.com/voi-oss/svc/svc.go:138.2,140.33 3 7 +github.com/voi-oss/svc/svc.go:151.2,153.9 2 7 +github.com/voi-oss/svc/svc.go:119.15,125.3 5 6 +github.com/voi-oss/svc/svc.go:128.38,131.54 3 13 +github.com/voi-oss/svc/svc.go:135.3,135.60 1 13 +github.com/voi-oss/svc/svc.go:131.54,134.4 2 0 +github.com/voi-oss/svc/svc.go:140.33,142.34 2 13 +github.com/voi-oss/svc/svc.go:142.34,144.34 2 13 +github.com/voi-oss/svc/svc.go:144.34,147.5 2 1 +github.com/voi-oss/svc/svc.go:154.21,155.40 1 1 +github.com/voi-oss/svc/svc.go:158.3,158.59 1 1 +github.com/voi-oss/svc/svc.go:159.26,160.69 1 1 +github.com/voi-oss/svc/svc.go:161.30,162.45 1 4 +github.com/voi-oss/svc/svc.go:155.40,157.4 1 0 +github.com/voi-oss/svc/svc.go:171.26,173.2 1 1 +github.com/voi-oss/svc/svc.go:176.39,177.16 1 0 +github.com/voi-oss/svc/svc.go:184.2,184.10 1 0 +github.com/voi-oss/svc/svc.go:177.16,178.34 1 0 +github.com/voi-oss/svc/svc.go:181.3,182.13 2 0 +github.com/voi-oss/svc/svc.go:178.34,179.14 1 0 +github.com/voi-oss/svc/svc.go:188.36,190.2 1 0 +github.com/voi-oss/svc/svc.go:192.34,198.12 4 6 +github.com/voi-oss/svc/svc.go:213.2,214.41 2 6 +github.com/voi-oss/svc/svc.go:198.12,201.45 3 6 +github.com/voi-oss/svc/svc.go:201.45,202.28 1 11 +github.com/voi-oss/svc/svc.go:202.28,204.41 2 11 +github.com/voi-oss/svc/svc.go:209.5,209.67 1 11 +github.com/voi-oss/svc/svc.go:204.41,208.6 1 0 +github.com/voi-oss/svc/svc.go:217.60,218.9 1 6 +github.com/voi-oss/svc/svc.go:219.29,219.29 0 6 +github.com/voi-oss/svc/svc.go:220.23,220.23 0 0 +github.com/voi-oss/svc/svc.go:224.58,226.12 2 13 +github.com/voi-oss/svc/svc.go:230.2,230.10 1 13 +github.com/voi-oss/svc/svc.go:226.12,229.3 2 13 +github.com/voi-oss/svc/svc.go:233.81,235.30 2 12 +github.com/voi-oss/svc/svc.go:235.30,236.31 1 0 +github.com/voi-oss/svc/svc.go:236.31,240.4 2 0 +github.com/voi-oss/svc/svc.go:240.9,242.4 1 0 +github.com/voi-oss/svc/svc.go:246.70,247.25 1 0 +github.com/voi-oss/svc/svc.go:250.2,250.30 1 0 +github.com/voi-oss/svc/svc.go:247.25,249.3 1 0 diff --git a/options_test.go b/options_test.go index 4ff60ec..cae524b 100644 --- a/options_test.go +++ b/options_test.go @@ -19,7 +19,7 @@ func TestAlive(t *testing.T) { expectedCode int }{ { - name: "return status ok when no error", + name: "should return status ok when no error", givenError: nil, @@ -46,7 +46,7 @@ func TestAlive(t *testing.T) { return nil }, InitFunc: func(*zap.Logger) error { return nil }, - aliveFunc: func() error { + HealthyFunc: func() error { return tc.givenError }, } @@ -58,12 +58,65 @@ func TestAlive(t *testing.T) { go s.Run() - req := httptest.NewRequest("GET", "/live", nil) + req := httptest.NewRequest("GET", "/ready", nil) rec := httptest.NewRecorder() s.Router.ServeHTTP(rec, req) assert.Equal(t, tc.expectedCode, rec.Code) }) + } +} + +func TestHealthy(t *testing.T) { + + tests := []struct { + name string + givenError error + expectedCode int + }{ + { + name: "should return status ok when no error", + + givenError: nil, + expectedCode: 200, + }, + { + name: "should return status not available when an error", + + givenError: fmt.Errorf("internal error, restart container"), + + expectedCode: 503, + }, } + for _, tt := range tests { + tc := tt + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + dummyWorker := &WorkerMock{ + RunFunc: func() error { + return nil + }, + TerminateFunc: func() error { + return nil + }, + InitFunc: func(*zap.Logger) error { return nil }, + AliveFunc: func() error { + return tc.givenError + }, + } + + s, err := New("dummy-service", "v0.0.0", WithHealthz(), WithHTTPServer("9090")) + require.NoError(t, err) + + s.AddWorker("dummy-worker", dummyWorker) + + go s.Run() + + req := httptest.NewRequest("GET", "/live", nil) + rec := httptest.NewRecorder() + s.Router.ServeHTTP(rec, req) + assert.Equal(t, tc.expectedCode, rec.Code) + }) + } } diff --git a/svc_test.go b/svc_test.go index af59089..4d7d57b 100644 --- a/svc_test.go +++ b/svc_test.go @@ -112,7 +112,8 @@ type WorkerMock struct { InitFunc func(*zap.Logger) error RunFunc func() error TerminateFunc func() error - aliveFunc func() error + AliveFunc func() error + HealthyFunc func() error } func (w *WorkerMock) Init(l *zap.Logger) error { @@ -136,8 +137,15 @@ func (w *WorkerMock) Terminate() error { } func (w *WorkerMock) Alive() error { - if w.aliveFunc == nil { - panic("WorkerMock: Alive was called but aliveFunc was not mocked!") + if w.AliveFunc == nil { + panic("WorkerMock: Alive was called but AliveFunc was not mocked!") } - return w.aliveFunc() + return w.AliveFunc() +} + +func (w *WorkerMock) Healthy() error { + if w.HealthyFunc == nil { + panic("WorkerMock: Healthy was called but HealthyFunc was not mocked!") + } + return w.HealthyFunc() } From 73a470d182ad1d3c01207dd3fb636cb65de1d3b5 Mon Sep 17 00:00:00 2001 From: Ignat Harczuk Date: Tue, 1 Mar 2022 14:28:10 +0100 Subject: [PATCH 4/8] chore: add example of liveliness probe --- examples/liveliness/main.go | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 examples/liveliness/main.go diff --git a/examples/liveliness/main.go b/examples/liveliness/main.go new file mode 100644 index 0000000..61c2554 --- /dev/null +++ b/examples/liveliness/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "time" + + "github.com/voi-oss/svc" + "go.uber.org/zap" +) + +var _ svc.Worker = (*dummyWorker)(nil) + +type dummyWorker struct { + state int +} + +func (d *dummyWorker) Init(*zap.Logger) error { return nil } +func (d *dummyWorker) Terminate() error { return nil } +func (d *dummyWorker) Run() error { + + time.Sleep(1 * time.Second) + d.state = 1 + select {} + +} +func (d *dummyWorker) Alive() error { + if d.state == 1 { + return fmt.Errorf("service not well, please restart me") + } + return nil +} + +func main() { + s, err := svc.New("minimal-service", "1.0.0", svc.WithHTTPServer("9090"), svc.WithHealthz()) + svc.MustInit(s, err) + + w := &dummyWorker{ + state: 0, + } + s.AddWorker("dummy-worker", w) + + s.Run() +} From 74e5eed2b80afac97b5e201e7fff5b6a647aa015 Mon Sep 17 00:00:00 2001 From: Ignat Harczuk Date: Tue, 1 Mar 2022 14:48:59 +0100 Subject: [PATCH 5/8] chore: fix linting --- options_test.go | 2 ++ svc_test.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/options_test.go b/options_test.go index cae524b..004c7b5 100644 --- a/options_test.go +++ b/options_test.go @@ -11,6 +11,7 @@ import ( "go.uber.org/zap" ) +// nolint: dupl func TestAlive(t *testing.T) { tests := []struct { @@ -66,6 +67,7 @@ func TestAlive(t *testing.T) { } } +// nolint: dupl func TestHealthy(t *testing.T) { tests := []struct { diff --git a/svc_test.go b/svc_test.go index 4d7d57b..a9c36c0 100644 --- a/svc_test.go +++ b/svc_test.go @@ -113,7 +113,7 @@ type WorkerMock struct { RunFunc func() error TerminateFunc func() error AliveFunc func() error - HealthyFunc func() error + HealthyFunc func() error } func (w *WorkerMock) Init(l *zap.Logger) error { From 0d83abd0ed368f6573f54d34ff26b80d60ed7dda Mon Sep 17 00:00:00 2001 From: Ignat Harczuk Date: Wed, 2 Mar 2022 08:23:08 +0100 Subject: [PATCH 6/8] fix: flip setting header and writing header in liveliness handler --- options.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options.go b/options.go index dec1d14..b7f1809 100644 --- a/options.go +++ b/options.go @@ -145,8 +145,8 @@ func WithHealthz() Option { http.Error(w, err.Error(), http.StatusInternalServerError) return } - w.WriteHeader(http.StatusServiceUnavailable) w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusServiceUnavailable) _, _ = w.Write(b) }) From 2d43f0664105bce489fd5f7644db44bf84a711b1 Mon Sep 17 00:00:00 2001 From: Ignat Harczuk Date: Wed, 2 Mar 2022 08:24:01 +0100 Subject: [PATCH 7/8] chore: irrelevant go import --- options_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/options_test.go b/options_test.go index 004c7b5..0026d49 100644 --- a/options_test.go +++ b/options_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "go.uber.org/zap" ) From 1f601c10f92c9aefcdc1768eeaf8827c8bec64e6 Mon Sep 17 00:00:00 2001 From: Ignat Harczuk Date: Wed, 2 Mar 2022 12:06:49 +0100 Subject: [PATCH 8/8] fix: change test name to be more clear what the handler is for --- options_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options_test.go b/options_test.go index 0026d49..9207a55 100644 --- a/options_test.go +++ b/options_test.go @@ -28,7 +28,7 @@ func TestAlive(t *testing.T) { { name: "should return status not available when an error", - givenError: fmt.Errorf("internal error, restart container"), + givenError: fmt.Errorf("internal error, stop taking traffic until ready again"), expectedCode: 503, },