Exemple #1
0
// New returns a new Ringpop instance.
func New(app string, opts ...Option) (*Ringpop, error) {
	var err error

	ringpop := &Ringpop{
		config: &configuration{
			App: app,
		},
		logger: logging.Logger("ringpop"),
	}

	err = applyOptions(ringpop, defaultOptions)
	if err != nil {
		panic(fmt.Errorf("Error applying default Ringpop options: %v", err))
	}

	err = applyOptions(ringpop, opts)
	if err != nil {
		return nil, err
	}

	errs := checkOptions(ringpop)
	if len(errs) != 0 {
		return nil, fmt.Errorf("%v", errs)
	}

	ringpop.setState(created)

	return ringpop, nil
}
// NewRequestSender returns a new request sender that can be used to forward a request to its destination
func newRequestSender(sender Sender, emitter eventEmitter, channel shared.SubChannel, request []byte, keys []string,
	destination, service, endpoint string, format tchannel.Format, opts *Options) *requestSender {

	logger := logging.Logger("sender")
	if identity, err := sender.WhoAmI(); err != nil {
		logger = logger.WithField("local", identity)
	}

	return &requestSender{
		sender:         sender,
		emitter:        emitter,
		channel:        channel,
		request:        request,
		keys:           keys,
		destination:    destination,
		service:        service,
		endpoint:       endpoint,
		format:         format,
		timeout:        opts.Timeout,
		maxRetries:     opts.MaxRetries,
		retrySchedule:  opts.RetrySchedule,
		rerouteRetries: opts.RerouteRetries,
		logger:         logger,
	}
}
Exemple #3
0
// newExponentialDelayer creates a new exponential delayer. joiner is required.
// opts is optional.
func newExponentialDelayer(joiner string, opts *delayOpts) (*exponentialDelayer, error) {
	if opts == nil {
		opts = newDelayOpts()
	}

	randomizer := opts.randomizer
	if randomizer == nil {
		randomizer = defaultRandomizer
	}

	sleeper := opts.sleeper
	if sleeper == nil {
		sleeper = defaultSleeper
	}

	return &exponentialDelayer{
		logger:          logging.Logger("join").WithField("local", joiner),
		initialDelay:    opts.initial,
		nextDelayMin:    0,
		maxDelayReached: false,
		maxDelay:        opts.max,
		randomizer:      randomizer,
		sleeper:         sleeper,
		numDelays:       0,
	}, nil
}
Exemple #4
0
// NewPingSender returns a new PingSender that can be used to send a ping to target node
func newPingSender(node *Node, target string, timeout time.Duration) *pingSender {
	ps := &pingSender{
		node:    node,
		target:  target,
		timeout: timeout,
		logger:  logging.Logger("ping").WithField("local", node.Address()),
	}

	return ps
}
Exemple #5
0
// newDisseminator returns a new Disseminator instance.
func newDisseminator(n *Node) *disseminator {
	d := &disseminator{
		node:    n,
		changes: make(map[string]*pChange),
		maxP:    defaultPFactor,
		pFactor: defaultPFactor,
		logger:  logging.Logger("disseminator").WithField("local", n.Address()),
	}

	return d
}
Exemple #6
0
// newSuspicion returns a new suspicion SWIM sub-protocol with the given timeout
func newSuspicion(n *Node, timeout time.Duration) *suspicion {
	suspicion := &suspicion{
		node:    n,
		timeout: timeout,
		timers:  make(map[string]*time.Timer),
		enabled: true,
		logger:  logging.Logger("suspicion").WithField("local", n.Address()),
	}

	return suspicion
}
Exemple #7
0
func newUpdateRollup(node *Node, flushInterval time.Duration, maxUpdates int) *updateRollup {
	rollup := &updateRollup{
		node:          node,
		maxUpdates:    maxUpdates,
		flushInterval: flushInterval,
		logger:        logging.Logger("rollup").WithField("local", node.Address()),
	}

	rollup.buffer.updates = make(map[string][]Change)

	return rollup
}
Exemple #8
0
// NewReplicator returns a new Replicator instance that makes calls with the given
// SubChannel to the service defined by SubChannel.GetServiceName(). The given n/w/r
// values will be used as defaults for the replicator when none are provided
// Deprecation: logger is no longer used.
func NewReplicator(s Sender, channel shared.SubChannel, logger log.Logger,
	opts *Options) *Replicator {

	f := forward.NewForwarder(s, channel)

	opts = mergeDefaultOptions(opts, &Options{3, 1, 3, Parallel})
	logger = logging.Logger("replicator")
	if identity, err := s.WhoAmI(); err == nil {
		logger = logger.WithField("local", identity)
	}
	return &Replicator{s, channel, f, logger, opts}
}
Exemple #9
0
// NewForwarder returns a new forwarder
func NewForwarder(s Sender, ch shared.SubChannel) *Forwarder {

	logger := logging.Logger("forwarder")
	if identity, err := s.WhoAmI(); err == nil {
		logger = logger.WithField("local", identity)
	}

	return &Forwarder{
		sender:  s,
		channel: ch,
		logger:  logger,
	}
}
Exemple #10
0
// newGossip returns a new gossip SWIM sub-protocol with the given protocol period
func newGossip(node *Node, minProtocolPeriod time.Duration) *gossip {
	gossip := &gossip{
		node:              node,
		minProtocolPeriod: minProtocolPeriod,
		logger:            logging.Logger("gossip").WithField("local", node.Address()),
	}

	gossip.SetStopped(true)
	gossip.protocol.timing = metrics.NewHistogram(metrics.NewUniformSample(10))
	gossip.protocol.timing.Update(int64(gossip.minProtocolPeriod))

	return gossip
}
Exemple #11
0
// newJoinSender returns a new JoinSender to join a cluster with
func newJoinSender(node *Node, opts *joinOpts) (*joinSender, error) {
	if opts == nil {
		opts = &joinOpts{}
	}

	if opts.discoverProvider == nil {
		return nil, errors.New("missing host provider in join options")
	}

	// Resolve/retrieve bootstrap hosts from the provider specified in the
	// join options.
	bootstrapHosts, err := opts.discoverProvider.Hosts()
	if err != nil {
		return nil, err
	}
	if len(bootstrapHosts) == 0 {
		return nil, errors.New("bootstrap hosts cannot be empty")
	}

	js := &joinSender{
		node:   node,
		logger: logging.Logger("join").WithField("local", node.Address()),
	}

	// Parse bootstrap hosts into a map
	js.parseHosts(bootstrapHosts)

	js.potentialNodes = js.CollectPotentialNodes(nil)

	js.timeout = util.SelectDuration(opts.timeout, defaultJoinTimeout)
	js.maxJoinDuration = util.SelectDuration(opts.maxJoinDuration, defaultMaxJoinDuration)
	js.parallelismFactor = util.SelectInt(opts.parallelismFactor, defaultParallelismFactor)
	js.size = util.SelectInt(opts.size, defaultJoinSize)
	js.size = util.Min(js.size, len(js.potentialNodes))
	js.delayer = opts.delayer

	if js.delayer == nil {
		// Create and use exponential delayer as the delay mechanism. Create it
		// with nil opts which uses default delayOpts.
		js.delayer, err = newExponentialDelayer(js.node.address, nil)
		if err != nil {
			return nil, err
		}
	}

	return js, nil
}
Exemple #12
0
// NewNode returns a new SWIM Node.
func NewNode(app, address string, channel shared.SubChannel, opts *Options) *Node {
	// use defaults for options that are unspecified
	opts = mergeDefaultOptions(opts)

	node := &Node{
		address: address,
		app:     app,
		channel: channel,
		logger:  logging.Logger("node").WithField("local", address),

		joinTimeout:        opts.JoinTimeout,
		pingTimeout:        opts.PingTimeout,
		pingRequestTimeout: opts.PingRequestTimeout,

		pingRequestSize: opts.PingRequestSize,

		clientRate: metrics.NewMeter(),
		serverRate: metrics.NewMeter(),
		totalRate:  metrics.NewMeter(),
		clock:      opts.Clock,
	}

	node.memberlist = newMemberlist(node)
	node.memberiter = newMemberlistIter(node.memberlist)
	node.suspicion = newSuspicion(node, opts.SuspicionTimeout)
	node.gossip = newGossip(node, opts.MinProtocolPeriod)
	node.disseminator = newDisseminator(node)
	node.rollup = newUpdateRollup(node, opts.RollupFlushInterval,
		opts.RollupMaxUpdates)

	if node.channel != nil {
		node.registerHandlers()
		node.service = node.channel.ServiceName()
	}

	return node
}