백업 테이블 운영
This commit is contained in:
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMMDBPath = "/data/GeoLite2-City.mmdb"
|
||||
defaultMMDBPath = "/initial_data/GeoLite2-City.mmdb"
|
||||
defaultSchema = "geoip"
|
||||
defaultLoaderTimeout = 30 * time.Minute
|
||||
)
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
"geoip-rest/internal/geo"
|
||||
"geoip-rest/internal/schedule"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultPort = "8080"
|
||||
defaultDBPath = "/data/GeoLite2-City.mmdb"
|
||||
defaultDBPath = "/initial_data/GeoLite2-City.mmdb"
|
||||
defaultCron = ""
|
||||
defaultScript = "./scripts/dump_and_import.sh"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -87,6 +92,14 @@ func main() {
|
||||
log.Printf("using mmdb path %s", dbPath)
|
||||
}
|
||||
|
||||
stopScheduler := maybeStartScheduler()
|
||||
defer func() {
|
||||
if stopScheduler != nil {
|
||||
ctx := stopScheduler()
|
||||
<-ctx.Done()
|
||||
}
|
||||
}()
|
||||
|
||||
if err := app.Listen(":" + port); err != nil {
|
||||
log.Fatalf("server stopped: %v", err)
|
||||
}
|
||||
@@ -106,3 +119,33 @@ func sanitizeDBURL(raw string) string {
|
||||
}
|
||||
return u.Redacted()
|
||||
}
|
||||
|
||||
func maybeStartScheduler() func() context.Context {
|
||||
cronExpr := env("USER_PROGRAM_CRON", defaultCron)
|
||||
if cronExpr == "" {
|
||||
return nil
|
||||
}
|
||||
script := env("USER_PROGRAM_SCRIPT", defaultScript)
|
||||
|
||||
sched, err := schedule.Start(schedule.Config{
|
||||
CronExpr: cronExpr,
|
||||
ScriptPath: script,
|
||||
Logger: log.Default(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("scheduler not started (error=%v)", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return func() context.Context {
|
||||
ctx := sched.Stop()
|
||||
timer := time.NewTimer(2 * time.Second)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
timer.Stop()
|
||||
return ctx
|
||||
case <-timer.C:
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
59
cmd/user_program_import/main.go
Normal file
59
cmd/user_program_import/main.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
|
||||
"geoip-rest/internal/importer"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultCSVPath = "./initial_data/user_program_info_init_20251208.csv"
|
||||
defaultUpdateDir = "./update_data"
|
||||
defaultTimeout = 10 * time.Minute
|
||||
defaultSchema = "public"
|
||||
defaultLogDir = "./log"
|
||||
targetTableName = "user_program_info_replica"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dbURL := os.Getenv("DATABASE_URL")
|
||||
if dbURL == "" {
|
||||
log.Fatal("DATABASE_URL is required")
|
||||
}
|
||||
|
||||
csvPath := env("USER_PROGRAM_INFO_CSV", defaultCSVPath)
|
||||
updateDir := env("USER_PROGRAM_UPDATE_DIR", defaultUpdateDir)
|
||||
schema := env("USER_PROGRAM_INFO_SCHEMA", defaultSchema)
|
||||
logDir := env("USER_PROGRAM_IMPORT_LOG_DIR", defaultLogDir)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
conn, err := pgx.Connect(ctx, dbURL)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to connect to database: %v", err)
|
||||
}
|
||||
defer conn.Close(context.Background())
|
||||
|
||||
if err := importer.EnsureUserProgramReplica(ctx, conn, csvPath, schema, logDir); err != nil {
|
||||
log.Fatalf("failed to ensure %s table: %v", targetTableName, err)
|
||||
}
|
||||
|
||||
if err := importer.ImportUserProgramUpdates(ctx, conn, updateDir, schema, logDir); err != nil {
|
||||
log.Fatalf("failed to import updates from %s: %v", updateDir, err)
|
||||
}
|
||||
|
||||
log.Printf("%s is ready in schema %s using data from %s (updates: %s)", targetTableName, schema, csvPath, updateDir)
|
||||
}
|
||||
|
||||
func env(key, fallback string) string {
|
||||
if val := os.Getenv(key); val != "" {
|
||||
return val
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
Reference in New Issue
Block a user