Documentation
¶
Overview ¶
Package scheduler cung cấp giải pháp lên lịch và chạy các task định kỳ cho ứng dụng Go, dựa trên thư viện gocron.
Tính năng nổi bật:
- Configuration-driven: Hỗ trợ cấu hình qua file config với struct Config và RedisLockerOptions
- Auto-start: Tự động khởi động scheduler khi ứng dụng boot (có thể tắt qua config)
- Wrap toàn bộ tính năng của thư viện gocron - một thư viện lập lịch và chạy task hiệu quả
- Hỗ trợ nhiều loại lịch trình: theo khoảng thời gian, theo thời điểm cụ thể, biểu thức cron
- Hỗ trợ chế độ singleton để tránh chạy song song cùng một task
- Hỗ trợ distributed locking với Redis cho môi trường phân tán (tự động cấu hình qua config)
- Hỗ trợ tag để nhóm và quản lý các task
- Tích hợp với DI container thông qua ServiceProvider
- API fluent cho trải nghiệm lập trình dễ dàng
Kiến trúc và cách hoạt động:
- Sử dụng mô hình embedding để triển khai interface Manager trực tiếp nhúng gocron.Scheduler
- Cung cấp fluent interface để cấu hình task một cách dễ dàng và rõ ràng
- ServiceProvider giúp tích hợp dễ dàng vào ứng dụng thông qua DI container
- Hỗ trợ dual config system: RedisLockerOptions (int) cho file config và RedisLockerOptionsTime (time.Duration) cho internal use
- Tự động khởi động scheduler khi ứng dụng boot (có thể tắt thông qua config auto_start: false)
- Tự động thiết lập distributed locking khi được enable trong config và có redis provider
- Hỗ trợ tự động gia hạn khóa cho distributed locking trong môi trường phân tán
Ví dụ sử dụng với configuration-driven approach:
// config/app.yaml scheduler: auto_start: true distributed_lock: enabled: true options: key_prefix: "myapp_scheduler:" lock_duration: 60 # seconds max_retries: 5 retry_delay: 200 # milliseconds redis: default: addr: "localhost:6379" password: "" db: 0 // Đăng ký service providers app := di.New() app.Register(config.NewServiceProvider()) app.Register(redis.NewServiceProvider()) // Required cho distributed locking app.Register(scheduler.NewServiceProvider()) // Boot ứng dụng - scheduler tự động cấu hình app.Boot() // Lấy scheduler từ container container := app.Container() sched := container.Get("scheduler").(scheduler.Manager) // Đăng ký task chạy mỗi 5 phút với distributed locking tự động sched.Every(5).Minutes().Do(func() { fmt.Println("Task runs every 5 minutes with distributed locking") }) // Đăng ký task với cron expression sched.Cron("0 0 * * *").Do(func() { fmt.Println("Task runs at midnight every day") }) // Đăng ký task với tag để dễ quản lý sched.Every(1).Hour().Tag("maintenance").Do(func() { fmt.Println("Maintenance task runs hourly") })
Sử dụng Manual Redis Locker (tùy chọn thay vì config):
import ( "github.com/redis/go-redis/v9" ) // Khởi tạo Redis client redisClient := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", DB: 0, }) // Tạo Redis Locker với tùy chọn mặc định locker, err := scheduler.NewRedisLocker(redisClient) if err != nil { log.Fatal(err) } // Hoặc với tùy chọn tùy chỉnh (sử dụng int values cho config) customLocker, err := scheduler.NewRedisLocker(redisClient, scheduler.RedisLockerOptions{ KeyPrefix: "myapp_scheduler:", LockDuration: 60, // seconds (int value) MaxRetries: 5, RetryDelay: 200, // milliseconds (int value) }) if err != nil { log.Fatal(err) } // Lấy scheduler từ container sched := container.Get("scheduler").(scheduler.Manager) // Thiết lập Redis Locker cho scheduler sched.WithDistributedLocker(locker) // Từ bây giờ, tất cả các jobs sẽ sử dụng distributed locking với Redis // để đảm bảo chỉ chạy một lần trong môi trường phân tán
Gói này giúp đơn giản hóa việc lên lịch và chạy các task định kỳ trong ứng dụng Go, đồng thời tích hợp dễ dàng với kiến trúc ứng dụng thông qua DI container và hỗ trợ configuration-driven approach cho việc thiết lập distributed locking.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrRedisClientNil được trả về khi Redis client nil. ErrRedisClientNil = errors.New("scheduler: redis client is nil") // ErrFailedToConnectToRedis được trả về khi không thể kết nối đến Redis. ErrFailedToConnectToRedis = errors.New("scheduler: failed to connect to redis") // ErrFailedToAcquireLock được trả về khi không thể lấy lock sau số lần thử tối đa. ErrFailedToAcquireLock = errors.New("scheduler: failed to acquire lock after maximum retries") // ErrInvalidLockDuration được trả về khi LockDuration không hợp lệ. ErrInvalidLockDuration = errors.New("scheduler: invalid lock duration") // ErrInvalidMaxRetries được trả về khi MaxRetries không hợp lệ. ErrInvalidMaxRetries = errors.New("scheduler: invalid max retries") // ErrInvalidRetryDelay được trả về khi RetryDelay không hợp lệ. ErrInvalidRetryDelay = errors.New("scheduler: invalid retry delay") // ErrInvalidKeyPrefix được trả về khi KeyPrefix không hợp lệ. ErrInvalidKeyPrefix = errors.New("scheduler: invalid key prefix") )
Error constants
Functions ¶
func NewRedisLocker ¶
func NewRedisLocker(client *redis.Client, opts ...RedisLockerOptions) (gocron.Locker, error)
NewRedisLocker tạo một Redis Locker mới để sử dụng với gocron. Nó có thể được chuyển vào phương thức WithDistributedLocker của scheduler.
Example:
redisClient := redis.NewClient(&redis.Options{ Addr: "localhost:6379", }) locker, err := scheduler.NewRedisLocker(redisClient) if err != nil { log.Fatal(err) } sched.WithDistributedLocker(locker)
func NewServiceProvider ¶
func NewServiceProvider() di.ServiceProvider
NewServiceProvider trả về một ServiceProvider mới cho module scheduler.
Hàm này khởi tạo và trả về một đối tượng ServiceProvider để sử dụng với DI container. ServiceProvider cho phép tự động đăng ký và cấu hình scheduler manager cho ứng dụng.
Returns:
- di.ServiceProvider: Interface di.ServiceProvider đã được implement bởi ServiceProvider
Example:
app.Register(scheduler.NewServiceProvider())
Types ¶
type Config ¶ added in v0.0.5
type Config struct { // AutoStart xác định có tự động khởi động scheduler khi ứng dụng boot không // ServiceProvider sẽ tự động gọi scheduler.StartAsync() trong Boot() method nếu true AutoStart bool `mapstructure:"auto_start" yaml:"auto_start"` // DistributedLock chứa cấu hình cho distributed locking DistributedLock DistributedLockConfig `mapstructure:"distributed_lock" yaml:"distributed_lock"` // Options chứa cấu hình RedisLockerOptions cho distributed locking Options RedisLockerOptions `mapstructure:"options" yaml:"options"` }
Config là cấu trúc cấu hình chính cho scheduler provider.
Config định nghĩa các tùy chọn cấu hình cho scheduler manager và distributed locking. Nó hỗ trợ Redis distributed locking khi chạy trên nhiều instance.
func DefaultConfig ¶ added in v0.0.5
func DefaultConfig() Config
DefaultConfig trả về cấu hình mặc định cho scheduler.
type DistributedLockConfig ¶ added in v0.0.5
type DistributedLockConfig struct { // Enabled xác định có bật distributed locking không // Chỉ cần thiết khi chạy scheduler trên nhiều instance trong môi trường phân tán Enabled bool `mapstructure:"enabled" yaml:"enabled"` }
DistributedLockConfig chứa cấu hình cho distributed locking.
type Manager ¶
type Manager interface { // WithDistributedLocker thiết lập distributed locker (như Redis) cho scheduler. // Hữu ích khi chạy scheduler trên nhiều máy chủ trong môi trường phân tán. WithDistributedLocker(locker gocron.Locker) Manager // Every tạo một công việc mới với khoảng thời gian được chỉ định. // Trả về Manager để hỗ trợ fluent interface. Every(interval interface{}) Manager // Second chỉ định đơn vị thời gian là giây (đơn lẻ). // Trả về Manager để hỗ trợ fluent interface. Second() Manager // Seconds chỉ định đơn vị thời gian là giây. // Trả về Manager để hỗ trợ fluent interface. Seconds() Manager // Minutes chỉ định đơn vị thời gian là phút. // Trả về Manager để hỗ trợ fluent interface. Minutes() Manager // Hours chỉ định đơn vị thời gian là giờ. // Trả về Manager để hỗ trợ fluent interface. Hours() Manager // Days chỉ định đơn vị thời gian là ngày. // Trả về Manager để hỗ trợ fluent interface. Days() Manager // Weeks chỉ định đơn vị thời gian là tuần. // Trả về Manager để hỗ trợ fluent interface. Weeks() Manager // At chỉ định thời điểm trong ngày để chạy công việc. // Định dạng: "HH:MM" hoặc "HH:MM:SS". // Trả về Manager để hỗ trợ fluent interface. At(time string) Manager // StartAt chỉ định thời điểm bắt đầu cho công việc. // Trả về Manager để hỗ trợ fluent interface. StartAt(time time.Time) Manager // Cron thiết lập biểu thức cron cho công việc. // Trả về Manager để hỗ trợ fluent interface. Cron(cronExpression string) Manager // CronWithSeconds thiết lập biểu thức cron có hỗ trợ giây. // Trả về Manager để hỗ trợ fluent interface. CronWithSeconds(cronExpression string) Manager // Tag đánh dấu công việc với các tag được chỉ định. // Trả về Manager để hỗ trợ fluent interface. Tag(tags ...string) Manager // SingletonMode đặt công việc ở chế độ singleton (không chạy đồng thời). // Trả về Manager để hỗ trợ fluent interface. SingletonMode() Manager // Do đặt hàm để thực thi cho công việc với các tham số tùy chọn. // Trả về Job và error nếu có. Do(jobFun interface{}, params ...interface{}) (*gocron.Job, error) // Name đặt tên cho công việc đang được cấu hình. // Trả về Manager để hỗ trợ fluent interface. Name(name string) Manager // RemoveByTag xóa các công việc theo tag. RemoveByTag(tag string) error // RemoveByTags xóa các công việc khớp với TẤT CẢ tags đã chỉ định. RemoveByTags(tags ...string) error // FindJobsByTag tìm công việc theo tag. FindJobsByTag(tags ...string) ([]*gocron.Job, error) // StartAsync bắt đầu scheduler trong một goroutine riêng. StartAsync() // StartBlocking bắt đầu scheduler và chặn luồng hiện tại. StartBlocking() // Stop dừng scheduler. Stop() // IsRunning kiểm tra xem scheduler có đang chạy không. IsRunning() bool // Clear xóa tất cả các công việc đã đăng ký. Clear() // GetScheduler trả về đối tượng scheduler gốc của gocron. GetScheduler() *gocron.Scheduler // RegisterEventListeners đăng ký các listener cho các sự kiện. RegisterEventListeners(eventListeners ...gocron.EventListener) }
Manager là interface chính cho việc quản lý lịch trình công việc, wrapping gocron.
func NewScheduler ¶
NewScheduler tạo một đối tượng Manager mới sử dụng gocron làm backend. Nhận tham số config để cấu hình scheduler.
func NewSchedulerWithConfig ¶ added in v0.0.5
NewSchedulerWithConfig tạo một đối tượng Manager mới với cấu hình cụ thể.
type RedisLockerOptions ¶
type RedisLockerOptions struct { // KeyPrefix là tiền tố được thêm vào trước mỗi khóa trong Redis KeyPrefix string `mapstructure:"key_prefix" yaml:"key_prefix"` // LockDuration là thời gian một khóa sẽ tồn tại trước khi tự động hết hạn (giây) LockDuration int `mapstructure:"lock_duration" yaml:"lock_duration"` // MaxRetries là số lần thử tối đa khi gặp lỗi khi tương tác với Redis MaxRetries int `mapstructure:"max_retries" yaml:"max_retries"` // RetryDelay là thời gian chờ giữa các lần thử (milliseconds) RetryDelay int `mapstructure:"retry_delay" yaml:"retry_delay"` }
RedisLockerOptions chứa các tùy chọn cấu hình cho Redis Locker.
func DefaultRedisLockerOptions ¶
func DefaultRedisLockerOptions() RedisLockerOptions
DefaultRedisLockerOptions trả về các tùy chọn mặc định cho Redis Locker.
func (RedisLockerOptions) ToTimeDuration ¶ added in v0.0.5
func (opts RedisLockerOptions) ToTimeDuration() RedisLockerOptionsTime
ToTimeDuration chuyển đổi các giá trị int trong config thành time.Duration.
type RedisLockerOptionsTime ¶ added in v0.0.5
type RedisLockerOptionsTime struct { // KeyPrefix là tiền tố được thêm vào trước mỗi khóa trong Redis KeyPrefix string // LockDuration là thời gian một khóa sẽ tồn tại trước khi tự động hết hạn LockDuration time.Duration // MaxRetries là số lần thử tối đa khi gặp lỗi khi tương tác với Redis MaxRetries int // RetryDelay là thời gian chờ giữa các lần thử RetryDelay time.Duration }
RedisLockerOptionsTime chứa các tùy chọn cấu hình với time.Duration.
type ServiceProvider ¶
type ServiceProvider struct {
// contains filtered or unexported fields
}
ServiceProvider cung cấp dịch vụ scheduler và tích hợp với DI container.
ServiceProvider là một implementation của interface di.ServiceProvider, cho phép tự động đăng ký scheduler manager vào DI container của ứng dụng. ServiceProvider thực hiện công việc:
- Tạo một scheduler manager mới sử dụng gocron
- Đăng ký scheduler manager vào DI container với key "scheduler"
Việc cấu hình cụ thể và đăng ký các task được thực hiện bởi ứng dụng.
Để sử dụng ServiceProvider, ứng dụng cần:
- Implement interface Container() *di.Container để cung cấp DI container
func (*ServiceProvider) Boot ¶
func (p *ServiceProvider) Boot(app interface{})
Boot được gọi sau khi tất cả các service provider đã được đăng ký.
Boot là một lifecycle hook của di.ServiceProvider mà thực hiện sau khi tất cả các service provider đã được đăng ký xong.
Trong trường hợp của SchedulerServiceProvider, có thể dùng Boot để: 1. Lấy scheduler manager từ container 2. Bắt đầu scheduler trong chế độ async để nó sẵn sàng xử lý các task
Params:
- app: interface{} - Đối tượng ứng dụng phải implement interface: Container() *di.Container - Trả về DI container
func (*ServiceProvider) Providers ¶ added in v0.0.5
func (p *ServiceProvider) Providers() []string
func (*ServiceProvider) Register ¶
func (p *ServiceProvider) Register(app interface{})
Register đăng ký scheduler vào DI container.
Register được gọi khi đăng ký ServiceProvider vào ứng dụng. Phương thức này tạo một scheduler manager mới và đăng ký vào DI container của ứng dụng.
Params:
- app: interface{} - Đối tượng ứng dụng phải implement interface: Container() *di.Container - Trả về DI container
Luồng thực thi:
- Kiểm tra app có implement Container() không, nếu không thì return
- Lấy container từ app, kiểm tra nếu nil thì panic
- Tạo scheduler manager mới
- Đăng ký scheduler manager vào container với key "scheduler"
Việc cấu hình và đăng ký các task sẽ được thực hiện bởi ứng dụng, cho phép mỗi ứng dụng tùy chỉnh scheduler theo nhu cầu riêng.
func (*ServiceProvider) Requires ¶ added in v0.0.5
func (p *ServiceProvider) Requires() []string