function join (instance, config, done) { config = config || {} if (!config.pin && !config.pins) { config.pin = 'null:true' } var instance_sneeze_opts = _.clone(sneeze_opts) instance_sneeze_opts.identifier = sneeze_opts.identifier + '~' + seneca.util.pincanon(config.pin || config.pins) + '~' + Date.now() sneeze = Sneeze(instance_sneeze_opts) var meta = { config: config, instance: instance.id } sneeze.on('error', function (err) { seneca.log.warn(err) }) sneeze.on('add', add_client) sneeze.on('remove', remove_client) sneeze.on('ready', done) seneca.add('role:seneca,cmd:close', function (msg, done) { closed = true if (sneeze) { sneeze.leave() } this.prior(msg, done) }) seneca.add('role:mesh,get:members', function get_members (msg, done) { var members = [] _.each(sneeze.members(), function (member) { var m = options.make_entry(member) members.push(void 0 === m ? default_make_entry(member) : m) }) this.prior(msg, function (err, out) { if (err) { done(err) } var list = out && out.list || [] var outlist = list.concat(members) done(null, {list: outlist}) }) }) sneeze.join(meta) function add_client (meta) { if (closed) return var config = meta.config || {} var pins = config.pins || config.pin || [] pins = _.isArray(pins) ? pins : [pins] _.each(pins, function (pin) { var pin_id = instance.util.pattern(pin) var has_balance_client = !!balance_map[pin_id] var target_map = (balance_map[pin_id] = balance_map[pin_id] || {}) var pin_config = _.clone(config) delete pin_config.pins delete pin_config.pin pin_config.pin = pin_id var id = instance.util.pattern(pin_config) + '~' + meta.identifier$ // this is a duplicate, so ignore if (target_map[id]) { return } pin_config.id = id // TODO: how to handle local override? var actmeta = instance.find(pin) var ignore_client = !!(actmeta && !actmeta.client) if (ignore_client) { return } if (!has_balance_client) { // no balancer for this pin, so add one instance.root.client({type: 'balance', pin: pin, model: config.model}) } target_map[id] = true instance.act( 'role:transport,type:balance,add:client', {config: pin_config}) }) } function remove_client (meta) { if (closed) return var config = meta.config || {} var pins = config.pins || config.pin || [] pins = _.isArray(pins) ? pins : [pins] _.each(pins, function (pin) { var pin_id = instance.util.pattern(pin) var pin_config = _.clone(config) delete pin_config.pins delete pin_config.pin pin_config.pin = pin_id var id = instance.util.pattern(pin_config) + '~' + meta.identifier$ pin_config.id = id var target_map = balance_map[pin_id] if (target_map) { delete target_map[id] } instance.act( 'role:transport,type:balance,remove:client', {config: pin_config}) }) } }
function join(instance, raw_config, done) { var client_instance = instance.root.delegate() var config = seneca.util.clean(raw_config || {}, {proto:false}) if (!config.pin && !config.pins) { config.pin = 'null:true' } config.pin = intern.resolve_pins(instance, config) delete config.pins var instance_sneeze_opts = _.clone(sneeze_opts) instance_sneeze_opts.identifier = sneeze_opts.identifier + '~' + config.pin + '~' + Date.now() sneeze = Sneeze(instance_sneeze_opts) var meta = { config: seneca.util.clean(config), instance: instance.id } sneeze.on('error', function(err) { seneca.log.warn(err) }) sneeze.on('add', add_client) sneeze.on('remove', remove_client) sneeze.on('ready', done) seneca.add('role:seneca,cmd:close', function(msg, done) { closed = true if (sneeze) { sneeze.leave() } this.prior(msg, done) }) seneca.add('role:mesh,get:members', function get_members(msg, done) { var members = [] _.each(sneeze.members(), function(member) { var m = options.make_entry(member) members.push(void 0 === m ? intern.default_make_entry(member) : m) }) this.prior(msg, function(err, out) { if (err) { done(err) } var list = (out && out.list) || [] var outlist = list.concat(members) done(null, { list: outlist }) }) }) sneeze.join(meta) function add_client(meta) { if (closed) return // ignore myself if (client_instance.id === meta.instance) { return } var config = meta.config || {} var pins = intern.resolve_pins(client_instance, config) _.each(pins, function(pin) { var pin_config = intern.make_pin_config( client_instance, meta, pin, config ) var has_balance_client = !!balance_map[pin_config.pin] var target_map = (balance_map[pin_config.pin] = balance_map[ pin_config.pin ] || {}) // this is a duplicate, so ignore if (target_map[pin_config.id]) { return } // TODO: how to handle local override? var actmeta = client_instance.find(pin) var ignore_client = !!(actmeta && !actmeta.client) if (ignore_client) { return } target_map[pin_config.id] = true if (!has_balance_client) { // no balancer for this pin, so add one client_instance.client({ type: 'balance', pin: pin, model: config.model }) } client_instance.act('role:transport,type:balance,add:client', { config: pin_config }) }) } function remove_client(meta) { if (closed) return // ignore myself if (client_instance.id === meta.instance) { return } var config = meta.config || {} var pins = intern.resolve_pins(client_instance, config) _.each(pins, function(pin) { var pin_config = intern.make_pin_config( client_instance, meta, pin, config ) var target_map = balance_map[pin_config.pin] if (target_map) { delete target_map[pin_config.id] } client_instance.act('role:transport,type:balance,remove:client', { config: pin_config, meta:meta }) }) } }