mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 22:46:38 +08:00
feat(db): split migrations into dialect-specific sqlite and postgres packages
This commit is contained in:
+5
-1
@@ -1,4 +1,5 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE IF NOT EXISTS w_schedules (
|
||||
id BIGINT PRIMARY KEY,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
@@ -15,6 +16,9 @@ CREATE INDEX IF NOT EXISTS idx_w_schedules_is_active ON w_schedules (is_active);
|
||||
INSERT INTO w_schedules (id, name, task_type, cron, payload, is_active, created_at, updated_at)
|
||||
VALUES (1, '系统定期垃圾清理', 'system_cleanup', '0 3 * * *', '{}', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS w_schedules;
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS w_schedules;
|
||||
-- +goose StatementEnd
|
||||
@@ -0,0 +1,24 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE IF NOT EXISTS w_schedules (
|
||||
id BIGINT PRIMARY KEY,
|
||||
name VARCHAR(128) NOT NULL,
|
||||
task_type VARCHAR(64) NOT NULL,
|
||||
cron VARCHAR(64) NOT NULL,
|
||||
payload TEXT,
|
||||
is_active BOOLEAN NOT NULL DEFAULT 1,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_w_schedules_is_active ON w_schedules (is_active);
|
||||
|
||||
-- Seed initial cleanup task
|
||||
INSERT INTO w_schedules (id, name, task_type, cron, payload, is_active, created_at, updated_at)
|
||||
VALUES (1, '系统定期垃圾清理', 'system_cleanup', '0 3 * * *', '{}', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS w_schedules;
|
||||
-- +goose StatementEnd
|
||||
@@ -16,9 +16,10 @@ import (
|
||||
|
||||
"Wavelet/core"
|
||||
"Wavelet/core/contracts"
|
||||
"Wavelet/pkg/config"
|
||||
)
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
//go:embed migrations/*/*.sql
|
||||
var cronMigrations embed.FS
|
||||
|
||||
// Option configures the Asynq cron scheduler driver plugin.
|
||||
@@ -148,7 +149,25 @@ func (p *Plugin) Start(_ context.Context) error {
|
||||
opts.Location = p.location
|
||||
}
|
||||
|
||||
p.scheduler = asynq.NewScheduler(p.redisOpt, opts)
|
||||
opt := p.redisOpt
|
||||
if opt == nil {
|
||||
if RedisOpt != nil {
|
||||
opt = RedisOpt
|
||||
} else {
|
||||
redisCfg := config.Config.Redis
|
||||
addr := "127.0.0.1:6379"
|
||||
if len(redisCfg.Addrs) > 0 && redisCfg.Addrs[0] != "" {
|
||||
addr = redisCfg.Addrs[0]
|
||||
}
|
||||
opt = asynq.RedisClientOpt{
|
||||
Addr: addr,
|
||||
Username: redisCfg.Username,
|
||||
Password: redisCfg.Password,
|
||||
DB: redisCfg.DB,
|
||||
}
|
||||
}
|
||||
}
|
||||
p.scheduler = asynq.NewScheduler(opt, opts)
|
||||
}
|
||||
|
||||
if p.coreCtx != nil && p.coreCtx.Schedules() != nil {
|
||||
|
||||
@@ -5,6 +5,8 @@ package driver_asynq_worker
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"Wavelet/core/extpoints"
|
||||
)
|
||||
|
||||
// TaskParam 任务参数定义
|
||||
@@ -61,30 +63,65 @@ func GetDispatchableTasks() []TaskMeta {
|
||||
return metas
|
||||
}
|
||||
|
||||
// GetTaskMeta 根据任务类型获取元数据
|
||||
func GetTaskMeta(taskType string) *TaskMeta {
|
||||
dispatchableTasksMutex.RLock()
|
||||
defer dispatchableTasksMutex.RUnlock()
|
||||
for _, t := range dispatchableTasks {
|
||||
if t.Type == taskType {
|
||||
copied := t
|
||||
return &copied
|
||||
var (
|
||||
activeTaskRegMutex sync.RWMutex
|
||||
activeTaskReg extpoints.TaskExtension
|
||||
)
|
||||
|
||||
// SetActiveTaskExtension sets the active task extension registry for task resolution.
|
||||
func SetActiveTaskExtension(reg extpoints.TaskExtension) {
|
||||
activeTaskRegMutex.Lock()
|
||||
defer activeTaskRegMutex.Unlock()
|
||||
activeTaskReg = reg
|
||||
}
|
||||
|
||||
func getFromActiveTaskExtension(taskType string) *TaskMeta {
|
||||
activeTaskRegMutex.RLock()
|
||||
defer activeTaskRegMutex.RUnlock()
|
||||
if activeTaskReg == nil {
|
||||
return nil
|
||||
}
|
||||
if td, ok := activeTaskReg.Get(taskType); ok {
|
||||
return &TaskMeta{
|
||||
Type: td.Pattern,
|
||||
Name: td.Pattern,
|
||||
AsynqTask: td.Pattern,
|
||||
Queue: "default",
|
||||
Retryable: td.Retry > 0,
|
||||
MaxRetry: td.Retry,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTaskMetaByAsynqTask 根据 Asynq 任务名称获取元数据
|
||||
func GetTaskMetaByAsynqTask(asynqTask string) *TaskMeta {
|
||||
// GetTaskMeta 根据任务类型获取元数据
|
||||
func GetTaskMeta(taskType string) *TaskMeta {
|
||||
dispatchableTasksMutex.RLock()
|
||||
defer dispatchableTasksMutex.RUnlock()
|
||||
for _, t := range dispatchableTasks {
|
||||
if t.AsynqTask == asynqTask {
|
||||
if t.Type == taskType {
|
||||
copied := t
|
||||
dispatchableTasksMutex.RUnlock()
|
||||
return &copied
|
||||
}
|
||||
}
|
||||
return nil
|
||||
dispatchableTasksMutex.RUnlock()
|
||||
|
||||
return getFromActiveTaskExtension(taskType)
|
||||
}
|
||||
|
||||
// GetTaskMetaByAsynqTask 根据 Asynq 任务名称获取元数据
|
||||
func GetTaskMetaByAsynqTask(asynqTask string) *TaskMeta {
|
||||
dispatchableTasksMutex.RLock()
|
||||
for _, t := range dispatchableTasks {
|
||||
if t.AsynqTask == asynqTask {
|
||||
copied := t
|
||||
dispatchableTasksMutex.RUnlock()
|
||||
return &copied
|
||||
}
|
||||
}
|
||||
dispatchableTasksMutex.RUnlock()
|
||||
|
||||
return getFromActiveTaskExtension(asynqTask)
|
||||
}
|
||||
|
||||
// GetRegisteredAsynqTasks 返回所有已注册的 Asynq 任务名称,以便动态注册路由
|
||||
|
||||
+5
-1
@@ -1,4 +1,5 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE IF NOT EXISTS w_task_executions (
|
||||
id BIGINT PRIMARY KEY,
|
||||
task_id VARCHAR(128) NOT NULL UNIQUE,
|
||||
@@ -23,6 +24,9 @@ CREATE INDEX IF NOT EXISTS idx_w_task_executions_task_type ON w_task_executions
|
||||
CREATE INDEX IF NOT EXISTS idx_w_task_executions_status ON w_task_executions (status);
|
||||
CREATE INDEX IF NOT EXISTS idx_w_task_executions_started_at ON w_task_executions (started_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_w_task_executions_created_at ON w_task_executions (created_at);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS w_task_executions;
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS w_task_executions;
|
||||
-- +goose StatementEnd
|
||||
@@ -0,0 +1,32 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE IF NOT EXISTS w_task_executions (
|
||||
id BIGINT PRIMARY KEY,
|
||||
task_id VARCHAR(128) NOT NULL UNIQUE,
|
||||
task_type VARCHAR(64) NOT NULL,
|
||||
task_name VARCHAR(128),
|
||||
status VARCHAR(32) NOT NULL,
|
||||
retryable BOOLEAN NOT NULL DEFAULT 0,
|
||||
max_retry INTEGER NOT NULL DEFAULT 0,
|
||||
retry_count INTEGER NOT NULL DEFAULT 0,
|
||||
log TEXT,
|
||||
error_message TEXT,
|
||||
result TEXT,
|
||||
started_at DATETIME,
|
||||
finished_at DATETIME,
|
||||
duration BIGINT,
|
||||
payload TEXT,
|
||||
triggered_by VARCHAR(32) NOT NULL DEFAULT 'system',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_w_task_executions_task_type ON w_task_executions (task_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_w_task_executions_status ON w_task_executions (status);
|
||||
CREATE INDEX IF NOT EXISTS idx_w_task_executions_started_at ON w_task_executions (started_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_w_task_executions_created_at ON w_task_executions (created_at);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS w_task_executions;
|
||||
-- +goose StatementEnd
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
"Wavelet/core"
|
||||
"Wavelet/core/contracts"
|
||||
"Wavelet/pkg/config"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -23,7 +24,7 @@ const (
|
||||
defaultShutdownTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
//go:embed migrations/*/*.sql
|
||||
var workerMigrations embed.FS
|
||||
|
||||
// Option configures the Asynq worker driver plugin.
|
||||
@@ -131,11 +132,13 @@ func (p *Plugin) Apply(ctx *core.Context) error {
|
||||
// 1. Provide contracts.TaskService
|
||||
p.taskSvc = &taskServiceImpl{}
|
||||
core.Provide[contracts.TaskService](ctx, p.taskSvc)
|
||||
SetActiveTaskExtension(ctx.Tasks())
|
||||
|
||||
// 2. Register migrations for w_task_executions table
|
||||
ctx.Migrations().Register("driver_asynq_worker", workerMigrations)
|
||||
|
||||
ctx.OnDispose(func() error {
|
||||
SetActiveTaskExtension(nil)
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), p.shutdownTimeout)
|
||||
defer cancel()
|
||||
return p.Stop(shutdownCtx)
|
||||
@@ -175,8 +178,26 @@ func (p *Plugin) Start(_ context.Context) error {
|
||||
}
|
||||
|
||||
if p.server == nil {
|
||||
opt := p.redisOpt
|
||||
if opt == nil {
|
||||
if RedisOpt != nil {
|
||||
opt = RedisOpt
|
||||
} else {
|
||||
redisCfg := config.Config.Redis
|
||||
addr := "127.0.0.1:6379"
|
||||
if len(redisCfg.Addrs) > 0 && redisCfg.Addrs[0] != "" {
|
||||
addr = redisCfg.Addrs[0]
|
||||
}
|
||||
opt = asynq.RedisClientOpt{
|
||||
Addr: addr,
|
||||
Username: redisCfg.Username,
|
||||
Password: redisCfg.Password,
|
||||
DB: redisCfg.DB,
|
||||
}
|
||||
}
|
||||
}
|
||||
p.server = asynq.NewServer(
|
||||
p.redisOpt,
|
||||
opt,
|
||||
asynq.Config{
|
||||
Concurrency: p.concurrency,
|
||||
Queues: p.queues,
|
||||
|
||||
Reference in New Issue
Block a user