in pkg/server/server.go [41:155]
func Serve(dbUrl string, natsUrl string) error {
if dbUrl == "" {
dbUrl = DefaultDbUrl
}
dbpool, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL"))
dbpool.Config().MaxConns = 10
if err != nil {
return err
}
statsServer := &StatsServer{
dbUrl: dbUrl,
}
defer func() {
statsServer.nameToDbPool.Range(func(_, pool any) bool {
p, ok := pool.(*puddle.Pool[*ch.Client])
if ok {
p.Close()
}
return true
})
}()
cacheManager, err := NewResponseCacheManager()
if err != nil {
return err
}
router := chi.NewRouter()
disposer := util.NewDisposer()
defer disposer.Dispose()
if natsUrl != "" {
err = listenNats(cacheManager, natsUrl, disposer)
if err != nil {
return err
}
} else {
slog.Info("no nats server configured")
}
router.Use(middleware.AllowContentType("application/octet-stream", "application/json"))
router.Use(cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "DELETE"},
AllowedHeaders: []string{"*"},
MaxAge: 50,
}).Handler)
router.Use(middleware.Heartbeat("/health-check"))
router.Use(middleware.Recoverer)
router.Route("/api/meta", func(r chi.Router) {
r.Route("/accidents", func(r chi.Router) {
r.Post("/*", meta.CreatePostAccidentRequestHandler(dbpool))
r.Delete("/*", meta.CreateDeleteAccidentRequestHandler(dbpool))
r.Get("/*", meta.CreateGetAccidentByIdHandler(dbpool))
})
r.Post("/getAccidents*", meta.CreateGetManyAccidentsRequestHandler(dbpool))
r.Get("/description*", meta.CreateGetDescriptionRequestHandler(dbpool))
r.Post("/accidentsAroundDate*", meta.CreateGetAccidentsAroundDateRequestHandler(dbpool))
r.Post("/missingData", meta.CreatePostMissingDataRequestHandler(dbpool))
r.Route("/youtrack", func(r chi.Router) {
r.Post("/createIssue", meta.CreatePostCreateIssueByAccident(dbpool))
r.Post("/uploadAttachments", meta.CreatePostUploadAttachmentsToIssue())
})
r.Route("/teamcity", func(r chi.Router) {
r.Post("/startBisect", meta.CreatePostStartBisect())
r.Get("/changes", meta.HandleGetTeamCityChanges())
r.Get("/buildType", meta.HandleGetTeamCityBuildType())
r.Get("/buildCounter", meta.HandleGetTeamCityBuildCounter())
r.Get("/buildInfo", meta.HandleGetTeamCityBuildInfo())
})
})
router.Route("/api/auth", func(r chi.Router) {
r.Route("/userinfo", func(r chi.Router) {
r.Get("/*", auth.CreateGetUserInfoHandler())
})
})
router.Post("/api/evaluateMetric*", statsServer.CreateProcessMetricDataHandler())
router.Group(func(r chi.Router) {
compressor := middleware.NewCompressor(5)
compressor.SetEncoder("br", func(w io.Writer, level int) io.Writer {
return brotli.NewWriterV2(w, level)
})
r.Use(compressor.Handler)
r.Route("/api/", func(r chi.Router) {
r.Route("/v1", func(r chi.Router) {
r.Handle("/meta/measure", cacheManager.CreateHandler(statsServer.handleMetaMeasureRequest))
r.Handle("/load/*", cacheManager.CreateHandler(statsServer.handleLoadRequest))
})
r.Handle("/q/*", cacheManager.CreateHandler(statsServer.handleLoadRequestV2))
r.Handle("/highlightingPasses*", cacheManager.CreateHandler(statsServer.getDistinctHighlightingPasses))
r.Handle("/compareBranches*", cacheManager.CreateHandler(statsServer.getBranchComparison))
r.Handle("/compareModes*", cacheManager.CreateHandler(statsServer.getModeComparison))
r.Handle("/zstd-dictionary/*", &CachingHandler{
handler: func(_ *http.Request) (*bytebufferpool.ByteBuffer, bool, error) {
return &bytebufferpool.ByteBuffer{B: util.ZstdDictionary}, false, nil
},
manager: cacheManager,
})
})
})
server := listenAndServe(env.Get("SERVER_PORT", "9044"), router)
slog.Info("started", "server", server.Addr, "clickhouse", dbUrl, "nats", natsUrl)
waitUntilTerminated(server, 1*time.Minute)
return nil
}