2026-08-03 23:51:21 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2026-09-09 16:42:21 +08:00
|
|
|
"context"
|
|
|
|
|
"errors"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os"
|
|
|
|
|
"os/signal"
|
|
|
|
|
"syscall"
|
|
|
|
|
"time"
|
2026-08-03 23:51:21 +08:00
|
|
|
|
|
|
|
|
"git.apinb.com/bsm-sdk/core/infra"
|
|
|
|
|
"git.apinb.com/bsm-sdk/core/middleware"
|
|
|
|
|
"git.apinb.com/ops/files/internal/config"
|
|
|
|
|
"git.apinb.com/ops/files/internal/impl"
|
|
|
|
|
"git.apinb.com/ops/files/internal/jobs"
|
|
|
|
|
"git.apinb.com/ops/files/internal/models"
|
|
|
|
|
"git.apinb.com/ops/files/internal/routers"
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const ServiceKey = "Files"
|
|
|
|
|
|
|
|
|
|
func main() {
|
2026-09-09 16:42:21 +08:00
|
|
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
|
|
|
|
defer stop()
|
|
|
|
|
|
2026-08-03 23:51:21 +08:00
|
|
|
config.New(ServiceKey)
|
|
|
|
|
impl.NewImpl()
|
2026-09-09 16:42:21 +08:00
|
|
|
if err := models.RequireSchemaVersion(impl.DBService, "files"); err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
if err := models.RequireStorageProvider(impl.DBService, impl.StorageService.Provider()); err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
if err := jobs.StartPendingUploadCleanup(ctx); err != nil {
|
|
|
|
|
if closeErr := impl.Close(); closeErr != nil {
|
|
|
|
|
panic(errors.Join(err, closeErr))
|
|
|
|
|
}
|
2026-08-03 23:51:21 +08:00
|
|
|
panic(err)
|
|
|
|
|
}
|
2026-09-09 16:42:21 +08:00
|
|
|
if err := jobs.StartIntegrity(ctx); err != nil {
|
|
|
|
|
stop()
|
|
|
|
|
waitCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
|
|
|
waitErr := jobs.Wait(waitCtx)
|
|
|
|
|
cancel()
|
|
|
|
|
if closeErr := impl.Close(); closeErr != nil {
|
|
|
|
|
panic(errors.Join(err, waitErr, closeErr))
|
|
|
|
|
}
|
|
|
|
|
panic(errors.Join(err, waitErr))
|
|
|
|
|
}
|
2026-08-03 23:51:21 +08:00
|
|
|
|
|
|
|
|
app := gin.Default()
|
|
|
|
|
middleware.Mode(app)
|
|
|
|
|
app.Use(middleware.Cors())
|
|
|
|
|
app.Use(gin.Recovery())
|
|
|
|
|
app.HEAD("/", infra.Health)
|
|
|
|
|
routers.Register(ServiceKey, app)
|
|
|
|
|
|
2026-09-09 16:42:21 +08:00
|
|
|
serveErr := serve(ctx, app)
|
|
|
|
|
stop()
|
|
|
|
|
waitCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
|
|
|
waitErr := jobs.Wait(waitCtx)
|
|
|
|
|
cancel()
|
|
|
|
|
closeErr := impl.Close()
|
|
|
|
|
if err := errors.Join(serveErr, waitErr, closeErr); err != nil {
|
2026-08-03 23:51:21 +08:00
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-09-09 16:42:21 +08:00
|
|
|
|
|
|
|
|
func serve(ctx context.Context, app http.Handler) error {
|
|
|
|
|
server := &http.Server{Addr: config.Spec.Addr, Handler: app, ReadHeaderTimeout: 10 * time.Second}
|
|
|
|
|
errCh := make(chan error, 1)
|
|
|
|
|
go func() { errCh <- server.ListenAndServe() }()
|
|
|
|
|
select {
|
|
|
|
|
case err := <-errCh:
|
|
|
|
|
if errors.Is(err, http.ErrServerClosed) {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return err
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
|
|
|
defer cancel()
|
|
|
|
|
return server.Shutdown(shutdownCtx)
|
|
|
|
|
}
|
|
|
|
|
}
|