2017-09-23 01:22:21 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2017-10-15 17:45:55 +02:00
|
|
|
"net/http"
|
2017-09-23 01:22:21 +02:00
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"strings"
|
|
|
|
"syscall"
|
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
kitconsul "github.com/go-kit/kit/sd/consul"
|
|
|
|
stdconsul "github.com/hashicorp/consul/api"
|
|
|
|
"github.com/mainflux/mainflux"
|
2017-09-23 01:22:21 +02:00
|
|
|
"github.com/mainflux/mainflux/writer"
|
|
|
|
"github.com/mainflux/mainflux/writer/cassandra"
|
|
|
|
nats "github.com/nats-io/go-nats"
|
2017-10-15 17:45:55 +02:00
|
|
|
uuid "github.com/satori/go.uuid"
|
2017-09-24 03:46:56 +02:00
|
|
|
"go.uber.org/zap"
|
2017-09-23 01:22:21 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2017-10-15 17:45:55 +02:00
|
|
|
port int = 9001
|
|
|
|
dbKey string = "cassandra"
|
|
|
|
natsKey string = "nats"
|
|
|
|
sep string = ","
|
|
|
|
keyspace string = "message_writer"
|
|
|
|
group string = "writers"
|
|
|
|
subject string = "msg.*"
|
2017-09-23 01:22:21 +02:00
|
|
|
)
|
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
var (
|
|
|
|
kv *stdconsul.KV
|
|
|
|
logger *zap.Logger
|
|
|
|
)
|
2017-09-23 01:22:21 +02:00
|
|
|
|
|
|
|
func main() {
|
2017-09-24 03:46:56 +02:00
|
|
|
logger, _ = zap.NewProduction()
|
|
|
|
defer logger.Sync()
|
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
consulAddr := os.Getenv("CONSUL_ADDR")
|
|
|
|
if consulAddr == "" {
|
|
|
|
logger.Fatal("Cannot start the service: CONSUL_ADDR not set.")
|
|
|
|
}
|
|
|
|
|
|
|
|
consul, err := stdconsul.NewClient(&stdconsul.Config{
|
|
|
|
Address: consulAddr,
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
status := fmt.Sprintf("Cannot connect to Consul due to %s", err)
|
|
|
|
logger.Fatal(status)
|
|
|
|
}
|
|
|
|
|
|
|
|
kv = consul.KV()
|
|
|
|
|
|
|
|
asr := &stdconsul.AgentServiceRegistration{
|
|
|
|
ID: uuid.NewV4().String(),
|
|
|
|
Name: "writer",
|
|
|
|
Tags: []string{},
|
|
|
|
Port: port,
|
|
|
|
Address: "",
|
|
|
|
EnableTagOverride: false,
|
|
|
|
}
|
|
|
|
|
|
|
|
sd := kitconsul.NewClient(consul)
|
|
|
|
if err = sd.Register(asr); err != nil {
|
|
|
|
status := fmt.Sprintf("Cannot register service due to %s", err)
|
|
|
|
logger.Fatal(status)
|
|
|
|
}
|
|
|
|
|
|
|
|
hosts := strings.Split(get(dbKey), sep)
|
|
|
|
session, err := cassandra.Connect(hosts, keyspace)
|
|
|
|
if err != nil {
|
|
|
|
logger.Fatal("Cannot connect to DB.", zap.Error(err))
|
|
|
|
}
|
2017-09-23 01:22:21 +02:00
|
|
|
defer session.Close()
|
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
nc, err := nats.Connect(get(natsKey))
|
|
|
|
if err != nil {
|
|
|
|
logger.Fatal("Cannot connect to NATS.", zap.Error(err))
|
|
|
|
}
|
2017-09-23 01:22:21 +02:00
|
|
|
defer nc.Close()
|
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
if err := cassandra.Initialize(session); err != nil {
|
|
|
|
logger.Fatal("Cannot initialize message repository.", zap.Error(err))
|
|
|
|
}
|
|
|
|
|
|
|
|
repo := cassandra.NewMessageRepository(session)
|
2017-09-23 01:22:21 +02:00
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
nc.QueueSubscribe(subject, group, func(m *nats.Msg) {
|
2017-09-29 00:42:45 +02:00
|
|
|
msg := writer.RawMessage{}
|
2017-09-23 01:22:21 +02:00
|
|
|
|
2017-09-29 00:42:45 +02:00
|
|
|
if err := json.Unmarshal(m.Data, &msg); err != nil {
|
|
|
|
logger.Error("Failed to unmarshal raw message.", zap.Error(err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := repo.Save(msg); err != nil {
|
|
|
|
logger.Error("Failed to save message.", zap.Error(err))
|
2017-09-23 01:22:21 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
errChan := make(chan error, 10)
|
2017-09-23 01:22:21 +02:00
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
go func() {
|
|
|
|
server := &http.Server{
|
|
|
|
Addr: fmt.Sprintf(":%d", port),
|
|
|
|
Handler: mainflux.Version(),
|
|
|
|
}
|
2017-09-23 01:22:21 +02:00
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
logger.Info("Writer started.")
|
2017-09-23 01:22:21 +02:00
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
errChan <- server.ListenAndServe()
|
|
|
|
}()
|
2017-09-23 01:22:21 +02:00
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
sigChan := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
2017-09-23 01:22:21 +02:00
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case err := <-errChan:
|
|
|
|
status := fmt.Sprintf("Writer terminated due to %s", err)
|
|
|
|
logger.Fatal(status)
|
|
|
|
case <-sigChan:
|
|
|
|
logger.Info("Writer terminated.")
|
|
|
|
}
|
2017-09-23 01:22:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
func get(key string) string {
|
|
|
|
pair, _, err := kv.Get(key, nil)
|
|
|
|
if err != nil {
|
|
|
|
status := fmt.Sprintf("Cannot retrieve %s due to %s", key, err)
|
|
|
|
logger.Fatal(status)
|
2017-10-15 14:05:05 +02:00
|
|
|
}
|
|
|
|
|
2017-10-15 17:45:55 +02:00
|
|
|
return string(pair.Value)
|
2017-09-23 01:22:21 +02:00
|
|
|
}
|