Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-34378

Is $setOnInsert atomic across single collection?

    XMLWordPrintableJSON

Details

    • Icon: Question Question
    • Resolution: Done
    • Icon: Major - P3 Major - P3
    • None
    • 3.6.3
    • Querying
    • None
    • Server Triage

    Description

      I'm working on a "set once" config module for mongodb, here's my go code:

      package dao
       
      import "github.com/globalsign/mgo/bson"
       
      func InsertOnce(selector interface{}, update interface{}) (ret bson.M, err error) {
      	s, c := Mg("config")
      	defer s.Close()
       
      	_, err = c.Upsert(selector, &bson.M{
      		"$setOnInsert": update,
      	})
      	if err != nil {
      		return
      	}
      	ret = make(bson.M)
      	err = c.Find(selector).One(&ret)
      	return
      }
      

      When I test it:

      package dao
       
      import (
      	"sync"
      	"sync/atomic"
      	"testing"
       
      	"github.com/globalsign/mgo/bson"
      )
       
      func TestInsertOnce(t *testing.T) {
      	s, c := Mg("config")
      	defer s.Close()
      	defer c.DropCollection()
      	for n := 0; n < 10; n++ {
      		prev := int32(-1)
      		var changed int32
      		var wg sync.WaitGroup
      		for i := 0; i < 10; i++ {
      			wg.Add(1)
      			go func(i int) {
      				defer wg.Done()
      				result, err := InsertOnce(&bson.M{"entry": "secret"}, &bson.M{"value": i})
      				if err != nil {
      					t.Fatal("InsertOnce", err)
      				}
      				value := result["value"].(int)
      				t.Log(value, prev)
      				if atomic.SwapInt32(&prev, int32(value)) != int32(value) {
      					atomic.AddInt32(&changed, 1)
      				}
      			}(i)
      		}
      		wg.Wait()
      		if changed != 1 {
      			t.Fatal("value maybe changed by later func calls", changed)
      		}
      		c.DropCollection()
      	}
      }
      

      It sometime fails with more than once changed, is it related to my implementation or test code, or MongoDB will not guarantee the atomicity of $setOnInsert across single collection?

      Attachments

        Activity

          People

            backlog-server-triage Backlog - Triage Team
            kassiansun Kassian Sun
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: