// 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, } }
// 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 }
// 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 }
// 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 }
// newDisseminator returns a new Disseminator instance. func newDisseminator(n *Node) *disseminator { d := &disseminator{ node: n, changes: make(map[string]*pChange), maxP: 1, pFactor: 15, logger: logging.Logger("disseminator").WithField("local", n.Address()), } return d }
// 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 }
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 }
// 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} }
// 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, } }
// 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 }
// 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 }
// 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 }