Skip to content

Commit 157456a

Browse files
committed
chore: replace ifrit with stdlib runner
# Issue `ifrit` (`github.com/tedsuo/ifrit`) is not maintained. # Fix Replace `ifrit` with a small internal `helpers/runner` package built on Go stdlib (`context`, `net/http`, `os/signal`). The package provides the same primitives that `ifrit` did: a `Runner` interface, a `RunFunc` adapter, named `Member` structs, and `StartOrdered` for ordered startup with LIFO graceful shutdown triggered by `SIGINT`/`SIGTERM` or context cancellation. A companion `helpers/runner/testrunner` package replaces `ginkgomon_v2` for tests, offering `Invoke`/`Interrupt`/`Kill` helpers for in-process runners and a `CmdRunner` that starts external binaries and waits for a configurable start-check string in their combined stdout+stderr before signalling ready. All five Go services (`api`, `eventgenerator`, `scalingengine`, `metricsforwarder`, `operator`) and the shared `startup`, `sync`, and `helpers` packages are updated accordingly. `ifrit` is removed from `go.mod`.
1 parent 654fe9b commit 157456a

34 files changed

Lines changed: 860 additions & 2931 deletions

CLAUDE.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@ make generate-fakes # Generate test mocks with Counterfeiter
5757
make generate-openapi-generated-clients-and-servers # Generate OpenAPI clients/servers
5858
```
5959

60+
### Verifying Bigger Changes
61+
62+
Always run these two steps to verify bigger changes (refactors, dependency replacements, new packages):
63+
64+
```bash
65+
make clean check # Clean, lint, build, and run all unit tests (no DB needed)
66+
make integration # Run integration tests (requires PostgreSQL: make start-db first)
67+
```
68+
69+
`make clean check` is the primary gate — it runs a full clean build plus all non-DB unit tests with the race detector. `make integration` catches DB-dependent behaviour and inter-service contracts.
70+
6071
### Deployment
6172
```bash
6273
make mta-deploy # Deploy to Cloud Foundry using MTA

api/brokerserver/broker_server.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import (
1414
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/healthendpoint"
1515
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers"
1616
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/handlers"
17+
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/runner"
1718
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/routes"
1819
"code.cloudfoundry.org/brokerapi/v13"
1920
"code.cloudfoundry.org/brokerapi/v13/domain"
2021
"code.cloudfoundry.org/lager/v3"
2122
"github.com/go-chi/chi/v5"
22-
"github.com/tedsuo/ifrit"
2323
"golang.org/x/crypto/bcrypt"
2424
)
2525

@@ -63,7 +63,7 @@ func (am *AuthMiddleware) authenticate(r *http.Request) bool {
6363
}
6464

6565
type BrokerServer interface {
66-
CreateServer() (ifrit.Runner, error)
66+
CreateServer() (runner.Runner, error)
6767
GetRouter() (*chi.Mux, error)
6868
}
6969

@@ -89,7 +89,7 @@ func NewBrokerServer(logger lager.Logger, conf *config.Config, bindingDB db.Bind
8989
}
9090
}
9191

92-
func (s *brokerServer) CreateServer() (ifrit.Runner, error) {
92+
func (s *brokerServer) CreateServer() (runner.Runner, error) {
9393
router, err := s.GetRouter()
9494
if err != nil {
9595
return nil, err

api/brokerserver/broker_server_suite_test.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,15 @@ import (
1010
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers"
1111
"code.cloudfoundry.org/brokerapi/v13/domain"
1212

13+
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/runner/testrunner"
14+
1315
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/api/brokerserver"
1416
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/api/config"
1517
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/fakes"
1618
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/routes"
1719

1820
"github.com/onsi/gomega/ghttp"
1921

20-
"github.com/tedsuo/ifrit"
21-
"github.com/tedsuo/ifrit/ginkgomon_v2"
22-
2322
"code.cloudfoundry.org/lager/v3"
2423

2524
. "github.com/onsi/ginkgo/v2"
@@ -41,7 +40,7 @@ const (
4140
)
4241

4342
var (
44-
serverProcess ifrit.Process
43+
serverProcess *testrunner.Process
4544
serverUrl *url.URL
4645
httpClient *http.Client
4746
conf *config.Config
@@ -153,7 +152,7 @@ var _ = BeforeSuite(func() {
153152
serverUrl, err = url.Parse("http://localhost:" + strconv.Itoa(port))
154153
Expect(err).NotTo(HaveOccurred())
155154

156-
serverProcess = ginkgomon_v2.Invoke(httpServer)
155+
serverProcess = testrunner.Invoke(httpServer)
157156

158157
httpClient = &http.Client{}
159158

@@ -179,5 +178,5 @@ var _ = AfterSuite(func() {
179178
for _, server := range servers {
180179
server.Close()
181180
}
182-
ginkgomon_v2.Interrupt(serverProcess)
181+
serverProcess.Interrupt()
183182
})

api/cmd/api/main.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import (
1111
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/db"
1212
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/db/sqldb"
1313
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/healthendpoint"
14+
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/runner"
1415
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/ratelimiter"
1516
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/startup"
1617

1718
"code.cloudfoundry.org/lager/v3"
18-
"github.com/tedsuo/ifrit/grouper"
1919
)
2020

2121
func main() {
@@ -72,13 +72,12 @@ func main() {
7272
unifiedServer, err := publicApiServer.CreateCFServer()
7373
startup.ExitOnError(err, logger, "failed to create public api http server")
7474

75-
members := grouper.Members{}
76-
members = append(members,
77-
grouper.Member{Name: "public_api_http_server", Runner: mtlsServer},
78-
grouper.Member{Name: "broker", Runner: brokerHttpServer},
79-
grouper.Member{Name: "health_server", Runner: healthServer},
80-
grouper.Member{Name: "unified_server", Runner: unifiedServer},
81-
)
75+
members := []runner.Member{
76+
{Name: "public_api_http_server", Runner: mtlsServer},
77+
{Name: "broker", Runner: brokerHttpServer},
78+
{Name: "health_server", Runner: healthServer},
79+
{Name: "unified_server", Runner: unifiedServer},
80+
}
8281

8382
err = startup.StartServices(logger, members)
8483
if err != nil {

api/publicapiserver/public_api_server.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ import (
1616
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/cf"
1717
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/db"
1818
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/healthendpoint"
19+
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/runner"
1920
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/ratelimiter"
2021
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/routes"
2122

2223
"code.cloudfoundry.org/lager/v3"
2324
"github.com/gorilla/mux"
2425
"github.com/prometheus/client_golang/prometheus"
25-
"github.com/tedsuo/ifrit"
2626
)
2727

2828
type VarsFunc func(w http.ResponseWriter, r *http.Request, vars map[string]string)
@@ -70,7 +70,7 @@ func NewPublicApiServer(logger lager.Logger, conf *config.Config, policyDB db.Po
7070
}
7171
}
7272

73-
func (s *PublicApiServer) CreateHealthServer() (ifrit.Runner, error) {
73+
func (s *PublicApiServer) CreateHealthServer() (runner.Runner, error) {
7474
if err := s.setupHealthRouter(); err != nil {
7575
return nil, err
7676
}
@@ -89,7 +89,7 @@ func (s *PublicApiServer) setupBrokerRouter() error {
8989
return nil
9090
}
9191

92-
func (s *PublicApiServer) CreateCFServer() (ifrit.Runner, error) {
92+
func (s *PublicApiServer) CreateCFServer() (runner.Runner, error) {
9393
if err := s.setupBrokerRouter(); err != nil {
9494
return nil, err
9595
}
@@ -107,7 +107,7 @@ func (s *PublicApiServer) CreateCFServer() (ifrit.Runner, error) {
107107
return helpers.NewHTTPServer(s.logger.Session("CfServer"), s.conf.CFServer, r)
108108
}
109109

110-
func (s *PublicApiServer) CreateMtlsServer() (ifrit.Runner, error) {
110+
func (s *PublicApiServer) CreateMtlsServer() (runner.Runner, error) {
111111
if err := s.setupApiRoutes(); err != nil {
112112
return nil, err
113113
}

api/publicapiserver/public_api_server_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strings"
88

99
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/api/publicapiserver"
10+
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/runner/testrunner"
1011
internalscalinghistory "code.cloudfoundry.org/app-autoscaler/src/autoscaler/scalingengine/apis/scalinghistory"
1112
"code.cloudfoundry.org/lager/v3/lagertest"
1213

@@ -15,7 +16,6 @@ import (
1516
"github.com/go-chi/chi/v5"
1617
. "github.com/onsi/ginkgo/v2"
1718
. "github.com/onsi/gomega"
18-
"github.com/tedsuo/ifrit/ginkgomon_v2"
1919
)
2020

2121
var _ = Describe("PublicApiServer", func() {
@@ -82,7 +82,7 @@ var _ = Describe("PublicApiServer", func() {
8282
})
8383

8484
AfterEach(func() {
85-
ginkgomon_v2.Interrupt(serverProcess)
85+
serverProcess.Interrupt()
8686
})
8787

8888
Describe("CreateMtlsServer", func() {
@@ -103,7 +103,7 @@ var _ = Describe("PublicApiServer", func() {
103103

104104
httpServer, err := publicApiServer.CreateMtlsServer()
105105
Expect(err).NotTo(HaveOccurred())
106-
serverProcess = ginkgomon_v2.Invoke(httpServer)
106+
serverProcess = testrunner.Invoke(httpServer)
107107
})
108108

109109
Context("when calling health endpoint", func() {
@@ -464,7 +464,7 @@ var _ = Describe("PublicApiServer", func() {
464464

465465
httpServer, err := publicApiServer.CreateHealthServer()
466466
Expect(err).NotTo(HaveOccurred())
467-
serverProcess = ginkgomon_v2.Invoke(httpServer)
467+
serverProcess = testrunner.Invoke(httpServer)
468468
})
469469

470470
It("should succeed", func() {
@@ -491,7 +491,7 @@ var _ = Describe("PublicApiServer", func() {
491491

492492
httpServer, err := publicApiServer.CreateCFServer()
493493
Expect(err).NotTo(HaveOccurred())
494-
serverProcess = ginkgomon_v2.Invoke(httpServer)
494+
serverProcess = testrunner.Invoke(httpServer)
495495
})
496496

497497
Context("when calling info endpoint", func() {

api/publicapiserver/publicapiserver_suite_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ import (
1515
. "github.com/onsi/ginkgo/v2"
1616
. "github.com/onsi/gomega"
1717
"github.com/onsi/gomega/ghttp"
18-
"github.com/tedsuo/ifrit"
1918

2019
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/api"
2120
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/api/config"
2221
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/cf"
2322
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/fakes"
2423
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers"
24+
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/runner/testrunner"
2525
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/models"
2626
)
2727

@@ -41,7 +41,7 @@ const (
4141
)
4242

4343
var (
44-
serverProcess ifrit.Process
44+
serverProcess *testrunner.Process
4545
serverUrl *url.URL
4646
cfServerUrl *url.URL
4747
healthUrl *url.URL

eventgenerator/aggregator/metric_poller_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,7 @@ var _ = Describe("MetricPoller", func() {
7272
It("logs an error", func() {
7373
//TODO this should be a prometheus counter not a log statement check
7474

75-
// Subsequently disabling linting, because there is nothing wrong with using whitespaces
76-
// to separate two multiplicands from the operation-symbol.
77-
// (Actually it is more readable.)
78-
Eventually(logger.Buffer, 10 * time.Second).Should(Say("retrieveMetric Failed")) //nolint
75+
Eventually(logger.Buffer, 10*time.Second).Should(Say("retrieveMetric Failed"))
7976

8077
})
8178

eventgenerator/cmd/eventgenerator/main.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package main
22

33
import (
4-
"os"
4+
"context"
55

66
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/db"
77
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/eventgenerator/aggregator"
@@ -12,14 +12,14 @@ import (
1212
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/healthendpoint"
1313
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers"
1414
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/auth"
15+
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/runner"
1516
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/models"
1617
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/startup"
1718
"github.com/prometheus/client_golang/prometheus"
1819
circuit "github.com/rubyist/circuitbreaker"
1920

2021
"code.cloudfoundry.org/clock"
2122
"code.cloudfoundry.org/lager/v3"
22-
"github.com/tedsuo/ifrit"
2323
)
2424

2525
func main() {
@@ -65,23 +65,23 @@ func main() {
6565
anAggregator, err := aggregator.NewAggregator(logger, clock, conf.Aggregator.AggregatorExecuteInterval, conf.Aggregator.SaveInterval, appMonitorsChan, appManager.GetPolicies, appManager.SaveMetricToCache, conf.DefaultStatWindowSecs, appMetricChan, appMetricDB.DB)
6666
startup.ExitOnError(err, logger, "failed to create Aggregator")
6767

68-
eventGenerator := ifrit.RunFunc(runFunc(appManager, evaluators, evaluationManager, metricPollers, anAggregator))
68+
eventGenerator := runner.RunFunc(runFunc(appManager, evaluators, evaluationManager, metricPollers, anAggregator))
6969

7070
// Server setup
7171
eventgeneratorServer := server.NewServer(logger.Session("http_server"), conf, appMetricDB.DB, policyDb.DB, appManager.QueryAppMetrics, httpStatusCollector)
7272
xm := auth.NewXfccAuthMiddleware(logger, conf.CFServer.XFCC)
7373

7474
// Start services
7575
startup.StartService(logger,
76-
startup.Server("eventGenerator", func() (ifrit.Runner, error) { return eventGenerator, nil }),
76+
startup.Server("eventGenerator", func() (runner.Runner, error) { return eventGenerator, nil }),
7777
startup.Server("https_server", eventgeneratorServer.CreateMtlsServer),
7878
startup.Server("health_server", eventgeneratorServer.CreateHealthServer),
79-
startup.Server("cf_server", func() (ifrit.Runner, error) { return eventgeneratorServer.CreateCFServer(xm) }),
79+
startup.Server("cf_server", func() (runner.Runner, error) { return eventgeneratorServer.CreateCFServer(xm) }),
8080
)
8181
}
8282

83-
func runFunc(appManager *aggregator.AppManager, evaluators []*generator.Evaluator, evaluationManager *generator.AppEvaluationManager, metricPollers []*aggregator.MetricPoller, anAggregator *aggregator.Aggregator) func(signals <-chan os.Signal, ready chan<- struct{}) error {
84-
return func(signals <-chan os.Signal, ready chan<- struct{}) error {
83+
func runFunc(appManager *aggregator.AppManager, evaluators []*generator.Evaluator, evaluationManager *generator.AppEvaluationManager, metricPollers []*aggregator.MetricPoller, anAggregator *aggregator.Aggregator) func(ctx context.Context, ready chan<- struct{}) error {
84+
return func(ctx context.Context, ready chan<- struct{}) error {
8585
appManager.Start()
8686

8787
for _, evaluator := range evaluators {
@@ -96,7 +96,7 @@ func runFunc(appManager *aggregator.AppManager, evaluators []*generator.Evaluato
9696

9797
close(ready)
9898

99-
<-signals
99+
<-ctx.Done()
100100
anAggregator.Stop()
101101
evaluationManager.Stop()
102102
appManager.Stop()

eventgenerator/server/server.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/eventgenerator/aggregator"
1010
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers"
1111
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/auth"
12+
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/helpers/runner"
1213
"go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux"
1314

1415
"code.cloudfoundry.org/app-autoscaler/src/autoscaler/eventgenerator/config"
@@ -18,7 +19,6 @@ import (
1819
"code.cloudfoundry.org/lager/v3"
1920
"github.com/gorilla/mux"
2021
"github.com/prometheus/client_golang/prometheus"
21-
"github.com/tedsuo/ifrit"
2222
)
2323

2424
type VarsFunc func(w http.ResponseWriter, r *http.Request, vars map[string]string)
@@ -69,14 +69,14 @@ func NewServer(logger lager.Logger, conf *config.Config, appMetricDB db.AppMetri
6969
}
7070
}
7171

72-
func (s *Server) CreateHealthServer() (ifrit.Runner, error) {
72+
func (s *Server) CreateHealthServer() (runner.Runner, error) {
7373
if err := s.setupHealthRouter(); err != nil {
7474
return nil, err
7575
}
7676
return helpers.NewHTTPServer(s.logger.Session("HealthServer"), s.conf.Health.ServerConfig, s.healthRouter)
7777
}
7878

79-
func (s *Server) CreateCFServer(am auth.XFCCAuthMiddleware) (ifrit.Runner, error) {
79+
func (s *Server) CreateCFServer(am auth.XFCCAuthMiddleware) (runner.Runner, error) {
8080
eventgenerator := s.createEventGeneratorRoutes()
8181
eventgenerator.Use(am.XFCCAuthenticationMiddleware)
8282

@@ -102,7 +102,7 @@ func (s *Server) setupHealthRouter() error {
102102
return nil
103103
}
104104

105-
func (s *Server) CreateMtlsServer() (ifrit.Runner, error) {
105+
func (s *Server) CreateMtlsServer() (runner.Runner, error) {
106106
eventgenerator := s.createEventGeneratorRoutes()
107107

108108
return helpers.NewHTTPServer(s.logger, s.conf.Server, eventgenerator)

0 commit comments

Comments
 (0)