func Serve()

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
}