瀏覽代碼

batcher: short-circuit when timeout is 0

There's no point in launching a goroutine and setting a timer and all that junk,
just run the work function inline.

Also clarify that the work function must be concurrency-safe, since that is now
much more obviously true. It was always true, but you could be forgiven for
concluding the opposite on a quick skim of the old code.
Evan Huus 11 年之前
父節點
當前提交
0fdc444808
共有 2 個文件被更改,包括 14 次插入1 次删除
  1. 7 1
      batcher/batcher.go
  2. 7 0
      batcher/batcher_test.go

+ 7 - 1
batcher/batcher.go

@@ -22,7 +22,9 @@ type Batcher struct {
 }
 
 // New constructs a new batcher that will batch all calls to Run that occur within
-// `timeout` time before calling doWork just once for the entire batch.
+// `timeout` time before calling doWork just once for the entire batch. The doWork
+// function must be safe to run concurrently with itself as this may occur, especially
+// when the timeout is small.
 func New(timeout time.Duration, doWork func([]interface{}) error) *Batcher {
 	return &Batcher{
 		timeout: timeout,
@@ -40,6 +42,10 @@ func (b *Batcher) Run(param interface{}) error {
 		}
 	}
 
+	if b.timeout == 0 {
+		return b.doWork([]interface{}{param})
+	}
+
 	w := &work{
 		param:  param,
 		future: make(chan error, 1),

+ 7 - 0
batcher/batcher_test.go

@@ -32,6 +32,13 @@ func TestBatcherSuccess(t *testing.T) {
 		}()
 	}
 	wg.Wait()
+
+	b = New(0, returnsSuccess)
+	for i := 0; i < 10; i++ {
+		if err := b.Run(nil); err != nil {
+			t.Error(err)
+		}
+	}
 }
 
 func TestBatcherError(t *testing.T) {