/* * WriteToBeanstalkd puts jobs onto beanstalkd */ func (conn *Connection) WriteToBeanstalkd(jobs <-chan interface{}) { log.Printf(" [*] Publishing beans. To exit press CTRL+C") for j := range jobs { job, ok := j.(rabbitbeans.Job) if !ok { rabbitbeans.FailOnError(errors.New("Unknown message on channel"), "Can't put message on rabbit") } if !conn.config.Quiet { log.Printf("Received a bean to create: %s", job.Body) } id, err := conn.beansConnection.Put( job.Body, //body job.Priority, //pri uint32 job.Delay, //delay job.TTR, // TTR time to run -- is an integer number of seconds to allow a worker to run this job ) rabbitbeans.LogOnError(err, fmt.Sprintf("Failed to put job on beanstalkd %s", job.Body)) if err != nil { job.Nack(id) } else { job.Ack(id) } if !conn.config.Quiet { fmt.Println("Created job", id) } } }
func configure() Config { var config Config if len(os.Args) < 2 { msg := "Missing config file" rabbitbeans.LogOnError(errors.New(msg), "Starting in rabbitToBean mode by default") config.RabbitToBean = defaultRabbitToBean } else { data, readErr := ioutil.ReadFile(os.Args[1]) rabbitbeans.LogOnError(readErr, "Starting in rabbitToBean mode by default") jsonErr := json.Unmarshal(data, &config) rabbitbeans.LogOnError(jsonErr, "Starting in rabbitToBean mode by default") } log.Printf("Starting with config: %v", config) return config }
/* * WriteToRabbit connects to the rabbitMQ queue defined in the config * (if it does not exit, it will error). Then it pushes to messages on that * queue whenever it gets a new one on the jobs channel. */ func (conn *Connection) WriteToRabbit(queueName string, jobs <-chan interface{}) { ch, err := conn.rabbitConnection.Channel() rabbitbeans.FailOnError(err, "Failed to open a channel") defer ch.Close() // Clean up by closing channel when function exits q, err := ch.QueueInspect( // Make sure queue exists - don't create one otherwise and err. queueName, // queue name ) rabbitbeans.FailOnError(err, fmt.Sprintf("Failed to find queue named: %s", queueName)) log.Printf("Connected to queue: %s", q.Name) if err := ch.Confirm( false, // noWait = false - means, please do wait for confirms ); err != nil { rabbitbeans.FailOnError(err, "Could not set channel confirm mode on") } // Buffer of 1 for our single outstanding publishing confirms := ch.NotifyPublish(make(chan amqp.Confirmation, 1)) log.Printf(" [*] Sending rabbits. To exit press CTRL+C") for j := range jobs { job, ok := j.(rabbitbeans.Job) if !ok { rabbitbeans.LogOnError(errors.New("Unreadable job on the channel"), "Skipping item") continue } if !conn.config.Quiet { log.Printf("Sending rabbit to queue: %s", string(job.Body)) } err = ch.Publish( "", // exchange queueName, // routing key false, // mandatory false, // immediate amqp.Publishing{ ContentType: job.ContentType, Body: job.Body, }) if err != nil { job.Nack(job.Id) } else { // only ack the source delivery when the destination acks the publishing if confirmed := <-confirms; confirmed.Ack { job.Ack(job.Id) } else { job.Nack(job.Id) } rabbitbeans.FailOnError(err, fmt.Sprintf("Failed to find queue named: %s", queueName)) } } }
/* * ReadFromBeanstalkd reads jobs off of beanstalkd. */ func (conn *Connection) ReadFromBeanstalkd(jobs chan<- interface{}) { log.Printf(" [*] Consuming beans. To exit press CTRL+C") ticker := time.NewTicker(time.Duration(conn.config.TickInterval) * time.Second) go func() { for { select { case <-ticker.C: log.Printf("Polling beanstalkd for beans") var i = 0 for { id, body, err := conn.beansConnection.Reserve(5 * time.Second) if cerr, ok := err.(beanstalk.ConnError); !ok { rabbitbeans.FailOnError(err, "expected connError") } else if cerr.Err != beanstalk.ErrTimeout { rabbitbeans.LogOnError(err, fmt.Sprintf("expected timeout on reserve %d", id)) // Means the job deadline is real soon!! Reserve job anyways } else { break } if !conn.config.Quiet { log.Printf("Reserved job %v %s", id, body) } jobs <- rabbitbeans.Job{ id, body, conn, "application/json", 0, 0, 0, "", } i++ if i == conn.config.BatchSize { break } } log.Printf("Processed %d jobs this tick", i) } } }() }