-
Type: Question
-
Resolution: Done
-
Priority: Major - P3
-
None
-
Affects Version/s: 3.6.3
-
Component/s: Querying
-
Labels:None
-
Server Triage
I'm working on a "set once" config module for mongodb, here's my go code:
Unable to find source-code formatter for language: golang. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
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:
Unable to find source-code formatter for language: golang. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
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?