github.com/jbking/gohan@v0.0.0-20151217002006-b41ccf1c2a96/server/amqp.go (about) 1 // Copyright (C) 2015 NTT Innovation Institute, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package server 17 18 import ( 19 "encoding/json" 20 "fmt" 21 "os" 22 "strings" 23 "time" 24 25 "github.com/cloudwan/gohan/extension" 26 27 "github.com/cloudwan/gohan/schema" 28 "github.com/cloudwan/gohan/util" 29 "github.com/streadway/amqp" 30 "github.com/twinj/uuid" 31 ) 32 33 const connectionWait = 10 * time.Second 34 35 //AMQP Process 36 func startAMQPProcess(server *Server) { 37 config := util.GetConfig() 38 enableAMQP := config.GetParam("amqp", nil) 39 if enableAMQP == nil { 40 return 41 } 42 listenAMQP(server) 43 } 44 45 func listenAMQP(server *Server) { 46 47 hostname, _ := os.Hostname() 48 processID := hostname + uuid.NewV4().String() 49 config := util.GetConfig() 50 manager := schema.GetManager() 51 connection := config.GetString("amqp/connection", "amqp://guest:guest@127.0.0.1:5672/") 52 queues := config.GetStringList("amqp/queues", []string{"notifications.info", "notifications.error"}) 53 events := config.GetStringList("amqp/events", []string{}) 54 extensions := map[string]extension.Environment{} 55 for _, event := range events { 56 path := "amqp://" + event 57 env := newEnvironment(server.db, server.keystoneIdentity) 58 err := env.LoadExtensionsForPath(manager.Extensions, path) 59 if err != nil { 60 log.Fatal(fmt.Sprintf("Extensions parsing error: %v", err)) 61 } 62 extensions[event] = env 63 } 64 65 for _, queue := range queues { 66 go func(queue string) { 67 for server.running { 68 conn, err := amqp.Dial(connection) 69 if err != nil { 70 log.Error(fmt.Sprintf("[AMQP] connection error: %s", err)) 71 time.Sleep(connectionWait) 72 continue 73 } 74 defer conn.Close() 75 76 ch, err := conn.Channel() 77 if err != nil { 78 log.Error(fmt.Sprintf("[AMQP] channel: %s", err)) 79 return 80 } 81 defer ch.Close() 82 q, err := ch.QueueDeclare( 83 queue, // name 84 false, // durable 85 false, // delete when usused 86 false, // exclusive 87 false, // no-wait 88 nil, // arguments 89 ) 90 if err != nil { 91 log.Error(fmt.Sprintf("[AMQP] queue declare error: %s", err)) 92 return 93 } 94 95 for server.running { 96 msgs, err := ch.Consume( 97 q.Name, // queue 98 "gohan-"+processID+"-"+queue, // consumer 99 true, // auto-ack 100 false, // exclusive 101 false, // no-local 102 false, // no-wait 103 nil, // args 104 ) 105 106 if err != nil { 107 log.Error(fmt.Sprintf("[AMQP] consume queue error: %s", err)) 108 break 109 } 110 for d := range msgs { 111 var message map[string]interface{} 112 err = json.Unmarshal(d.Body, &message) 113 log.Debug(fmt.Sprintf("Received a message: %s %s", queue, d.Body)) 114 if err != nil { 115 log.Error(fmt.Sprintf("[AMQP] json decode error: %s", err)) 116 continue 117 } 118 eventType, ok := message["event_type"].(string) 119 if !ok { 120 log.Error("[AMQP] wrong event type") 121 continue 122 } 123 for _, event := range events { 124 if strings.HasPrefix(eventType, event) { 125 env := extensions[event] 126 127 context := map[string]interface{}{ 128 "event": message, 129 } 130 if err := env.HandleEvent("notification", context); err != nil { 131 log.Warning(fmt.Sprintf("extension error: %s", err)) 132 } 133 } 134 } 135 } 136 } 137 } 138 }(queue) 139 } 140 } 141 142 //AMQP Process 143 func stopAMQPProcess(server *Server) { 144 }