func (n *Node) AddRule(rule *rules.Rule) error {
	if err := rule.Validate(); err != nil {
		return err
	}
	return n.store.addRule(rule)
}
AddRule adds a rule to the store
package store
import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/myntra/cortex/pkg/executions"
	"github.com/myntra/cortex/pkg/js"
	"github.com/golang/glog"
	"github.com/hashicorp/raft"
	"github.com/myntra/cortex/pkg/config"
	"github.com/myntra/cortex/pkg/events"
	"github.com/myntra/cortex/pkg/rules"
	"github.com/myntra/cortex/pkg/util"
)
type Node struct {
	mu    sync.RWMutex
	store *defaultStore
}
func NewNode(cfg *config.Config) (*Node, error) {
	glog.Infof("NewNode %v\n", cfg)
	if err := cfg.Validate(); err != nil {
		return nil, fmt.Errorf("invalid config: %v", err)
	}
	store, err := newStore(cfg)
	if err != nil {
		return nil, err
	}
	node := &Node{store: store}
	return node, nil
}
func (n *Node) Start() error {
	return n.store.open()
}
func (n *Node) Shutdown() error {
	n.mu.Lock()
	defer n.mu.Unlock()
	err := n.store.close()
	if err != nil {
		glog.Errorf("error shutting down node %v\n", err)
		return err
	}
	time.Sleep(time.Second)
	glog.Info("node shut down")
	return nil
}
func (n *Node) LeaderAddr() string {
	if n.store.raft.State() == raft.Leader {
		return ""
	}
	raftAddress := string(n.store.raft.Leader())
	fields := strings.Split(raftAddress, ":")
	if len(fields) == 0 || len(fields) != 2 {
		glog.Errorf("invalid raftAddress %v", raftAddress)
		return ""
	}
	raftPortStr := fields[1]
	raftPort, err := strconv.Atoi(raftPortStr)
	if err != nil {
		glog.Errorf("invalid port %v %v", raftAddress, raftPortStr)
		return ""
	}
	tcpPort := raftPort + 1
	tcpURL := fields[0]
	if tcpURL == "" {
		tcpURL = "0.0.0.0"
	}
	glog.Info("LeaderAddr ", tcpURL, tcpPort)
	tcpAddr := fmt.Sprintf("%s:%d", tcpURL, tcpPort)
	return tcpAddr
}