Настраиваемый курсор не блокируется в пустой коллекции - PullRequest
0 голосов
/ 15 января 2020

Я хочу обрабатывать уведомления, как только они добавляются в MongoDB. Для этого существуют закрытые коллекции, которые позволяют использовать настраиваемые курсоры. Они должны блокироваться при получении следующего элемента, пока этот следующий элемент не станет доступным.

Вот код Go, который я использовал:

package main

import (
    "context"
    "fmt"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/mongo/readpref"
    "time"
)

func main() {
    defer fmt.Println("done.")

    ctx := context.Background()

    collection, err := connect(ctx)
    if err != nil {
        fmt.Println("failed to connect", err)
        return
    }
    fmt.Println("connected.")

    if err := follow(ctx, collection); err != nil {
        fmt.Println("failed to follow", err)
    }
}

func connect(ctx context.Context) (*mongo.Collection, error) {
    // use 3s timeout for connecting
    ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
    defer cancel()

    opts := options.Client().
        ApplyURI("mongodb://localhost")
    err := opts.Validate()
    if err != nil {
        return nil, err
    }

    client, err := mongo.NewClient(opts)
    if err != nil {
        return nil, err
    }

    if err := client.Connect(ctx); err != nil {
        return nil, err
    }

    if err := client.Ping(ctx, readpref.Primary()); err != nil {
        return nil, err
    }

    db := client.Database("test")
    return db.Collection("example"), nil
}

func follow(ctx context.Context, collection *mongo.Collection) error {
    // create a tailable cursor on the collection
    filter := bson.M{}
    opts := options.Find().
        SetCursorType(options.TailableAwait)
    cursor, err := collection.Find(ctx, filter, opts)
    if err != nil {
        return err
    }
    defer cursor.Close(ctx)

    // load and print documents as they are inserted
    for cursor.Next(ctx) {
        var document bson.M
        if err := cursor.Decode(&document); err != nil {
            return err
        }
        fmt.Println("loaded document", document)
    }
    return nil
}

MongoDB был настроен с использованием Docker, посмотрите скрипт Bash:

docker run --rm --detach --name mongodb --publish 27017:27017 mongo:4.2
sleep 2 # Hack: wait for the DB to start up
docker exec mongodb mongo --eval "db.createCollection('example', {capped:true, size: 1000000})"

При запуске программы Go появляется следующий вывод:

connected.
done.

Здесь есть две особенности: во-первых, я бы ожидать, что это заблокирует после подключения, то есть никогда не выходить. Во-вторых, нет даже ошибки!

Если вы запустите docker exec mongodb mongo --eval "db.example.insert({_id:1})" просто для добавления некоторого содержимого в коллекцию, это изменит поведение программы. Затем, после подключения, он выводит существующий элемент и затем сидит там:

connected.
loaded document map[_id:1]

Я делаю что-то не так или это ошибка в другом месте?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...