func RunNewPusher(schedule RunSchedule, name string, c *api.SyncGatewayClient, channel string, size int, sendAttachment bool, dist DocSizeDistribution, seqId, sleepTime int, wg *sync.WaitGroup) { defer wg.Done() glExpvars.Add("user_active", 1) // if config contains DocSize, always generate this fixed document size if size != 0 { dist = DocSizeDistribution{ &DocSizeDistributionElement{ Prob: 100, MinSize: size, MaxSize: size, }, } } docSizeGenerator, err := NewDocSizeGenerator(dist) if err != nil { Log("Error starting docuemnt pusher: %v", err) return } docIterator := DocIterator(seqId*DocsPerUser, (seqId+1)*DocsPerUser, docSizeGenerator, channel, sendAttachment) docsToSend := 0 online := false scheduleIndex := 0 start := time.Now() timer := time.NewTimer(schedule[scheduleIndex].start) var lastSend time.Time var pushTimer <-chan time.Time for { select { case <-timer.C: // timer went off, transition modes timeOffset := time.Since(start) if online { glExpvars.Add("user_awake", -1) online = false pushTimer = nil scheduleIndex++ if scheduleIndex < len(schedule) { nextOnIn := schedule[scheduleIndex].start - timeOffset timer = time.NewTimer(nextOnIn) Log("Pusher %s going offline, next on at %v", name, nextOnIn) if nextOnIn < 0 { log.Printf("WARNING: pusher %s negative timer nextOnTime, exiting", name) return } } } else { glExpvars.Add("user_awake", 1) online = true pushTimer = time.NewTimer(0).C if schedule[scheduleIndex].end != -1 { nextOffIn := schedule[scheduleIndex].end - timeOffset timer = time.NewTimer(nextOffIn) Log("Pusher %s going online, next off at %v", name, nextOffIn) if nextOffIn < 0 { log.Printf("WARNING: pusher %s negative timer nextOffTime, exiting", name) glExpvars.Add("user_awake", -1) return } } } case <-pushTimer: if lastSend.IsZero() { docsToSend = 1 } else { //log.Printf("time since last %v", time.Since(lastSend)) //log.Printf("durration: %v", (time.Duration(sleepTime) * time.Millisecond)) docsToSend = int(time.Since(lastSend) / (time.Duration(sleepTime) * time.Millisecond)) //log.Printf("docs to send: %v", docsToSend) } if docsToSend > 0 { Log("Pusher online sending %d docs", docsToSend) // generage docs docs := make([]api.Doc, docsToSend) for i := 0; i < docsToSend; i++ { nextDoc := <-docIterator docs[i] = nextDoc } // send revs diff revsDiff := map[string][]string{} for _, doc := range docs { revsDiff[doc.Id] = []string{doc.Rev} } c.PostRevsDiff(revsDiff) // set the creation time in doc id nowString := "_" + strconv.Itoa(int(time.Now().UnixNano()/1e6)) // time since epoch in ms as string for i, doc := range docs { doc.Id = doc.Id + nowString docs[i] = doc } // send bulk docs bulkDocs := map[string]interface{}{ "docs": docs, "new_edits": false, } Log("Pusher #%d saved %d docs", seqId, docsToSend) if c.PostBulkDocs(bulkDocs) { glExpvars.Add("total_doc_pushed", int64(docsToSend)) } else { glExpvars.Add("total_doc_failed_to_push", int64(docsToSend)) } docsToSend = 0 lastSend = time.Now() // reset the timer pushTimer = time.NewTimer(time.Duration(sleepTime) * time.Millisecond).C } } } glExpvars.Add("user_active", -1) }