86 lines
2.9 KiB
Go
86 lines
2.9 KiB
Go
package runtime
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
|
|
"git.sendico.io/tech/sxchnge/product/app/api"
|
|
amr "git.sendico.io/tech/sxchnge/product/app/health"
|
|
"git.sendico.io/tech/sxchnge/product/app/health/status"
|
|
httptransport "git.sendico.io/tech/sxchnge/product/app/http"
|
|
"git.sendico.io/tech/sxchnge/product/app/urls"
|
|
"git.sendico.io/tech/sxchnge/product/sessions/browser"
|
|
"git.sendico.io/tech/sxchnge/shared/database"
|
|
"git.sendico.io/tech/sxchnge/shared/errors"
|
|
"git.sendico.io/tech/sxchnge/shared/logging"
|
|
"git.sendico.io/tech/sxchnge/shared/service"
|
|
"github.com/go-chi/chi/v5"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func CreateAPI(
|
|
ctx context.Context,
|
|
logger mlogger.Logger,
|
|
config *api.Config,
|
|
db db.Factory,
|
|
rootRouter, apiRouter *chi.Mux,
|
|
debug bool,
|
|
runtime api.RuntimeConfig,
|
|
) (_ mservice.MicroService, result error) {
|
|
if config == nil || config.Mw == nil {
|
|
return nil, merrors.InvalidArgument("API middleware configuration is required")
|
|
}
|
|
endpoint := os.Getenv(config.Mw.EndPointEnv)
|
|
mounts, err := resolveMounts(config.Versions, endpoint, runtime.Versions)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if runtime.Bootstrap == nil {
|
|
return nil, merrors.InvalidArgument("runtime bootstrap is required")
|
|
}
|
|
// Resolve every URL before opening resources or publishing routes.
|
|
scopes := make([]api.Scope, len(mounts))
|
|
for i, mount := range mounts {
|
|
urls, err := domainprovider.CreateDomainProvider(logger, os.Getenv(config.Mw.DomainEnv), os.Getenv(config.Mw.APIProtocolEnv), mount.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
scopes[i] = api.Scope{Router: chi.NewRouter(), Mount: mount.Path, URLs: urls, Logger: logger.With(zap.String("api_version", mount.Version), zap.String("mount", mount.Path))}
|
|
scopes[i].Router.Use(browser.Scope(mount.Path))
|
|
}
|
|
a := &instance{logger: logger.Named("api").With(zap.String("runtime", runtime.RuntimeName()))}
|
|
defer func() {
|
|
if result != nil {
|
|
if err := a.Finish(context.Background()); err != nil {
|
|
a.logger.Warn("Failed startup resource cleanup", zap.Error(err))
|
|
}
|
|
}
|
|
}()
|
|
a.mw, err = httptransport.CreateMiddleware(logger, apiRouter, config.Mw, endpoint, debug)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
deps, cleanup, err := runtime.Bootstrap(ctx, a.logger, config, db)
|
|
a.cleanup = cleanup
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i, mount := range mounts {
|
|
if err := runtime.Versions[mount.Version](scopes[i], deps); err != nil {
|
|
return nil, merrors.OpaqueWrap(merrors.ErrInternal, err, "API version installation failed: "+mount.Version)
|
|
}
|
|
}
|
|
// Attach only after every installer succeeds.
|
|
for i, mount := range mounts {
|
|
apiRouter.Mount(mount.Path, scopes[i].Router)
|
|
scopes[i].Logger.Info("API version installed")
|
|
}
|
|
a.health, err = amr.NewHealthRouter(a.logger, rootRouter, endpoint)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
a.logger.Info("API installation complete", zap.Int("versions", len(mounts)))
|
|
a.health.SetStatus(health.SSRunning)
|
|
return a, nil
|
|
}
|