Add monitoring service and database schema

- Implement monitoring service with heartbeat, lease tasks, resume tasks, and task result handling.
- Create monitoring time utilities for business date calculations.
- Add unit tests for date window resolution and business day handling.
- Define database schema for monitoring-related tables including quotas, daily reports, and task management.
- Establish migration scripts for creating and dropping monitoring tables.
This commit is contained in:
2026-04-12 09:56:18 +08:00
parent 9b4dd09780
commit 6066f43a7d
67 changed files with 16312 additions and 125 deletions
+35
View File
@@ -15,6 +15,7 @@ import (
"github.com/geo-platform/tenant-api/internal/shared/cache"
"github.com/geo-platform/tenant-api/internal/shared/config"
"github.com/geo-platform/tenant-api/internal/shared/llm"
"github.com/geo-platform/tenant-api/internal/shared/messaging/rabbitmq"
"github.com/geo-platform/tenant-api/internal/shared/middleware"
"github.com/geo-platform/tenant-api/internal/shared/objectstorage"
"github.com/geo-platform/tenant-api/internal/shared/observability"
@@ -29,6 +30,8 @@ type App struct {
Config *config.Config
Logger *zap.Logger
DB *pgxpool.Pool
MonitoringDB *pgxpool.Pool
RabbitMQ *rabbitmq.Client
Redis *goredis.Client
Engine *gin.Engine
JWT *auth.Manager
@@ -60,12 +63,27 @@ func New(configPath string) (*App, error) {
return nil, fmt.Errorf("init postgres: %w", err)
}
monitoringPool, err := postgres.NewPool(ctx, cfg.MonitoringDatabase)
if err != nil {
pool.Close()
return nil, fmt.Errorf("init monitoring postgres: %w", err)
}
rdb, err := redis.NewClient(ctx, cfg.Redis)
if err != nil {
pool.Close()
monitoringPool.Close()
return nil, fmt.Errorf("init redis: %w", err)
}
mqClient, err := rabbitmq.New(ctx, cfg.RabbitMQ)
if err != nil {
pool.Close()
monitoringPool.Close()
_ = rdb.Close()
return nil, fmt.Errorf("init rabbitmq: %w", err)
}
jwtMgr := auth.NewManager(cfg.JWT.Secret, cfg.JWT.AccessTTL, cfg.JWT.RefreshTTL)
sessions := auth.NewSessionStore(rdb)
llmClient := llm.New(cfg.LLM)
@@ -84,6 +102,7 @@ func New(configPath string) (*App, error) {
engine.Use(
middleware.Recovery(logger),
middleware.RequestID(),
middleware.Logger(logger),
middleware.CORS(),
)
@@ -95,10 +114,18 @@ func New(configPath string) (*App, error) {
response.Error(c, response.ErrServiceUnavailable(50301, "postgres_unavailable", "database is not reachable"))
return
}
if err := monitoringPool.Ping(c.Request.Context()); err != nil {
response.Error(c, response.ErrServiceUnavailable(50303, "monitoring_postgres_unavailable", "monitoring database is not reachable"))
return
}
if err := rdb.Ping(c.Request.Context()).Err(); err != nil {
response.Error(c, response.ErrServiceUnavailable(50302, "redis_unavailable", "redis is not reachable"))
return
}
if err := mqClient.Ping(c.Request.Context()); err != nil {
response.Error(c, response.ErrServiceUnavailable(50304, "rabbitmq_unavailable", "rabbitmq is not reachable"))
return
}
response.Success(c, gin.H{"status": "ready"})
})
@@ -106,6 +133,8 @@ func New(configPath string) (*App, error) {
Config: cfg,
Logger: logger,
DB: pool,
MonitoringDB: monitoringPool,
RabbitMQ: mqClient,
Redis: rdb,
Engine: engine,
JWT: jwtMgr,
@@ -129,6 +158,12 @@ func (a *App) Close() {
cancel()
}
a.DB.Close()
if a.MonitoringDB != nil {
a.MonitoringDB.Close()
}
if a.RabbitMQ != nil {
_ = a.RabbitMQ.Close()
}
_ = a.Redis.Close()
_ = a.Logger.Sync()
}