Exemple #1
0
func main() {
	mlvl := metafora.LogLevelInfo
	hostname, _ := os.Hostname()

	peers := flag.String("etcd", "http://127.0.0.1:2379", "comma delimited etcd peer list")
	namespace := flag.String("namespace", "koalemos", "metafora namespace")
	name := flag.String("name", hostname, "node name or empty for automatic")
	loglvl := flag.String("log", mlvl.String(), "set log level: [debug], info, warn, error")
	flag.Parse()

	hosts := strings.Split(*peers, ",")
	etcdc := etcd.NewClient(hosts)

	switch strings.ToLower(*loglvl) {
	case "debug":
		mlvl = metafora.LogLevelDebug
	case "info":
		mlvl = metafora.LogLevelInfo
	case "warn":
		mlvl = metafora.LogLevelWarn
	case "error":
		mlvl = metafora.LogLevelError
	default:
		metafora.Warnf("Invalid log level %q - using %s", *loglvl, mlvl)
	}
	metafora.SetLogLevel(mlvl)

	conf := m_etcd.NewConfig(*name, *namespace, hosts)

	// Replace NewTask func with one that returns a *koalemos.Task
	conf.NewTaskFunc = func(id, value string) metafora.Task {
		t := koalemos.NewTask(id)
		if value == "" {
			return t
		}
		if err := json.Unmarshal([]byte(value), t); err != nil {
			metafora.Errorf("Unable to unmarshal task %s: %v", t.ID(), err)
			return nil
		}
		return t
	}

	hfunc := makeHandlerFunc(etcdc)
	ec, err := m_etcd.NewEtcdCoordinator(conf)
	if err != nil {
		metafora.Errorf("Error creating etcd coordinator: %v", err)
	}

	bal := m_etcd.NewFairBalancer(conf)
	c, err := metafora.NewConsumer(ec, hfunc, bal)
	if err != nil {
		metafora.Errorf("Error creating consumer: %v", err)
		os.Exit(2)
	}
	metafora.Infof(
		"Starting koalsmosd with etcd=%s; namespace=%s; name=%s; loglvl=%s",
		*peers, conf.Namespace, conf.Name, mlvl)
	consumerRunning := make(chan struct{})
	go func() {
		defer close(consumerRunning)
		c.Run()
	}()

	sigC := make(chan os.Signal, 1)
	signal.Notify(sigC, os.Interrupt, os.Kill, syscall.SIGTERM)
	select {
	case s := <-sigC:
		metafora.Infof("Received signal %s, shutting down", s)
	case <-consumerRunning:
		metafora.Warn("Consumer exited. Shutting down.")
	}
	c.Shutdown()
	metafora.Info("Shutdown")
}
Exemple #2
0
// Start the grid. Actors that were stopped from a previous exit
// of the grid but returned a "done" status of false will start
// to be scheduled. New actors can be scheduled with StartActor.
func (g *grid) Start() (<-chan bool, error) {
	g.mu.Lock()
	defer g.mu.Unlock()

	// Start only once.
	if g.started {
		return g.exit, nil
	}

	// Use the hostname as the node identifier.
	hostname, err := os.Hostname()
	if err != nil {
		return nil, err
	}
	nodeid := fmt.Sprintf("%s-%s", hostname, g.name)

	// Define the metafora new task function and config.
	conf := m_etcd.NewConfig(nodeid, g.name, g.etcdservers)
	conf.NewTaskFunc = func(id, value string) metafora.Task {
		def := NewActorDef(id)
		err := json.Unmarshal([]byte(value), def)
		if err != nil {
			log.Printf("error: failed to schedule actor: %v, error: %v", id, err)
			return nil
		}
		a, err := g.maker.MakeActor(def)
		if err != nil {
			log.Printf("error: failed to schedule actor: %v, error: %v", id, err)
			return nil
		}

		return newHandler(g.fork(), a)
	}

	// Create the metafora etcd coordinator.
	ec, err := m_etcd.NewEtcdCoordinator(conf)
	if err != nil {
		return nil, err
	}

	// Create the metafora consumer.
	c, err := metafora.NewConsumer(ec, handler(etcd.NewClient(g.etcdservers)), m_etcd.NewFairBalancer(conf))
	if err != nil {
		return nil, err
	}
	g.metaconsumer = c
	g.metaclient = m_etcd.NewClient(g.name, g.etcdservers)
	g.stopped = false
	g.started = true

	// Close the exit channel when metafora thinks
	// an exit is needed.
	go func() {
		defer close(g.exit)
		g.metaconsumer.Run()
	}()

	for i := 0; i < 2*runtime.NumCPU(); i++ {
		natsconn, err := g.newNatsConn()
		if err != nil {
			return nil, err
		}
		g.natsconnpool[i] = natsconn
		if i == 0 {
			g.natsconn = g.natsconnpool[0]
		}
	}

	return g.exit, nil
}