lock on votes, fix #77
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@@ -16,6 +17,8 @@ type DataStore struct {
|
||||
EditDuration time.Duration
|
||||
Secret string
|
||||
MaxCommentSize int
|
||||
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
const defaultCommentMaxSize = 2000
|
||||
@@ -53,6 +56,9 @@ func (s *DataStore) SetPin(locator store.Locator, commentID string, status bool)
|
||||
// Vote for comment by id and locator
|
||||
func (s *DataStore) Vote(locator store.Locator, commentID string, userID string, val bool) (comment store.Comment, err error) {
|
||||
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
comment, err = s.Get(locator, commentID)
|
||||
if err != nil {
|
||||
return comment, err
|
||||
|
||||
@@ -170,7 +170,39 @@ func TestService_VoteAggressive(t *testing.T) {
|
||||
assert.Equal(t, 3, len(res))
|
||||
t.Logf("%+v %d", res[0], res[0].Score)
|
||||
assert.True(t, res[0].Score >= 0 && res[0].Score <= 2, "unexpected score %d", res[0].Score)
|
||||
}
|
||||
|
||||
func TestService_VoteConcurrent(t *testing.T) {
|
||||
|
||||
defer os.Remove(testDb)
|
||||
b := DataStore{Interface: prepStoreEngine(t)}
|
||||
|
||||
comment := store.Comment{
|
||||
Text: "text",
|
||||
User: store.User{IP: "192.168.1.1", ID: "user", Name: "name"},
|
||||
Locator: store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"},
|
||||
}
|
||||
_, err := b.Create(comment)
|
||||
assert.NoError(t, err)
|
||||
res, err := b.Last("radio-t", 0)
|
||||
require.Nil(t, err)
|
||||
|
||||
// concurrent vote +1 as multiple users for the same comment
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 1000; i++ {
|
||||
wg.Add(1)
|
||||
i := i
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
b.Vote(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, res[0].ID, fmt.Sprintf("user1-%d", i), true)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
res, err = b.Last("radio-t", 0)
|
||||
require.NoError(t, err)
|
||||
t.Logf("%+v %d", res[0], res[0].Score)
|
||||
assert.Equal(t, 1000, res[0].Score, "should have 1000 score")
|
||||
assert.Equal(t, 1000, len(res[0].Votes), "should have 1000 votes")
|
||||
}
|
||||
|
||||
func TestService_Pin(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user