sync: 同步 v1.0.4 并脱敏配置与镜像

This commit is contained in:
MiFaZhan
2026-10-29 14:36:49 +08:00
parent 743e8e6e6e
commit 2206a393f7
516 changed files with 18119 additions and 2253 deletions
@@ -0,0 +1,18 @@
package tasks
import "testing"
func TestAllFullSyncTaskRegistrations(t *testing.T) {
for name, method := range map[string]string{
"start_traffic_usage_full_sync": "StartTrafficUsageFullSync",
"syns_sim_status_queue": "SynsSimStatusQueue",
"syns_imei_queue": "SynsImeiQueue",
"sync_traffic_usage_daily": "SyncTrafficUsageDaily",
"sync_traffic_usage_monthly": "SyncTrafficUsageMonthly",
"start_traffic_usage_monthly_history": "StartTrafficUsageMonthlyHistory",
} {
if got := GetInnerTaskName(name); got != method {
t.Errorf("task %q registered as %q, want %q", name, got, method)
}
}
}
+26
View File
@@ -0,0 +1,26 @@
package tasks
import (
"context"
"time"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/service"
)
const (
monthlyExpiryJobPeriod = 24 * time.Hour
monthlyExpiryJobTTL = 6 * time.Hour
)
func init() {
RegisterInnerTask("NotifyMonthlyPackageExpiry", "NotifyMonthlyPackageExpiry")
}
// NotifyMonthlyPackageExpiry uses an independent sys_job target and Redis lock.
func (t Task) NotifyMonthlyPackageExpiry() {
t.runWithRedisJobLock(context.Background(), redisJobLockOptions{
InvokeTarget: "NotifyMonthlyPackageExpiry",
Period: monthlyExpiryJobPeriod,
TTL: monthlyExpiryJobTTL,
}, service.SimWarning().NotifyMonthlyExpiry)
}
@@ -0,0 +1,81 @@
package tasks
import (
"os"
"regexp"
"strings"
"testing"
"time"
_ "time/tzdata"
"github.com/robfig/cron/v3"
)
func monthlyExpiryMigration(t *testing.T) string {
t.Helper()
data, err := os.ReadFile("../../resource/migrations/20261014_monthly_package_expiry_notice.sql")
if err != nil {
t.Fatal(err)
}
return regexp.MustCompile(`(?m)--[^\r\n]*`).ReplaceAllString(string(data), "")
}
func TestMonthlyExpiryDeploymentSchedule(t *testing.T) {
sql := monthlyExpiryMigration(t)
matches := regexp.MustCompile(`'CRON_TZ=[^']+'`).FindString(sql)
if matches == "" {
t.Fatal("migration must specify cron expression")
}
parser := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
schedule, err := parser.Parse(strings.Trim(matches, "'"))
if err != nil {
t.Fatalf("deployment expression must parse with the real scheduler: %v", err)
}
for _, tc := range []struct{ start, expected string }{
{"2026-10-14T01:00:00Z", "2026-10-15T01:00:00Z"},
{"2026-10-15T01:00:00Z", "2026-11-15T01:00:00Z"},
{"2026-12-15T01:00:00Z", "2027-01-15T01:00:00Z"},
{"2028-02-15T01:00:00Z", "2028-03-15T01:00:00Z"},
} {
start, _ := time.Parse(time.RFC3339, tc.start)
expected, _ := time.Parse(time.RFC3339, tc.expected)
if got := schedule.Next(start); !got.Equal(expected) {
t.Errorf("from %s: got %s, want %s", tc.start, got, expected)
}
}
for _, alias := range []string{"ScanSimExpireCandidateWarning", "scan_sim_expire_candidate_warning"} {
if got := GetInnerTaskName(alias); got != "ScanSimExpireCandidateWarning" {
t.Errorf("existing alias %s no longer registered: %s", alias, got)
}
}
if got := GetInnerTaskName("NotifyMonthlyPackageExpiry"); got != "NotifyMonthlyPackageExpiry" {
t.Errorf("monthly task not registered independently: %s", got)
}
if got, want := jobLockKey("NotifyMonthlyPackageExpiry", time.Date(2026, 10, 15, 9, 0, 0, 0, time.UTC), monthlyExpiryJobPeriod), jobLockKey("scan_sim_expire_candidate_warning", time.Date(2026, 10, 15, 9, 0, 0, 0, time.UTC), warningExpireScanJobPeriod); got == want {
t.Fatal("monthly and legacy tasks must not share the same lock")
}
}
// 只检查迁移脚本结构,不连接数据库或执行 SQL;不替代部署前的 MySQL 验证。
func TestMonthlyExpiryDeploymentInsertOnly(t *testing.T) {
sql := strings.Join(strings.Fields(monthlyExpiryMigration(t)), " ")
if strings.Count(strings.ToUpper(sql), "INSERT INTO SYS_JOB") != 1 {
t.Fatal("migration must insert only one independent sys_job")
}
if regexp.MustCompile(`(?i)\bUPDATE\s+sys_job\b|\bDELETE\s+FROM\s+sys_job\b|\bjob_id\b`).MatchString(sql) {
t.Fatal("migration must not update/delete jobs or provide a generated job_id")
}
for _, required := range []string{
"'NotifyMonthlyPackageExpiry'",
"'CRON_TZ=Asia/Shanghai 0 0 9 15 * *'",
"1, 1, '1'",
"WHERE NOT EXISTS ( SELECT 1 FROM sys_job WHERE invoke_target = 'NotifyMonthlyPackageExpiry' )",
} {
if !strings.Contains(sql, required) {
t.Errorf("migration missing required independent paused job behavior: %q", required)
}
}
if strings.Contains(sql, "ScanSimExpireCandidateWarning") || strings.Contains(sql, "scan_sim_expire_candidate_warning") {
t.Fatal("migration must not touch legacy job targets")
}
}
+3 -3
View File
@@ -7,7 +7,7 @@ import (
)
const (
warningTrafficJobPeriod = 15 * time.Minute
warningTrafficJobPeriod = -time.Second
warningTrafficJobTTL = 45 * time.Minute
warningExpirePreloadJobPeriod = 24 * time.Hour
warningExpirePreloadJobTTL = 6 * time.Hour
@@ -42,7 +42,7 @@ func (t Task) ScanSimWarning() {
func (t Task) ScanSimTrafficWarning() {
t.runWithRedisJobLock(context.Background(), redisJobLockOptions{
InvokeTarget: "scan_sim_traffic_warning",
InvokeTarget: "scan_sim_warning",
Period: warningTrafficJobPeriod,
TTL: warningTrafficJobTTL,
}, service.SimWarning().ScanTraffic)
@@ -50,7 +50,7 @@ func (t Task) ScanSimTrafficWarning() {
func (t Task) ScanSimFlowPoolWarning() {
t.runWithRedisJobLock(context.Background(), redisJobLockOptions{
InvokeTarget: "check_flow_pool_warning",
InvokeTarget: "scan_sim_warning",
Period: warningTrafficJobPeriod,
TTL: warningTrafficJobTTL,
}, service.SimWarning().ScanFlowPool)
@@ -0,0 +1,32 @@
package tasks
import (
"testing"
"time"
)
func TestTrafficUsageMonthlyTaskRegistrations(t *testing.T) {
tests := map[string]string{
"sync_traffic_usage_monthly": "SyncTrafficUsageMonthly",
"start_traffic_usage_full_sync": "StartTrafficUsageFullSync",
}
for name, method := range tests {
if actual := GetInnerTaskName(name); actual != method {
t.Fatalf("task %q registered as %q, want %q", name, actual, method)
}
}
}
func TestTrafficUsageJobLockUsesStableActiveScope(t *testing.T) {
first := time.Date(2026, 9, 20, 23, 59, 0, 0, time.Local)
second := first.Add(2 * time.Minute)
if got := jobLockPeriodKey(first, -1); got != "active" {
t.Fatalf("first active key = %q", got)
}
if got := jobLockPeriodKey(second, -1); got != "active" {
t.Fatalf("second active key = %q", got)
}
if jobLockKey("sync_traffic_usage_daily", first, -1) != jobLockKey("sync_traffic_usage_daily", second, -1) {
t.Fatal("active job lock key must remain stable across midnight")
}
}