duanfeng7756 2019-01-09 20:06
浏览 17

有什么更好的方法来实现在社交网络中验证和执行帖子的例程?

I'm writing a small application to perform automatic postings on social networks.

My intention is that the user can via the web interface create the post at a specific time and the bot can be checking for new posts scheduled and execute them.

I'm having trouble working with routines and channels on Go.

I will leave below an example that reflects the reality of my code. It contains some comments to make it easier to understand.

What is the best way to implement a routine that checks for new posts at any time? Remembering:

  1. User can enter new posts at any time.
  2. The bot can manage hundreds/thousands of accounts at the same time. It would be essential to consume as little processing as possible.

play.golang.org (here)


    package main

    import (
        "fmt"
        "sync"
        "time"
    )

    var botRunning = true
    var wg = &sync.WaitGroup{}

    func main() {
        // I start the routine of checking for and posting scheduled appointments.
        wg.Add(1)
        go postingScheduled()

        // Later the user passes the command to stop the post.
        // At that moment I would like to stop the routine immediately without getting stuck in a loop.
        // What is the best way to do this?
        time.Sleep(3 * time.Second)
        botRunning = false

        // ignore down
        time.Sleep(2 * time.Second)
        panic("")

        wg.Wait()
    }

    // Function that keeps checking whether the routine should continue or not.
    // Check every 2 seconds.
    // I think this is very wrong because it consumes unnecessary resources.
    // -> Is there another way to do this?
    func checkRunning() {
        for {
            fmt.Println("Pause/Running? - ", botRunning)
            if botRunning {
                break
            }
            time.Sleep(2 * time.Second)
        }
    }

    // Routine that looks for the scheduled posts in the database.
    // It inserts the date of the posts in the Ticker and when the time comes the posting takes place.
    // This application will have hundreds of social network accounts and each will have its own function running in parallel.
    // -> What better way to check constantly if there are scheduled items in the database consuming the least resources on the machine?
    // -> Another important question. User can schedule posts to the database at any time. How do I check for new posts schedule while the Ticker is waiting for the time the last posting loaded?
    func postingScheduled() {
        fmt.Println("Init bot posting routine")
        defer wg.Done()
        for {
            checkRunning()
            <-time.NewTicker(2 * time.Second).C
            fmt.Println("posted success")
        }

    }

  • 写回答

1条回答 默认 最新

  • doo58088 2019-01-10 02:10
    关注

    With Peter's response I was able to adapt all the needs to put together a sketch.

    I do not know if this would be the best way to do it, maybe some function will consume processing resources unnecessarily. If anyone has better ideas for refactoring, I'll be very grateful to hear.

    
        package main
    
        import (
            "fmt"
            "log"
            "net/http"
            "sort"
            "time"
        )
    
        type posting struct {
            caption string
            scheduledTo time.Time
        }
    
        const dateLayoutFormat  = "02-01-2006 15:04:05"
    
        var botStatus = true
        var indexPosting int
        var tickerSchedule = time.NewTicker(1)
        var posts = []posting{
            {caption: "item 1", scheduledTo: time.Now().Add(5 * time.Second)},
            {caption: "item 2", scheduledTo: time.Now().Add(25 * time.Second)},
        }
    
        func init() {
            indexPosting = len(posts)
        }
    
        func main() {
            http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
                fmt.Fprint(w, "Bem vindo ao bot")
            })
    
            http.HandleFunc("/stop", func (w http.ResponseWriter, r *http.Request) {
                fmt.Fprint(w, "Parando o bot!")
                stopBot()
            })
    
            http.HandleFunc("/start", func (w http.ResponseWriter, r *http.Request) {
                fmt.Fprint(w, "Iniciando o bot!")
                startBot()
            })
    
            http.HandleFunc("/add", func (w http.ResponseWriter, r *http.Request) {
                t := time.Now().Add(5 * time.Second)
                indexPosting++
    
                addItemDB(posting{
                    caption: fmt.Sprint("item ", indexPosting),
                    scheduledTo: t,
                })
    
                fmt.Fprint(w, "Adicionando nova postagem 
    Próximo post será: ", t.Format(dateLayoutFormat))
            })
    
            if botStatus {
                go workerScheduled()
            }
    
            log.Print("Inicnando server...")
            if err := http.ListenAndServe(":9090", nil); err != nil {
                log.Print("erro ao iniciar servidor => ", err)
            }
    
        }
    
        func workerScheduled() {
            for {
                log.Print("listando as próximas postagens")
    
                pts := getNextPostsDB()
                if len(pts) == 0 {
                    log.Print("sem postagem agendada")
                    botStatus = false
                    return
                }
    
                p1 := pts[0]
    
                log.Printf("Próxima postagem será: %s 
    
    ", string(p1.scheduledTo.Format(dateLayoutFormat)))
                <- updateTimer(p1.scheduledTo).C
    
                if !botStatus {
                    log.Print("postagem cancelado, bot status = parado")
                    return
                }
    
                if time.Until(p1.scheduledTo) > 1 * time.Second {
                    updateTimer(p1.scheduledTo)
                    log.Print("timer resetado")
                    continue
                }
    
                post(p1)
                if len(pts) > 1 {
                    p2 := pts[1]
                    updateTimer(p2.scheduledTo)
                }
                updatePostedDB()
            }
        }
    
        func updateTimer(t time.Time) *time.Ticker {
            tickerSchedule = time.NewTicker(t.Sub(time.Now()))
            return tickerSchedule
        }
    
        func post(p posting) {
            log.Printf("'%s' postado com sucesso", p.caption)
        }
    
        func addItemDB(p posting) {
            posts = append(posts, p)
            if botStatus {
                next := getNextPostDB()
                updateTimer(next.scheduledTo)
            } else {
                botStatus = true
                go workerScheduled()
            }
        }
    
        func getNextPostDB() posting {
            return getNextPostsDB()[0]
        }
    
        func getNextPostsDB() []posting {
            orderPostsList()
            removePostExpired()
            return posts
        }
    
        func removePostExpired() {
            for _, p := range posts {
                if p.scheduledTo.Before(time.Now()) {
                    log.Printf("removendo postagem expirada")
                    removePostByIndex(getIndexOf(p))
                }
            }
        }
    
        func removePostByIndex(i int) {
            copy(posts[i:], posts[i+1:])
            posts = posts[:len(posts)-1]
        }
    
        func getIndexOf(post posting) int {
            for i, p := range posts {
                if p.caption == post.caption {
                    return i
                }
            }
            return -1
        }
    
        func updatePostedDB() {
            removePostByIndex(0)
        }
    
        func orderPostsList() {
            sort.Slice(posts, func(i, j int) bool {
                return posts[i].scheduledTo.Before(posts[j].scheduledTo)
            })
        }
    
        func startBot() {
            if !botStatus {
                log.Printf("comando 'iniciar bot'")
                botStatus = true
                go workerScheduled()
            } else {
                log.Printf("comando 'iniciar bot' (já iniciado)")
            }
        }
    
        func stopBot() {
            if botStatus {
                log.Printf("comando 'pausar bot'")
                botStatus = false
                tickerSchedule.Stop()
            } else {
                log.Printf("comando 'pausar bot' (já pausado)")
            }
        }
    
    
    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?