英文:
Why golang CronJob cannot run within goroutine?
问题
我每天使用CronJob来启动我的任务,我的任务有几个子任务,我计划使用goroutine来运行。然而,事情并不顺利。
文件框架
|-gpool
| -pool.go
|-main.go
main.go
import (
"code.byted.org/i18n_web/content_import_tool_cronJob/gpool"
"fmt"
"github.com/robfig/cron/v3"
"log"
"os"
"runtime"
"time"
)
func SeedJob(it string, pool *gpool.Pool){
fmt.Println("Name item: ", it)
println(runtime.NumGoroutine())
pool.Done()
}
type delayJob struct {
PagePatternNameList []string
}
func (j *delayJob) GetPagePatternNameList() {
//j.PagePatternNameList = dal.GetPagePatternName()
j.PagePatternNameList = []string{"atama_posts","cchan_posts", "cookdoor_posts", "cookpad_posts",
"cookpad_recipe_seed", "kurashiru_posts", "lips_all_posts", "lips_product", "lips_product_sku_seed",
"lips_rank", "press_posts", "voce_all_posts", "zozo_posts_women"}
}
func (j *delayJob)Run(){
log.Println("delay Job RUN")
//time.Sleep(2 * time.Second)
// startSeedJob
pool := gpool.New(10)
println(runtime.NumGoroutine())
for _, it := range j.PagePatternNameList {
pool.Add(1)
go SeedJob(it, pool)
}
pool.Wait()
println(runtime.NumGoroutine())
}
func main() {
c := cron.New(
cron.WithLogger(
cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))))
_, err := c.AddJob("CRON_TZ=America/New_York @every 2m", cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&delayJob{}))
if err != nil {
fmt.Println("Cron Job err!")
return
}
fmt.Println("it started")
c.Start()
defer c.Stop()
time.Sleep(time.Second * 5)
}
pool.go
package gpool
import (
"sync"
)
type Pool struct {
queue chan int
wg *sync.WaitGroup
}
func New(size int) *Pool {
if size <= 0 {
size = 1
}
return &Pool{
queue: make(chan int, size),
wg: &sync.WaitGroup{},
}
}
func (p *Pool) Add(delta int) {
for i := 0; i < delta; i++ {
p.queue <- 1
}
for i := 0; i > delta; i-- {
<-p.queue
}
p.wg.Add(delta)
}
func (p *Pool) Done() {
<-p.queue
p.wg.Done()
}
func (p *Pool) Wait() {
p.wg.Wait()
}
当我运行我的代码时,它没有打印出我期望的任何信息,只有
it started
cron: 2021/06/10 13:41:21 start
cron: 2021/06/10 13:41:21 schedule, now=2021-06-10T13:41:21+08:00, entry=1, next=2021-06-10T13:43:21+08:00
Exiting.
Debugger finished with the exit code 0
看起来它没有触发错误,但没有正确运行。我该如何解决这个问题?
英文:
I use CronJob for starting my task everyday, and my task has several sub-tasks which I plan to use goroutine to run. However, things do not go smoothly.
File Framework
|-gpool
| -pool.go
|-main.go
main.go
import (
"code.byted.org/i18n_web/content_import_tool_cronJob/gpool"
"fmt"
"github.com/robfig/cron/v3"
"log"
"os"
"runtime"
"time"
)
func SeedJob(it string, pool *gpool.Pool){
fmt.Println("Name item: ", it)
println(runtime.NumGoroutine())
pool.Done()
}
type delayJob struct {
PagePatternNameList []string
}
func (j *delayJob) GetPagePatternNameList() {
//j.PagePatternNameList = dal.GetPagePatternName()
j.PagePatternNameList = []string{"atama_posts","cchan_posts", "cookdoor_posts", "cookpad_posts",
"cookpad_recipe_seed", "kurashiru_posts", "lips_all_posts", "lips_product", "lips_product_sku_seed",
"lips_rank", "press_posts", "voce_all_posts", "zozo_posts_women"}
}
func (j *delayJob)Run(){
log.Println("delay Job RUN")
//time.Sleep(2 * time.Second)
// startSeedJob
pool := gpool.New(10)
println(runtime.NumGoroutine())
for _, it := range j.PagePatternNameList {
pool.Add(1)
go SeedJob(it, pool)
}
pool.Wait()
println(runtime.NumGoroutine())
}
func main() {
c := cron.New(
cron.WithLogger(
cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))))
_, err := c.AddJob("CRON_TZ=America/New_York @every 2m", cron.NewChain(cron.DelayIfStillRunning(cron.DefaultLogger)).Then(&delayJob{}))
if err != nil {
fmt.Println("Cron Job err!")
return
}
fmt.Println("it started")
c.Start()
defer c.Stop()
time.Sleep(time.Second * 5)
}
pool.go
package gpool
import (
"sync"
)
type Pool struct {
queue chan int
wg *sync.WaitGroup
}
func New(size int) *Pool {
if size <= 0 {
size = 1
}
return &Pool{
queue: make(chan int, size),
wg: &sync.WaitGroup{},
}
}
func (p *Pool) Add(delta int) {
for i := 0; i < delta; i++ {
p.queue <- 1
}
for i := 0; i > delta; i-- {
<-p.queue
}
p.wg.Add(delta)
}
func (p *Pool) Done() {
<-p.queue
p.wg.Done()
}
func (p *Pool) Wait() {
p.wg.Wait()
}
When I run my code, it did not print out any information I expected, just
it started
cron: 2021/06/10 13:41:21 start
cron: 2021/06/10 13:41:21 schedule, now=2021-06-10T13:41:21+08:00, entry=1, next=2021-06-10T13:43:21+08:00
Exiting.
Debugger finished with the exit code 0
It seems like it did not trigger an err, but not run correctly. How can I solve this?
答案1
得分: 2
它没有运行,因为你将作业安排为每2分钟运行一次,然后只等待了5秒钟,然后从main()
返回,这导致你的程序退出。
如果你想在后台启动这个cron作业,你必须让程序运行足够长的时间,以便它能够运行和完成,至少在这个例子中要超过2分钟。
如果在main()
中没有其他事情要做,你可以考虑使用c.Run()
而不是c.Start()
。
英文:
It did not run because you scheduled the job to run every 2 minutes and then waited only 5 seconds, then you returned from main()
which causes your program to exit.
If you want to start this cron in the background you must keep the program running long enough for it to run and complete, at least more than 2 minutes in this example.
If you have nothing else to do in main()
then you might consider using c.Run()
rather than c.Start()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论