[SERVER-34378] Is $setOnInsert atomic across single collection? Created: 09/Apr/18  Updated: 06/Dec/22  Resolved: 09/Apr/18

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: 3.6.3
Fix Version/s: None

Type: Question Priority: Major - P3
Reporter: Kassian Sun Assignee: Backlog - Triage Team
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Server Triage
Participants:

 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?



 Comments   
Comment by Ramon Fernandez Marina [ 09/Apr/18 ]

Thanks for your report. Please note that the SERVER project is for reporting bugs or feature suggestions for the MongoDB server. For MongoDB-related support discussion please post on the mongodb-user group or Stack Overflow with the mongodb tag, where your question will reach a larger audience. A question like this involving more discussion would be best posted on the mongodb-user group. See also our Technical Support page for additional support resources.

Regards,
Ramón.

Comment by Kassian Sun [ 09/Apr/18 ]

Well, it seems to be a wrong direction of thought. I'll use unique index instead.

Generated at Thu Feb 08 04:36:28 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.