簡體   English   中英

如何停止正在偵聽 RethinkDB changefeeds 的 goroutine?

[英]How to stop a goroutine that is listening for RethinkDB changefeeds?

我想弄清楚如何在 golang 中使用 RethinkDB changefeeds。 我的具體問題是如何停止監聽數據庫更改的 goroutine。 例如,請參見下面的函數getData() 我通過調用go getData(c)從處理程序函數運行它。 每當數據庫更新時,記錄都會傳遞到通道c ,然后傳遞到處理程序函數並使用 SSE 技術發送到客戶端。 我的問題是:當客戶端斷開連接時,我知道如何停止和退出處理程序函數; 然而,運行getData()函數的 goroutine 一直在運行。 我該怎么做才能關閉它? 基於 stackoverflow 上的其他答案,我能想到的一種解決方案是發送信號以關閉另一個通道上的 goroutine,並使用 select 語句來處理此信號。 例如,我可以替換

    for cur.Next(&rec) {
        c <- rec
    }

在下面的函數定義中:

    for cur.Next(&rec) {
        select {
         case <- closesignal:
            return
         default:
            c <- rec
        }
    }

其中, closesignal是另一個通道,它作為getData()的第三個參數給出,當客戶端斷開連接時,處理程序在此通道上發送一條消息。

這種方法的問題是:如果特定 rethinkdb 查詢的結果永遠不會更新怎么辦。 在這種情況下,不會進入for cur.Next(&rec)循環並且不會使用closesignal 這個 goroutine 會繼續運行嗎? 如果是這樣,我該如何停止這個 goroutine?

getData()函數

func getData(session *r.Session, c chan interface{}) {
    var rec interface{}

    changesOpts := r.ChangesOpts{
        IncludeInitial: true,
    }

    cur, err := r.DB(DBNAME).Table("test").Changes(changesOpts).Run(session)
    if err != nil {
        log.Println(err)
        return
    }
    defer cur.Close()

    defer func() {
        fmt.Println("exiting getData goroutine()...")
    }()


    for cur.Next(&rec) {
        c <- rec
    }

}

您可以通過關閉光標來停止正在偵聽 changefeed 的 goroutine。 例如,此代碼將在關閉前偵聽 changefeed 10 秒:

go func() {
    time.Sleep(10 * time.Second)
    cur.Close()
}()

for cur.Next(&rec) {
    c <- rec
}

// Loop exits as the cursor has been closed

您應該通過context停止 changefeed。 您可以將您的上下文傳遞給RunOpts 這將立即關閉您的更改源。

我認為管理這種情況的最好方法是使用上下文來關閉游標,使用 goroutine。 這里有一些來自 go 博客的關於上下文的好文檔

這是帶有上下文的實現示例:

func AreThereChanges(ctx context.Context) error {
    cursor, err := r.Table("something").
        Changes().
        Run(db.Session)

    if err != nil {
      //manage error
    }

    go func(ctx context.Context) {
        <-ctx.Done()
        cursor.Close()
    }(ctx)

    var changeFeed map[string]interface{}
    for cursor.Next(&changeFeed) {
        if changeFeed["old_val"] != nil {
          //do something
        }

        if changeFeed["new_val"] != nil {
          //do something
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM