如何停止rethinkdbs Next(.Changes())

时间:2016-01-01 23:48:13

标签: go

我目前在我的应用中使用RethinkDB,因为他们的实时事件驱动数据。我目前有这个监视功能,可以检查在线用户:

func (c *connection) watchUsers() {
    db := common.DB()
    query := gorethink.Table("Users").Filter(map[string]interface{}{
        "online": 1,
    }).Changes(gorethink.ChangesOpts{
        IncludeInitial: true,
    })
    res, err := query.Run(db)
    if err != nil {
        log.Println(err)
    }
    defer res.Close()
    var users interface{}
    for res.Next(&users) {
        if c.disconnecting {
            break
        }
        usersNewMap := users.(map[string]interface{})["new_val"]
        user := usersNewMap.(map[string]interface{})
        log.Println(user["username"])
        c.ws.WriteJSON(wsMsg{
            "user add",
            map[string]interface{}{
                "username": user["username"].(string),
                "uuid":     user["id"].(string),
            },
        })
    }
    log.Println("Ended on disconnect")
}

唯一的问题是我需要在websocket断开连接时返回watchUsers函数。现在我有

defer func() {
   c.disconnecting = true
}()

在websocket中,当手表试图在另一个公告上获得更多数据时,它会打破循环并结束goroutine。唯一的问题是,如果没有数据要播放一段时间,现在这个goroutine暂停一段时间占用不必要的空间。所以我的问题是,我怎么能用某种事件驱动的方法打破这个循环,如果我可以让res.Next成为一个通道会更容易因为那时我可以使用一个选择,但事实并非如此

1 个答案:

答案 0 :(得分:0)

所以我提出了一个解决方案,使用来自@CodingPickle的建议似乎工作得很好,简而言之,在自己的goroutine中运行for循环,然后在完成观看时执行res.Close()

func (c *connection) watchUsers() {
    db := common.DB()
    query := gorethink.Table("Users").Filter(map[string]interface{}{
        "online": 1,
    }).Changes(gorethink.ChangesOpts{
        IncludeInitial: true,
    })
    res, err := query.Run(db)
    if err != nil {
        log.Println(err)
    }

    go func(res *gorethink.Cursor, c *connection) {
        defer res.Close()
        var users interface{}
        for res.Next(&users) {
            usersNewMap := users.(map[string]interface{})["new_val"]
            user := usersNewMap.(map[string]interface{})
            c.send <- wsMsg{
                "user add",
                map[string]interface{}{
                    "username": user["username"].(string),
                    "uuid":     user["id"].(string),
                },
            }
        }
        log.Println("Ended gracefully")
    }(res, c)

    select {
    case <-c.disconnecting:
        res.Close()
        break
    case <-c.stopWatchingUsers:
        res.Close()
        break
    }
}