func connect(conn *amqp.Connection, exchange string, wg *sync.WaitGroup) { ch, err := conn.Channel() utils.FailOnError(err, "Failed to open a channel") defer conn.Close() err = ch.ExchangeDeclare( exchange, // name "direct", // type true, // durable false, // auto-deleted false, // internal false, // no-wait nil, // arguments ) utils.FailOnError(err, "Failed to declare an exchange") keys := []string{"create", "update"} for { for _, key := range keys { go connectKey(ch, key, exchange) } log.Printf("Break \n \n") time.Sleep(40 * time.Second) } }
func monitoring(uri string, queueName string, mgmtUri string, prefix string) { var ( queueConn *amqp.Connection queueChan *amqp.Channel err error ) queueConn, queueChan, err = rabbitmqConnect(uri, queueName) if err != nil { return } for { log.Printf("fetch rabbitmq stats") var metrics []graphite.Metric for _, metric := range fetchQueueMetrics(mgmtUri, prefix) { metrics = append(metrics, metric) } for _, metric := range fetchExchangeMetrics(mgmtUri, prefix) { metrics = append(metrics, metric) } for _, metric := range metrics { body := []byte(metric.Name + "\t" + metric.Value + "\t" + strconv.FormatInt(metric.Timestamp, 10)) msg := amqp.Publishing{ContentType: "text/plain", Body: body} err = queueChan.Publish("", queueName, false, false, msg) if err != nil { log.Printf("publish err: %s", err) return } //log.Printf("metric\t%s\t\t%s", metric.Name, metric.Value) } time.Sleep(time.Second * 5) } queueChan.Close() queueConn.Close() }
// redial continually connects to the URL, exiting the program when no longer possible func redial(ctx context.Context, url, exchange string) chan chan session { sessions := make(chan chan session) go func() { sess := make(chan session) defer close(sessions) for { select { case sessions <- sess: case <-ctx.Done(): log.Info("shutting down session factory") return } connected := false var conn *amqp.Connection var ch *amqp.Channel var err error for !connected { log.Debug("dialing amqp url: %s", url) conn, err = amqp.Dial(url) if err != nil { log.Error(3, "cannot (re)dial: %v: %q", err, url) time.Sleep(time.Second) continue } log.Debug("connected to %s", url) log.Debug("creating new channel on AMQP connection.") ch, err = conn.Channel() if err != nil { log.Error(3, "cannot create channel: %v", err) conn.Close() time.Sleep(time.Second) continue } log.Debug("Ensuring that %s topic exchange exists on AMQP server.", exchange) if err := ch.ExchangeDeclare(exchange, "topic", true, false, false, false, nil); err != nil { log.Error(3, "cannot declare topic exchange: %v", err) conn.Close() time.Sleep(time.Second) } log.Debug("Successfully connected to RabbitMQ.") connected = true } select { case sess <- session{conn, ch}: case <-ctx.Done(): log.Info("shutting down new session") return } } }() return sessions }
// shutdown is a general closer function for handling close gracefully // Mostly here for both consumers and producers // After a reconnection scenerio we are gonna call shutdown before connection func shutdown(conn *amqp.Connection) error { if err := conn.Close(); err != nil { if amqpError, isAmqpError := err.(*amqp.Error); isAmqpError && amqpError.Code != 504 { return fmt.Errorf("AMQP connection close error: %s", err) } } return nil }
// Closes the connection func (amqpBackend *AMQPBackend) close(channel *amqp.Channel, conn *amqp.Connection) error { if err := channel.Close(); err != nil { return fmt.Errorf("Channel Close: %s", err) } if err := conn.Close(); err != nil { return fmt.Errorf("Connection Close: %s", err) } return nil }
func Publish(messages chan *amqp.Publishing, connectionUri, exchange, routingKey string, mandatory, immediate bool, results chan *PublishResult) { var err error var conn *amqp.Connection var channel *amqp.Channel defer close(results) if conn, err = amqp.Dial(connectionUri); err != nil { results <- &PublishResult{"Failed to connect", err, true} return } defer conn.Close() if channel, err = conn.Channel(); err != nil { results <- &PublishResult{"Failed to get channel", err, true} return } pubAcks, pubNacks := channel.NotifyConfirm(make(chan uint64), make(chan uint64)) chanClose := channel.NotifyClose(make(chan *amqp.Error)) if err = channel.Confirm(false); err != nil { results <- &PublishResult{ "Failed to put channel into confirm mode", err, true, } return } for message := range messages { err = channel.Publish(exchange, routingKey, mandatory, immediate, *message) if err != nil { results <- &PublishResult{"Failed to publish message", err, false} continue } select { case err = <-chanClose: results <- &PublishResult{"Channel closed!", err, true} case <-pubAcks: results <- &PublishResult{ fmt.Sprintf("Published to exchange '%s' routing key '%v': %+v", exchange, routingKey, message), nil, false, } case <-pubNacks: results <- &PublishResult{"Received basic.nack for message", errors.New("'basic.nack'"), false} } } }
// Closes the connection func (amqpBroker *AMQPBroker) close(channel *amqp.Channel, conn *amqp.Connection) error { if channel != nil { if err := channel.Close(); err != nil { return fmt.Errorf("Channel Close: %s", err) } } if conn != nil { if err := conn.Close(); err != nil { return fmt.Errorf("Connection Close: %s", err) } } return nil }
// Function to restart everything func restart(reset chan *amqp.Error, config Configuration, conn *amqp.Connection, ch_gcm_log, ch_db_log, ch_apn_log, ch_gcm_log_success, ch_apn_log_success chan []byte, logger *log.Logger, killWorker, killStatusInactive, killTokenUpd, killStatusInactiveAck, killTokenUpdAck, killApnStatusInactive, killApnStatusInactiveAck chan int) { // Kill all Worker killAllWorkers(config, killWorker, killStatusInactive, killTokenUpd, killStatusInactiveAck, killTokenUpdAck, killApnStatusInactive, killApnStatusInactiveAck) conn.Close() conn = initConn(config) defer conn.Close() olog(fmt.Sprintf("Spinning up workers"), config.DebugMode) // For all GcmQueues start new goroutines for i := 0; i < len(config.GcmQueues); i++ { for j := 0; j < config.GcmQueues[i].Numworkers; j++ { go gcm_processor(j, config, conn, config.GcmQueues[i].GcmTokenUpdateQueue, config.GcmQueues[i].GcmStatusInactiveQueue, config.GcmQueues[i].Name, ch_gcm_log, ch_gcm_log_success, logger, killWorker, config.GcmQueues[i]) } go gcm_error_processor_status_inactive(config, conn, config.GcmQueues[i].GcmStatusInactiveQueue, ch_db_log, logger, killStatusInactive, killStatusInactiveAck, config.GcmQueues[i]) go gcm_error_processor_token_update(config, conn, config.GcmQueues[i].GcmTokenUpdateQueue, ch_db_log, logger, killTokenUpd, killTokenUpdAck, config.GcmQueues[i]) } //For all APN Queues start workers for i := 0; i < len(config.ApnQueues); i++ { // For all GCM Queues start workers for j := 0; j < config.ApnQueues[i].NumWorkers; j++ { go apn_processor(j, config, conn, config.ApnQueues[i].ApnStatusInactiveQueue, config.ApnQueues[i].Name, ch_apn_log, ch_apn_log_success, logger, killWorker, config.ApnQueues[i]) } olog(fmt.Sprintf("Startting workers for status_inactive for APN %s", config.GcmQueues[i].Identifier), config.DebugMode) go apn_error_processor_status_inactive(config, conn, config.ApnQueues[i].ApnStatusInactiveQueue, ch_db_log, logger, killApnStatusInactive, killApnStatusInactiveAck, config.ApnQueues[i]) } olog("Starting error processors", config.DebugMode) reset = conn.NotifyClose(make(chan *amqp.Error)) for range reset { go restart(reset, config, conn, ch_gcm_log, ch_db_log, ch_apn_log, ch_gcm_log_success, ch_apn_log_success, logger, killWorker, killStatusInactive, killTokenUpd, killStatusInactiveAck, killTokenUpdAck, killApnStatusInactive, killApnStatusInactiveAck) } }
// connects to an AMQP topic and emits each message into streamtools. func (b *FromAMQP) Run() { var err error var conn *amqp.Connection var amqp_chan *amqp.Channel toOut := make(blocks.MsgChan) toError := make(chan error) host := "localhost" port := "5672" username := "******" password := "******" routingkey := "#" exchange := "amq.topic" exchange_type := "topic" for { select { case msg := <-toOut: b.out <- msg case err := <-toError: b.Error(err) case ruleI := <-b.inrule: rule := ruleI.(map[string]interface{}) routingkey, err = util.ParseString(rule, "RoutingKey") if err != nil { b.Error(err) continue } exchange, err = util.ParseString(rule, "Exchange") if err != nil { b.Error(err) continue } exchange_type, err = util.ParseString(rule, "ExchangeType") if err != nil { b.Error(err) continue } host, err = util.ParseString(rule, "Host") if err != nil { b.Error(err) continue } port, err = util.ParseString(rule, "Port") if err != nil { b.Error(err) continue } username, err = util.ParseString(rule, "Username") if err != nil { b.Error(err) continue } password, err = util.ParseString(rule, "Password") if err != nil { b.Error(err) continue } conn, err = amqp.Dial("amqp://" + username + ":" + password + "@" + host + ":" + port + "/") if err != nil { b.Error(err) continue } amqp_chan, err = conn.Channel() if err != nil { b.Error(err) continue } err = amqp_chan.ExchangeDeclare( exchange, // name exchange_type, // type true, // durable false, // auto-deleted false, // internal false, // noWait nil, // arguments ) if err != nil { b.Error(err) continue } queue, err := amqp_chan.QueueDeclare( "", // name false, // durable true, // delete when unused false, // exclusive false, // noWait nil, // arguments ) if err != nil { b.Error(err) continue } err = amqp_chan.QueueBind( queue.Name, // queue name routingkey, // routing key exchange, // exchange false, nil, ) if err != nil { b.Error(err) continue } deliveries, err := amqp_chan.Consume( queue.Name, // name "", // consumerTag true, // noAck false, // exclusive false, // noLocal false, // noWait nil, // arguments ) if err != nil { b.Error(err) continue } h := readWriteAMQPHandler{toOut, toError} go h.handle(deliveries) case <-b.quit: if amqp_chan != nil { amqp_chan.Close() } if conn != nil { conn.Close() } return case c := <-b.queryrule: c <- map[string]interface{}{ "Host": host, "Port": port, "Username": username, "Password": password, "Exchange": exchange, "ExchangeType": exchange_type, "RoutingKey": routingkey, } } } }
func newRPCQueue(uri string) (*rpcQueue, error) { fmt.Println("newRPCQueue") var conn *amqp.Connection var err error for try := 0; try < 10; try++ { log.Infof("Attempt to connect to RabbitMQ: %d", try+1) conn, err = amqp.Dial(uri) if err == nil { break } time.Sleep(time.Second * 5) } if err != nil { return nil, err } amqpChannel, err := conn.Channel() if err != nil { conn.Close() return nil, err } queue, err := amqpChannel.QueueDeclare( "", // name false, // durable false, // delete when usused true, // exclusive false, // noWait nil, // arguments ) if err != nil { amqpChannel.Close() conn.Close() return nil, err } name := queue.Name msgs, err := amqpChannel.Consume( name, // queue "", // consumer true, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) if err != nil { amqpChannel.Close() conn.Close() return nil, err } q := rpcQueue{ name: name, channels: cmap.New(), amqpChannel: amqpChannel, correlationId: 0, } go func() { for d := range msgs { corrId := d.CorrelationId context, exists := q.channels.Get(corrId) if exists { q.channels.Remove(corrId) context.(chan *amqp.Delivery) <- &d } else { log.Errorf("Cannot handle RPC request (correlation id = %s)", corrId) } } }() return &q, nil }
func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, usageString, filepath.Base(os.Args[0])) flag.PrintDefaults() } flag.Parse() if *versionFlag { progName := path.Base(os.Args[0]) if VersionString == "" { VersionString = "<unknown>" } fmt.Printf("%s %s\n", progName, VersionString) os.Exit(0) } if *revFlag { if RevString == "" { RevString = "<unknown>" } fmt.Println(RevString) os.Exit(0) } files := flag.Args() if len(files) == 0 { flag.Usage() os.Exit(5) } var conn *amqp.Connection var channel *amqp.Channel var err error conn, err = amqp.Dial(*uriFlag) debugger.Print(fmt.Sprintf("uri: %s\n", *uriFlag)) if debugger.WithError(err, "Failed to connect ", err) { os.Exit(2) } debugger.Print("connection made") defer conn.Close() channel, err = conn.Channel() if debugger.WithError(err, "Failed to open channel ", err) { os.Exit(3) } debugger.Print("channel.established") var bytes []byte if len(files) == 1 && files[0] == "-" { stdin := bufio.NewReader(os.Stdin) for { myBytes, err := stdin.ReadString('\n') bytes = []byte(myBytes) if err != nil { if err != io.EOF { debugger.Print("ERROR:", err) } break } HandleMessageBytes(bytes, channel, debugger) } } else { for _, file := range files { bytes, err = ioutil.ReadFile(file) if debugger.WithError(err, fmt.Sprintf("Unable to read file %s: ", file), err) { os.Exit(13) } HandleMessageBytes(bytes, channel, debugger) } } }
// connects to an AMQP topic and emits each message into streamtools. func (b *ToAMQP) Run() { var err error var conn *amqp.Connection var amqp_chan *amqp.Channel host := "localhost" port := "5672" username := "******" password := "******" routingkey := "streamtools" exchange := "amq.topic" exchange_type := "topic" for { select { case ruleI := <-b.inrule: routingkey, err = util.ParseString(ruleI, "RoutingKey") if err != nil { b.Error(err) continue } exchange, err = util.ParseString(ruleI, "Exchange") if err != nil { b.Error(err) continue } exchange_type, err = util.ParseString(ruleI, "ExchangeType") if err != nil { b.Error(err) continue } host, err = util.ParseString(ruleI, "Host") if err != nil { b.Error(err) continue } port, err = util.ParseString(ruleI, "Port") if err != nil { b.Error(err) continue } username, err = util.ParseString(ruleI, "Username") if err != nil { b.Error(err) continue } password, err = util.ParseString(ruleI, "Password") if err != nil { b.Error(err) continue } conn, err = amqp.Dial("amqp://" + username + ":" + password + "@" + host + ":" + port + "/") if err != nil { b.Error(err) continue } amqp_chan, err = conn.Channel() if err != nil { b.Error(err) continue } err = amqp_chan.ExchangeDeclare( exchange, // name exchange_type, // type true, // durable false, // auto-deleted false, // internal false, // noWait nil, // arguments ) if err != nil { b.Error(err) continue } case msg := <-b.in: if conn == nil || amqp_chan == nil { continue } msgBytes, err := json.Marshal(msg) // Make the output JSON if msg wasn't JSON already if err != nil { json_msg := map[string]interface{}{ "data": msg, } msgBytes, err = json.Marshal(json_msg) if err != nil { b.Error(err) continue } } if len(msgBytes) == 0 { b.Error("Zero byte length message") continue } err = amqp_chan.Publish( exchange, routingkey, false, false, amqp.Publishing{ Headers: amqp.Table{}, ContentType: "text/plain", ContentEncoding: "", Body: msgBytes, DeliveryMode: amqp.Transient, Priority: 0, }, ) if err != nil { b.Error(err) continue } case <-b.quit: if amqp_chan != nil { amqp_chan.Close() } if conn != nil { conn.Close() } return case c := <-b.queryrule: c <- map[string]interface{}{ "Host": host, "Port": port, "Username": username, "Password": password, "Exchange": exchange, "ExchangeType": exchange_type, "RoutingKey": routingkey, } } } }
func Start() { mq := g.Config().Mq nodes := map[string]interface{}{} // Retry RetriedLimit times if there is some problem during connecting var ch *amqp.Channel var conn *amqp.Connection var err error for i := 0; i < RetriedLimit; i++ { if conn, ch, err = setup(mq.Queue); err != nil { time.Sleep(time.Second * SleepTimePeriod) } } if err != nil { log.Println(ExitStringPrefix + "retried too many times.") return } defer conn.Close() defer ch.Close() q, err := ch.QueueDeclare( "mute", // name false, // durable false, // delete when usused false, // exclusive false, // no-wait nil, // arguments ) if err != nil { log.Printf(LogStringFormat, ExitStringPrefix+"failed to declare a queue", err) return } msgs, err := ch.Consume( q.Name, // queue "", // consumer true, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) if err != nil { log.Printf(LogStringFormat, ExitStringPrefix+"failed to register a consumer", err) return } forever := make(chan bool) var pkt Message go func() { for d := range msgs { json.Unmarshal(d.Body, &pkt) log.Printf("Received a message: %v", pkt) params := map[string]string{ "host": pkt.Hostname, "mute": "", } if pkt.Mute { params["mute"] = "1" } else { params["mute"] = "0" } payload := map[string]interface{}{ "method": "host.update", "params": params, } log.Println("payload =", payload) s, err := json.Marshal(payload) if err != nil { log.Println("json.Marshal Error:", err.Error()) } url := mq.Consumer log.Println("url =", url) reqPost, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(s))) if err != nil { log.Println("reqPost Error:", err.Error()) } reqPost.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(reqPost) if err != nil { log.Println("resp Error:", err.Error()) } else { defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) err = json.Unmarshal(body, &nodes) if err != nil { log.Println("Unmarshal Error:", err.Error()) } log.Println("nodes =", nodes) } } }() log.Println("mq.Start ok. Waiting for messages.") <-forever }