func putToTube(t *beanstalk.Tube, args []string) { var data []byte var pri uint32 var delay time.Duration ttr := 30 * time.Second switch len(args) { case 4: if ttrSecs, err := strconv.Atoi(args[3]); err == nil { ttr = time.Duration(ttrSecs) * time.Second } fallthrough case 3: if delaySecs, err := strconv.Atoi(args[2]); err == nil { delay = time.Duration(delaySecs) * time.Second } fallthrough case 2: if pri64, err := strconv.ParseUint(args[1], 10, 32); err == nil { pri = uint32(pri64) } fallthrough case 1: data = []byte(args[0]) } id, err := t.Put(data, pri, delay, ttr) if err != nil { fmt.Println(err) os.Exit(4) } fmt.Printf("Job was put to tube %s with pri=%d, delay=%v, ttr=%v. Job ID: %d\n", t.Name, pri, delay, ttr, id) }
func (b *beanstalkdQ) Put(m *Message, delay time.Duration) error { conn, err := connection() if err != nil { return err } var buf bytes.Buffer err = gob.NewEncoder(&buf).Encode(m) if err != nil { return err } tube := beanstalk.Tube{Conn: conn, Name: b.name} _, err = tube.Put(buf.Bytes(), 1, delay, ttr) return err }
// Send the job off to a beanstalkd // handle reconnect if needed while we have the SubmitLock func Submit(job *CronJob) { logDebug("submitting:", fmt.Sprintf("%#v", job)) SubmitLock.Lock() defer SubmitLock.Unlock() // previous reconnect failed, so we're nil here if BeanstalkdConn == nil { log.Println("not connected to a beanstalkd server") if err := connectBeanstalkd(); err != nil { return } } // loop if we need to reconnect for i := 0; i < 2; i++ { tube := beanstalk.Tube{ BeanstalkdConn, job.Tube, } _, err := tube.Put([]byte(job.Body), job.Priority, 0, time.Duration(job.Ttr)*time.Second) if _, ok := err.(beanstalk.ConnError); ok { log.Println(err) // attempt to reconnect on a Connection Error if err := connectBeanstalkd(); err != nil { // abort if we can't reconnect return } // try submitting again continue } // something besides a ConnError if err != nil { // anything else is fatal log.Println("error submitting job:", err) return } // we're OK now logDebug("submitted:", job) // make an attempt to set last_submit in redis if RedisConn != nil { RedisConn.Do("HSET", job.Key, "last_submit", time.Now().UTC().Format(time.RFC3339)) } return } }
func (c *PutCommand) Put() error { t := beanstalk.Tube{c.conn, c.Tube} id, err := t.Put([]byte(c.Body), c.Priority, c.Delay, c.TTR) if err != nil { return err } fmt.Printf( "Added job with id %d to %s with priority %d, delay %s, TTR %d\n", id, c.Tube, c.Priority, c.Delay.String(), c.TTR, ) return nil }
func queueJob(body string, priority uint32, ttr time.Duration) (string, uint64) { r := rand.New(rand.NewSource(time.Now().UnixNano())) tubeName := "cmdstalk-test-" + strconv.FormatInt(r.Int63(), 16) assertTubeEmpty(tubeName) c, err := beanstalk.Dial("tcp", address) if err != nil { log.Fatal(err) } tube := beanstalk.Tube{Conn: c, Name: tubeName} id, err := tube.Put([]byte(body), priority, 0, ttr) if err != nil { log.Fatal(err) } return tubeName, id }
// Satisfies the Listener interface and places the event on an AWS SQS func (this *Beanstalkd) Exec(evt event.Event) { this.Log.Handler(this, &evt) conStr := fmt.Sprintf("%s:%d", this.Config.GetHost(), this.Config.GetPort()) msg := magicString(this.Config.GetMessage(), evt) tube := magicString(this.Config.GetTube(), evt) c, err := beanstalk.Dial("tcp", conStr) t := beanstalk.Tube{c, tube} if err != nil { this.Log.Error(err.Error()) return } _, err = t.Put([]byte(msg), 1025, 0, 120*time.Hour) if err != nil { this.Log.Error(err.Error()) return } }
func beanstalkWriter() error { bean, err := beanstalk.Dial("tcp", "127.0.0.1:11300") if err != nil { return fmt.Errorf("Could not connect to beanstalkd: %s", err) } tube := beanstalk.Tube{bean, "v6-results"} for { js, ok := <-beanCh if !ok { return fmt.Errorf("Could not read from channel") } _, err := tube.Put(js, 100, 0, 120*time.Second) if err != nil { return fmt.Errorf("Could not put job: %s", err) } } }
// Send a unit of work to a worker. 'workerTube' determines the // tube that will respond to incoming work. 'feedback' is lets the caller // determine if a response is expected. 'options' is an optional parameter // to configure the beanstalkd interaction, otherwise, the default options // will be used. func Send(tube string, data interface{}, feedback bool, options *Options) ([]byte, error) { if options == nil { options = defaultOptions } // put together our request data req := &struct { Data interface{} `json:"data"` Feedback bool `json:"feedback"` }{ Data: data, Feedback: feedback, } // marshal the data into a payload jsonReq, err := json.Marshal(req) if err != nil { return nil, ErrJSONMarshal } // connect to beanstalkd beanConn, err := beanstalk.Dial("tcp", options.Host) if err != nil { return nil, ErrBeanstalkConnect } defer beanConn.Close() // configure conn for send tube workerTube := beanstalk.Tube{beanConn, tube} // send it jobID, err := workerTube.Put(jsonReq, options.Priority, options.Delay, options.TTR) if err != nil { return nil, ErrUnableToSend } // no response -- all done with the send if !feedback { return nil, nil } var ( resTube = tube + "_" + strconv.FormatUint(jobID, 10) watch = beanstalk.NewTubeSet(beanConn, resTube) id uint64 msg []byte start = time.Now() ) // wait for a response from the worker for { id, msg, err = watch.Reserve(options.Reserve) if err != nil { cerr, ok := err.(beanstalk.ConnError) if ok && cerr.Err == beanstalk.ErrTimeout { if time.Since(start) > options.Wait { return nil, ErrNoResponse } continue } else { return nil, err } } break } // delete the job beanConn.Delete(id) // handle the response resp := &struct { Error string `json:"error"` Data json.RawMessage `json:"data"` }{} err = json.Unmarshal(msg, resp) if err != nil { return nil, err } else if len(resp.Error) > 0 { return nil, errors.New(resp.Error) } // success! return resp.Data, nil }