Produced by Araxis Merge on 10/4/2017 8:38:10 AM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.
| # | Location | File | Last Modified |
|---|---|---|---|
| 1 | solr-smart-client.zip\solr-smart-client | solr-smart-client.js | Mon Aug 28 19:30:59 2017 UTC |
| 2 | solr-smart-client.zip\solr-smart-client | solr-smart-client.js | Wed Oct 4 13:31:53 2017 UTC |
| Description | Between Files 1 and 2 |
|
|---|---|---|
| Text Blocks | Lines | |
| Unchanged | 8 | 1272 |
| Changed | 7 | 22 |
| Inserted | 0 | 0 |
| Removed | 0 | 0 |
| Whitespace | |
|---|---|
| Character case | Differences in character case are significant |
| Line endings | Differences in line endings (CR and LF characters) are ignored |
| CR/LF characters | Not shown in the comparison detail |
No regular expressions were active.
| 1 | 'use stric t'; | |
| 2 | ||
| 3 | /* | |
| 4 | This class handles c onnecting to ZooKeep er, lookin g up and c onnecting to a Solr server, | |
| 5 | and perfor ming opera tions agai nst that s erver. Thi s class au tomaticall y connects to | |
| 6 | ZooKeeper, and will attempt to reconnect if ZooKee per goes d own. In th e event th at the | |
| 7 | SolrSmartC lient cann ot connect to ZooKee per within the timeo ut period, it will r eturn | |
| 8 | an error i n the call back. | |
| 9 | ||
| 10 | Currently, this impl ementation does not listen for (ZooKeepe r) node ev ents, as i t does | |
| 11 | not appear to be nec essary giv en the cur rent requi rements. | |
| 12 | ||
| 13 | Note that it is not necessary to pass a value for the 'agent ' paramete r in the c onstructor | |
| 14 | function o r for eith er of the factory fu nctions. I n this cas e, no Keep -alive Age nt will be | |
| 15 | used. | |
| 16 | */ | |
| 17 | ||
| 18 | ||
| 19 | const _ = require('u nderscore' ); | |
| 20 | const solr ClientModu le = requi re('solr-c lient'); | |
| 21 | const zook eeper = re quire('nod e-zookeepe r-client') ; | |
| 22 | ||
| 23 | const CHIL D_INSTANCE _ENABLED = true; | |
| 24 | const DATA _TIMEOUT_M ILLIS = 30 000; | |
| 25 | const WAIT _LOOP_DELA Y_MILLIS = 100; | |
| 26 | const REQU ERY_LOOP_D ELAY_MILLI S = 1000; | |
| 27 | const CORE = 'vpr'; | |
| 28 | const PATH = '/colle ctions/vpr /state.jso n'; | |
| 29 | const NODE _EVENT_LOG _LEVEL = ' debug'; | |
| 30 | const ZOOK EEPER_EVEN T_LOG_LEVE L = 'debug '; | |
| 31 | ||
| 32 | /* | |
| 33 | Variadic F unction: | |
| 34 | function S olrSmartCl ient(logge r, config, agent, pa rentDataWr apper) | |
| 35 | function S olrSmartCl ient(logge r, config, agent) | |
| 36 | ||
| 37 | IMPORTANT: If you ma nually cre ate an ins tance of S olrSmartCl ient direc tly by usi ng this co nstructor, | |
| 38 | you MUST c all start( ) for the SolrSmartC lient inst ance to co nnect to Z ookeeper. | |
| 39 | ||
| 40 | logger - a bunyan ty pe logger | |
| 41 | config - t he connect ion and co nfiguratio n properti es | |
| 42 | agent - HT TP Agent w hich is us ed for poo ling socke ts used in HTTP(s) c lient requ ests | |
| 43 | Th is paramet er is opti onal | |
| 44 | parentData Wrapper = optional o bject. If a value is passed th en this is a child i nstance an d | |
| 45 | it will not attempt an y connecti on managem ent (as th at is hand led by the parent) | |
| 46 | an d will onl y return d ata. This parameter should onl y be passe d when the construct or | |
| 47 | is called by the child Instance() method. | |
| 48 | ||
| 49 | config sho uld be an object as follows: | |
| 50 | ||
| 51 | let config = { | |
| 52 | childIns tanceEnabl ed, // if false, chi ldInstance () returns "this" | |
| 53 | dataTime outMillis, // the am ount of ti me to wait for ZooKe eper data | |
| 54 | waitLoop DelayMilli s, // the amount of time betwe en each lo op when wa iting for valid data | |
| 55 | requeryL oopDelayMi llis, // t he amount of time be tween each attempt t o call get Data() aft er an erro r | |
| 56 | core. // the solr core, e.g. 'vpr' | |
| 57 | zooKeepe rConnectio n, // conn ection str ing for Zo oKeeper, e .g. 'local host:2183, localhost: 2182,local host:2181' | |
| 58 | path, // ZooKeeper path to n ode with c luster sta tus | |
| 59 | nodeEven tLogLevel, // bunyan log level at which ZooKeeper Node Event s will be logged | |
| 60 | zookeepe rEventLogL evel, // b unyan log level at w hich ZooKe eper Event s will be logged | |
| 61 | zooKeepe rOptions: { // this node and a ll of the values it contains a re optiona l | |
| 62 | spinDe lay: // a millisecon d value - zookeeper client wil l default to 1000 | |
| 63 | sessio nTimeout: // a milli second val ue - zooke eper clien t will def ault to 30 000 | |
| 64 | retrie s: // zook eeper clie nt will de fault to 0 - SEE BEL OW BEFORE SETTING TH IS | |
| 65 | sessio nId: // zo okeeper cl ient will default to undefined | |
| 66 | sessio nPassword: // zookee per client will defa ult to und efined | |
| 67 | } | |
| 68 | }; | |
| 69 | ||
| 70 | RETRIES VA LUE | |
| 71 | The Zookee per client uses an a lgorithm t hat geomet rically in creases th e delay be tween each | |
| 72 | retry as f ollows: | |
| 73 | Math.m in(1000 * Math.pow(2 , attempts ), session Timeout) | |
| 74 | */ | |
| 75 | ||
| 76 | class Solr SmartClien t { | |
| 77 | construc tor(logger , config, agent, par entDataWra pper) { | |
| 78 | if (!n ew.target) { | |
| 79 | retu rn new Sol rSmartClie nt(logger, config, a gent, pare ntDataWrap per); | |
| 80 | } | |
| 81 | ||
| 82 | logger .debug('so lr-smart-c lient.Solr SmartClien t()'); | |
| 83 | ||
| 84 | this.l ogger = lo gger; | |
| 85 | this.c onfig = co nfig; | |
| 86 | this.a gent = age nt; | |
| 87 | this.c hild = !!p arentDataW rapper; | |
| 88 | this.z kClient = null; | |
| 89 | ||
| 90 | this.c onfig.chil dInstanceE nabled = _ .has(confi g, 'childI nstanceEna bled') ? c onfig.chil dInstanceE nabled : C HILD_INSTA NCE_ENABLE D; | |
| 91 | this.c onfig.data TimeoutMil lis = _.ha s(config, 'dataTimeo utMillis') ? config. dataTimeou tMillis : DATA_TIMEO UT_MILLIS; | |
| 92 | this.c onfig.wait LoopDelayM illis = _. has(config , 'waitLoo pDelayMill is') ? con fig.waitLo opDelayMil lis : WAIT _LOOP_DELA Y_MILLIS; | |
| 93 | this.c onfig.requ eryLoopDel ayMillis = _.has(con fig, 'requ eryLoopDel ayMillis') ? config. requeryLoo pDelayMill is : REQUE RY_LOOP_DE LAY_MILLIS ; | |
| 94 | this.c onfig.core = config. core || CO RE; | |
| 95 | this.c onfig.path = config. path || PA TH; | |
| 96 | this.c onfig.zooK eeperConne ction = co nfig.zooKe eperConnec tion; | |
| 97 | this.c onfig.node EventLogLe vel = conf ig.nodeEve ntLogLevel || NODE_E VENT_LOG_L EVEL; | |
| 98 | this.c onfig.zook eeperEvent LogLevel = config.zo okeeperEve ntLogLevel || ZOOKEE PER_EVENT_ LOG_LEVEL; | |
| 99 | this.c onfig.zooK eeperOptio ns = confi g.zooKeepe rOptions; | |
| 100 | ||
| 101 | ||
| 102 | // Thi s wrapper object all ows the Zo okeeper da ta to be p assed by r eference | |
| 103 | // fro m parent t o child an d child to parent. T his way, t he parent and child | |
| 104 | // ins tances all share the same zook eeper conn ection. | |
| 105 | // IMP ORTANT: Do not set t hese value s manually ! Only set them in r esponse | |
| 106 | // to a Zookeepe r event or a Zookeep er Node ev ent! | |
| 107 | this.d ataWrapper = parentD ataWrapper || { | |
| 108 | data : undefine d, | |
| 109 | vali d: false | |
| 110 | }; | |
| 111 | } | |
| 112 | ||
| 113 | ||
| 114 | /* | |
| 115 | This met hod create s a child instance o f the curr ent SolrSm artClient instance. | |
| 116 | A child instance o nly uses t he 'dataWr apper' obj ect and as sumes that Zookeeper | |
| 117 | connecti on, event, and error handling will be pe rformed by the paren t instance . | |
| 118 | ||
| 119 | The purp ose of thi s method i s to allow instance- specific l ogging wit hout addin g | |
| 120 | addition al Zookeep er connect ion overhe ad. | |
| 121 | ||
| 122 | IMPORTAN T: DO NOT call start () on inst ances of S olrSmartCl ient creat ed with th is | |
| 123 | method. The Zookee per connec tion manag ement will be handle d exclusiv ely by the | |
| 124 | parent i nstance. | |
| 125 | */ | |
| 126 | childIns tance(chil dLogger) { | |
| 127 | this.l ogger.debu g('solr-sm art-client .childInst ance() chi ldInstance Enabled? % s', this.c onfig.chil dInstanceE nabled); | |
| 128 | ||
| 129 | if (!t his.config .childInst anceEnable d) { | |
| 130 | this .logger.de bug('solr- smart-clie nt.childIn stance() c hildInstan ceEnabled false, ret urning "th is"'); | |
| 131 | retu rn this; | |
| 132 | } | |
| 133 | ||
| 134 | return new SolrS martClient (childLogg er, this.c onfig, thi s.agent, t his.dataWr apper); | |
| 135 | } | |
| 136 | ||
| 137 | ||
| 138 | /* | |
| 139 | Add a do cument or a list of documents | |
| 140 | ||
| 141 | docs - d ocument or list of d ocuments t o add into the Solr database | |
| 142 | callback - a funct ion execut ed when th e Solr ser ver respon ds or an e rror occur s | |
| 143 | */ | |
| 144 | add(docs , callback ) { | |
| 145 | this.l ogger.debu g('solr-sm art-client .add(): %j ', docs); | |
| 146 | this._ executeSol rCommand(' add', docs , callback ); | |
| 147 | } | |
| 148 | ||
| 149 | ||
| 150 | /* | |
| 151 | Delete a ll documen ts | |
| 152 | ||
| 153 | callback - a funct ion execut ed when th e Solr ser ver respon ds or an e rror occur s | |
| 154 | */ | |
| 155 | deleteAl l(callback ) { | |
| 156 | this.l ogger.debu g('solr-sm art-client .deleteAll ()'); | |
| 157 | this._ executeSol rCommand(' deleteByQu ery', '*:* ', callbac k); | |
| 158 | } | |
| 159 | ||
| 160 | ||
| 161 | /* | |
| 162 | Delete d ocuments m atching th e given `q uery` | |
| 163 | ||
| 164 | query - solr query | |
| 165 | callback - a funct ion execut ed when th e Solr ser ver respon ds or an e rror occur s | |
| 166 | */ | |
| 167 | deleteBy Query(quer y, callbac k) { | |
| 168 | this.l ogger.debu g('solr-sm art-client .deleteByQ uery(%j)', query); | |
| 169 | this._ executeSol rCommand(' deleteByQu ery', quer y, callbac k); | |
| 170 | } | |
| 171 | ||
| 172 | ||
| 173 | /* | |
| 174 | Search d ocuments m atching th e `query` | |
| 175 | ||
| 176 | query - solr query | |
| 177 | callback - a funct ion execut ed when th e Solr ser ver respon ds or an e rror occur s | |
| 178 | */ | |
| 179 | search(q uery, call back) { | |
| 180 | this.l ogger.debu g('solr-sm art-client .search(%j )', query) ; | |
| 181 | this._ executeSol rCommand(' search', q uery, call back); | |
| 182 | } | |
| 183 | ||
| 184 | ||
| 185 | /* | |
| 186 | Send an arbitrary HTTP GET r equest to Solr on th e specifie d `handler ` (as Solr like to c all it i.e path) | |
| 187 | ||
| 188 | handler - a Solr p ath | |
| 189 | query - Solr query | |
| 190 | callback - a funct ion execut ed when th e Solr ser ver respon ds or an e rror occur s | |
| 191 | */ | |
| 192 | get(hand ler, query , callback ) { | |
| 193 | this.l ogger.debu g('solr-sm art-client .get(%j, % j)', handl er, query) ; | |
| 194 | this._ executeSol rCommand(' get', [han dler, quer y], callba ck); | |
| 195 | } | |
| 196 | ||
| 197 | ||
| 198 | /* | |
| 199 | Commit l ast added and remove d document s, that me ans your d ocuments a re now ind exed. | |
| 200 | This isn 't strictl y necessar y for norm al operati ons, but c ommitting updates wi ll | |
| 201 | cause th em to be a pplied mor e immediat ely (this will likel y be neces sary for i ntegration | |
| 202 | tests wh ich involv e data bei ng updated in Solr). | |
| 203 | ||
| 204 | callback - a funct ion execut ed when th e Solr ser ver respon ds or an e rror occur s | |
| 205 | */ | |
| 206 | commit(c allback) { | |
| 207 | this.l ogger.debu g('solr-sm art-client .commit()' ); | |
| 208 | this._ executeSol rCommand(' commit', c allback); | |
| 209 | } | |
| 210 | ||
| 211 | ||
| 212 | /* | |
| 213 | Ping the server vi a a call t o solrClie nt.ping() | |
| 214 | ||
| 215 | callback - a funct ion execut ed when th e Solr ser ver respon ds or an e rror occur s | |
| 216 | */ | |
| 217 | ping(cal lback) { | |
| 218 | this.l ogger.debu g('solr-sm art-client .ping()'); | |
| 219 | this._ executeSol rCommand(' ping', cal lback); | |
| 220 | } | |
| 221 | ||
| 222 | ||
| 223 | /* | |
| 224 | This met hod create s the Zook eeper clie nt instanc es and reg isters all event | |
| 225 | handlers for Zooke eper event s and Zook eeper Node events. I f this met hod is | |
| 226 | called f rom and in stance cre ated with childInsta nce(), it will log a warning | |
| 227 | message and return without d oing anyth ing. | |
| 228 | */ | |
| 229 | start() { | |
| 230 | this.l ogger.debu g('solr-sm art-client .start()') ; | |
| 231 | ||
| 232 | if (th is.child) { | |
| 233 | // T his method was calle d on a chi ld instanc e, so log a warning and return | |
| 234 | this .logger.wa rn('solr-s mart-clien t.start() attempt to call this method fr om childIn stance ign ored'); | |
| 235 | retu rn; | |
| 236 | } | |
| 237 | ||
| 238 | let lo gger = thi s.logger; | |
| 239 | let da taWrapper = this.dat aWrapper; | |
| 240 | let zo oKeeperOpt ions = thi s.config.z ooKeeperOp tions; | |
| 241 | let zo oKeeperCon nection = this.confi g.zooKeepe rConnectio n; | |
| 242 | let zo okeeperEve ntLogLevel = this.co nfig.zooke eperEventL ogLevel; | |
| 243 | ||
| 244 | // Cle ar the dat a to start fresh | |
| 245 | dataWr apper.vali d = false; | |
| 246 | dataWr apper.data = undefin ed; | |
| 247 | ||
| 248 | // Unr egister al l Zookeepe r listener s, close t he current connectio n | |
| 249 | if (th is.zkClien t) { | |
| 250 | this .zkClient. removeAllL isteners() ; | |
| 251 | this .zkClient. close(); | |
| 252 | } | |
| 253 | ||
| 254 | logger .debug('so lr-smart-c lient.star t() zookee per.create Client()') ; | |
| 255 | this.z kClient = zookeeper. createClie nt(zooKeep erConnecti on, zooKee perOptions ); | |
| 256 | logger .debug('so lr-smart-c lient.star t() zookee per client created') ; | |
| 257 | this.z kClient.co nnect(); | |
| 258 | this.z kClient.on ('state', state => { | |
| 259 | logg er.debug(' solr-smart -client.st art() -> s essionId: %s, eventH andler(): %j', this. zkSessionI d, state); | |
| 260 | ||
| 261 | // Z ooKeeper e vents can be one of 6 states: | |
| 262 | // DISCONNEC TED | |
| 263 | // SYNC_CONN ECTED | |
| 264 | // AUTH_FAIL ED | |
| 265 | // CONNECTED _READ_ONLY | |
| 266 | // SASL_AUTH ENTICATED | |
| 267 | // EXPIRED | |
| 268 | ||
| 269 | if ( !_.isEmpty (zookeeper EventLogLe vel) && _. isFunction (logger[zo okeeperEve ntLogLevel ])) { | |
| 270 | lo gger[zooke eperEventL ogLevel](' solr-smart -client.st art() -> e ventHandle r() sessio nId: %s, Z ookeeper E vent: %j', this.zkSe ssionId, s tate); | |
| 271 | } | |
| 272 | ||
| 273 | if ( state === zookeeper. State.SYNC _CONNECTED || state === zookee per.State. CONNECTED_ READ_ONLY) { | |
| 274 | re turn this. _fetchZook eeperData( ); | |
| 275 | } | |
| 276 | ||
| 277 | if ( state === zookeeper. State.DISC ONNECTED) { | |
| 278 | lo gger.debug ('solr-sma rt-client. start() -> eventHand ler() sess ionId: %s, DISCONNEC TED', this .zkSession Id); | |
| 279 | da taWrapper. valid = fa lse; | |
| 280 | da taWrapper. data = und efined; | |
| 281 | re turn; | |
| 282 | } | |
| 283 | ||
| 284 | if ( state === zookeeper. State.EXPI RED) { | |
| 285 | lo gger.warn( 'solr-smar t-client.s tart() -> eventHandl er() sessi onId: %s, EXPIRED', this.zkSes sionId); | |
| 286 | ||
| 287 | // EXPIRED e vents shou ld be unco mmon. Clea r out the client and reset eve rything. | |
| 288 | th is.start() ; | |
| 289 | } | |
| 290 | }); | |
| 291 | } | |
| 292 | ||
| 293 | ||
| 294 | /* | |
| 295 | Returns the Zookee per Sessio nId as a s tring. If "this.zkCl ient" | |
| 296 | (the Zoo keeper cli ent instan ce) is nul l or undef ined, it r eturns | |
| 297 | 'undefin ed'. | |
| 298 | ||
| 299 | The valu e returned will be a hex value which wil l match up with the | |
| 300 | sessionI d value in the Zooke eper log f ile. | |
| 301 | */ | |
| 302 | get zkSe ssionId() { | |
| 303 | if (!t his.zkClie nt) { | |
| 304 | retu rn; | |
| 305 | } | |
| 306 | ||
| 307 | return this.zkCl ient.getSe ssionId(). toString(' hex'); | |
| 308 | } | |
| 309 | ||
| 310 | ||
| 311 | /* | |
| 312 | Call zkC lient.getC hildren() and update the data from the r esults. | |
| 313 | Addition ally, regi ster a wat cher so th at in the event of a node | |
| 314 | being mo dified, ad ded, or de leted, the data will be reload ed. | |
| 315 | */ | |
| 316 | _fetchZo okeeperDat a() { | |
| 317 | this.l ogger.debu g('solr-sm art-client ._fetchZoo keeperData ()'); | |
| 318 | ||
| 319 | let da taWrapper = this.dat aWrapper; | |
| 320 | let lo gger = thi s.logger; | |
| 321 | let no deEventLog Level = th is.nodeEve ntLogLevel ; | |
| 322 | let re queryLoopD elayMillis = this.co nfig.reque ryLoopDela yMillis; | |
| 323 | ||
| 324 | ||
| 325 | // Thi s is calle d on any o f the Zook eeper Node events: | |
| 326 | // NOD E_CREATED, NODE_DELE TED, NODE_ DATA_CHANG ED, NODE_C HILDREN_CH ANGED | |
| 327 | ||
| 328 | // A w atch is a one-time e vent liste ner (i.e. it is call ed at most , one time ) | |
| 329 | let wa tch = even t => { | |
| 330 | if ( !_.isEmpty (nodeEvent LogLevel) && _.isFun ction(logg er[nodeEve ntLogLevel ])) { | |
| 331 | lo gger[nodeE ventLogLev el]('solr- smart-clie nt._fetchZ ookeeperDa ta() -> wa tch() sess ionId: %s, Zookeeper Node Even t: %j', th is.zkSessi onId, even t); | |
| 332 | } | |
| 333 | ||
| 334 | logg er.debug(' solr-smart -client._f etchZookee perData() -> watch() Zookeeper Node Even t: %j', ev ent); | |
| 335 | this ._fetchZoo keeperData (); | |
| 336 | }; | |
| 337 | ||
| 338 | // Sav e the data or the va lid flag t o false if an error occured wh en | |
| 339 | // att empting to call zkCl ient.getCh ildren() | |
| 340 | let se tData = (e rror, clus terState) => { | |
| 341 | if ( error) { | |
| 342 | lo gger.error ('solr-sma rt-client. _fetchZook eeperData( ) -> setDa ta() Error calling z ookeeper.g etData(): sessionId: %s, error : %j', thi s.zkSessio nId, error ); | |
| 343 | da taWrapper. valid = fa lse; | |
| 344 | da taWrapper. data = und efined; | |
| 345 | re turn setTi meout(this ._fetchZoo keeperData .bind(this ), requery LoopDelayM illis); | |
| 346 | } | |
| 347 | ||
| 348 | logg er.debug(' solr-smart -client._f etchZookee perData() -> setData () session Id: %s, cl usterState : %s', thi s.zkSessio nId, clust erState); | |
| 349 | data Wrapper.va lid = true ; | |
| 350 | data Wrapper.da ta = clust erState; | |
| 351 | }; | |
| 352 | ||
| 353 | this.z kClient.ge tData(this .config.pa th, watch, setData); | |
| 354 | } | |
| 355 | ||
| 356 | ||
| 357 | /* | |
| 358 | This fun ction retr ieves the SOLR clien t info fro m ZooKeepe r. In the event | |
| 359 | that dat a has not been retri eved yet, or has bee n cleared because Zo oKeeper | |
| 360 | is down or because the data is being u pdated, th e method w ill wait f or the | |
| 361 | data unt il the con fig.dataTi meoutMilli s period i s exceeded , at which point | |
| 362 | it will return an error. | |
| 363 | */ | |
| 364 | _getSolr ClientInfo (callback) { | |
| 365 | this.l ogger.debu g('solr-sm art-client ._getSolrC lientInfo( )'); | |
| 366 | ||
| 367 | let st artTime = Date.now() ; | |
| 368 | let lo gger = thi s.logger; | |
| 369 | let da taWrapper = this.dat aWrapper; | |
| 370 | let da taTimeoutM illis = th is.config. dataTimeou tMillis; | |
| 371 | let wa itLoopDela yMillis = this.confi g.waitLoop DelayMilli s; | |
| 372 | ||
| 373 | // inv oked immed iately via IIFE | |
| 374 | // rec ursively l oop until dataWrappe r.valid or timeout e xpires | |
| 375 | (funct ion waitFo rValidData () { | |
| 376 | logg er.debug(' solr-smart -client._g etSolrClie ntInfo() - > waitForV alidData() : waiting for dataWr apper.vali d: %s', da taWrapper. valid); | |
| 377 | if ( !dataWrapp er.valid) { | |
| 378 | if (Date.now () - start Time > dat aTimeoutMi llis) { | |
| 379 | logger.war n('solr-sm art-client ._getSolrC lientInfo( ) -> waitF orValidDat a(): timeo ut while w aiting for valid dat a'); | |
| 380 | return set Timeout(ca llback, 0, 'Timeout waiting fo r valid zo okeeper da ta'); | |
| 381 | } | |
| 382 | ||
| 383 | re turn setTi meout(wait ForValidDa ta, waitLo opDelayMil lis); | |
| 384 | } | |
| 385 | ||
| 386 | logg er.debug(' solr-smart -client._g etSolrClie ntInfo() - > waitForV alidData() : retrieve d valid da ta: %s', d ataWrapper .data); | |
| 387 | retu rn setTime out(callba ck, 0, nul l, dataWra pper.data) ; | |
| 388 | })(); | |
| 389 | } | |
| 390 | ||
| 391 | ||
| 392 | /* | |
| 393 | Variadic function: | |
| 394 | function executeSo lrCommand( operation, callback) | |
| 395 | function executeSo lrCommand( operation, param, ca llback) | |
| 396 | function executeSo lrCommand( operation, [param1, param2...] , callback ) | |
| 397 | ||
| 398 | operatio n - name o f the oper ation to c all on sol rClient (e .g. solrCl ient.add() , etc.) | |
| 399 | params - a single parameter or an arra y of param eters to p ass to sol rClient | |
| 400 | callback - the fun ction(erro r, result) called on success o r failure of the sol r action | |
| 401 | ||
| 402 | This fun ction exec utes a sol r command, first per forming al l of the n ecessary o perations | |
| 403 | to get a reference to a vali d solr cli ent instan ce. The fo llowing so lr command methods | |
| 404 | in this class dele gate to th is method: | |
| 405 | ||
| 406 | add() | |
| 407 | delete All() | |
| 408 | delete ByQuery() | |
| 409 | search () | |
| 410 | get() | |
| 411 | commit () | |
| 412 | */ | |
| 413 | _execute SolrComman d(operatio n, params, callback) { | |
| 414 | this.l ogger.debu g('solr-sm art-client ._executeS olrCommand () -> solr Client.%s( %j)', oper ation, par ams); | |
| 415 | ||
| 416 | if (ar guments.le ngth < 3) { | |
| 417 | call back = par ams; | |
| 418 | para ms = []; | |
| 419 | } | |
| 420 | ||
| 421 | if (!_ .isArray(p arams)) { | |
| 422 | para ms = [para ms]; | |
| 423 | } | |
| 424 | ||
| 425 | // sli ce() makes a shallow copy of t he array | |
| 426 | params = params. slice(); | |
| 427 | params .push(call back); | |
| 428 | ||
| 429 | this.l ogger.debu g('solr-sm art-client ._executeS olrCommand () -> solr Client.%s( )', operat ion); | |
| 430 | this._ getValidSo lrClient(s olrClientM odule, (er ror, solrC lientInsta nce) => { | |
| 431 | if ( error) { | |
| 432 | re turn callb ack(error) ; | |
| 433 | } | |
| 434 | ||
| 435 | let func = sol rClientIns tance[oper ation]; | |
| 436 | if ( !_.isFunct ion(func)) { | |
| 437 | re turn callb ack('"' + operation + '" is no t a valid function f or the Sol r Client') ; | |
| 438 | } | |
| 439 | ||
| 440 | retu rn func.ap ply(solrCl ientInstan ce, params ); | |
| 441 | }); | |
| 442 | } | |
| 443 | ||
| 444 | ||
| 445 | /* | |
| 446 | Returns a valid So lrClient r eady to in voke vario us Solr op erations | |
| 447 | ||
| 448 | The solr Client par ameter is to allow u nit tests to pass in a custom | |
| 449 | solrClie nt library . | |
| 450 | */ | |
| 451 | _getVali dSolrClien t(solrClie ntLibrary, callback) { | |
| 452 | this.l ogger.debu g('solr-sm art-client ._getValid SolrClient ()'); | |
| 453 | ||
| 454 | let co re = this. config.cor e; | |
| 455 | let ag ent = this .agent; | |
| 456 | this._ getSolrCli entInfo((e rror, solr ClientInfo ) => { | |
| 457 | if ( error) { | |
| 458 | th is.logger. warn('solr -smart-cli ent._getVa lidSolrCli ent() erro r retrievi ng solrCon fig: %j', error); | |
| 459 | re turn callb ack(error) ; | |
| 460 | } | |
| 461 | ||
| 462 | let solrConfig = SolrSma rtClient._ createSolr ClientConf ig(this.lo gger, core , agent, s olrClientI nfo); | |
| 463 | ||
| 464 | this .logger.in fo('solr-s mart-clien t._getVali dSolrClien t() solrCo nfig: %j', _.omit(so lrConfig, 'agent')); | |
| 465 | retu rn callbac k(null, so lrClientLi brary.crea teClient(s olrConfig) ); | |
| 466 | }); | |
| 467 | } | |
| 468 | ||
| 469 | ||
| 470 | /* | |
| 471 | Generate a Solr cl ient confi g object o r return u ndefined i f no valid liveNode string exi sts. | |
| 472 | core - t he Solr 'c ore' (e.g. 'vpr'); | |
| 473 | agent - a referenc e to the a gent objec t (i.e. th e KeepAliv eAgent) | |
| 474 | This value can be 'u ndefined' in which c ase, no ag ent will b e used. | |
| 475 | clusterS tate - the state of the SOLR c luster sto red by Zoo Keeper. Th is should be a JSON | |
| 476 | document similar t o: | |
| 477 | ||
| 478 | { | |
| 479 | "vpr": { | |
| 480 | "rep licationFa ctor": "1" , | |
| 481 | "sha rds": { | |
| 482 | "s hard1": { | |
| 483 | "range": " 80000000-7 fffffff", | |
| 484 | "state": " active", | |
| 485 | "replicas" : { | |
| 486 | "core_no de1": { | |
| 487 | "core" : "vpr_sha rd1_replic a1", | |
| 488 | "base_url" : "http:// IP /solr", | |
| 489 | "node_name ": " IP _solr", | |
| 490 | "state ": "active ", | |
| 491 | "leade r": "true" | |
| 492 | } | |
| 493 | } | |
| 494 | } | |
| 495 | }, | |
| 496 | "rou ter": { | |
| 497 | "n ame": "com positeId" | |
| 498 | }, | |
| 499 | "max ShardsPerN ode": "2", | |
| 500 | "aut oAddReplic as": "fals e" | |
| 501 | } | |
| 502 | } | |
| 503 | ||
| 504 | Note tha t "vpr" is the name of the col lection (i .e. the co re). Note that a com plex syste m could | |
| 505 | have mul tiple shar ds with mu ltiple rep licas per shard. Thi s function will find the data from the | |
| 506 | first sh ard with a replica w ith "state " === 'act ive' and " leader" == = 'true'. | |
| 507 | */ | |
| 508 | static _ createSolr ClientConf ig(logger, core, age nt, cluste rState) { | |
| 509 | logger .debug('so lr-smart-c lient._cre ateSolrCli entConfig( ) core: %s clusterSt ate: %s', core, clus terState); | |
| 510 | ||
| 511 | if (_. isEmpty(co re) || _.i sEmpty(clu sterState) ) { | |
| 512 | logg er.warn('s olr-smart- client._cr eateSolrCl ientConfig () no valu e for core and/or cl usterState , unable t o create s olr client config'); | |
| 513 | retu rn; | |
| 514 | } | |
| 515 | ||
| 516 | try { | |
| 517 | clus terState = JSON.pars e(clusterS tate); | |
| 518 | } catc h (error) { | |
| 519 | logg er.warn('s olr-smart- client._cr eateSolrCl ientConfig () error p arsing clu sterState, unable to create so lr client config: %j ', error); | |
| 520 | retu rn; | |
| 521 | } | |
| 522 | ||
| 523 | if (!c lusterStat e[core]) { | |
| 524 | logg er.warn('s olr-smart- client._cr eateSolrCl ientConfig () no entr y for "%s" collectio n, unable to create solr clien t config', core); | |
| 525 | retu rn; | |
| 526 | } | |
| 527 | ||
| 528 | let pa rsedUrl = SolrSmartC lient._fin dFirstRead yNodeUrl(l ogger, clu sterState[ core].shar ds); | |
| 529 | ||
| 530 | if (!p arsedUrl) { | |
| 531 | logg er.warn('s olr-smart- client._cr eateSolrCl ientConfig () unable to find re ady replic a to creat e solr cli ent config '); | |
| 532 | retu rn; | |
| 533 | } | |
| 534 | ||
| 535 | return { | |
| 536 | secu re: parsed Url[2] === 'https', | |
| 537 | host : parsedUr l[3], | |
| 538 | port : parsedUr l[4], | |
| 539 | path : parsedUr l[5], | |
| 540 | core : core, | |
| 541 | agen t: agent | |
| 542 | }; | |
| 543 | } | |
| 544 | ||
| 545 | ||
| 546 | /* | |
| 547 | This fun ction pars es the sha rd and rep lica infor mation (wh ich was re trieved fr om the | |
| 548 | collecti ons node) and finds the first replica wh ich matche s the crit eria: | |
| 549 | state === 'activ e' | |
| 550 | leader === 'true ' | |
| 551 | base_u rl that ma tches the regex | |
| 552 | ||
| 553 | The retu rn value i s the arra y gotten f rom execut ing the re gex. | |
| 554 | ||
| 555 | Given th e followin g input: | |
| 556 | ||
| 557 | let shar ds = | |
| 558 | "shard 1": { | |
| 559 | "ran ge": "8000 0000-7ffff fff", | |
| 560 | "sta te": "acti ve", | |
| 561 | "rep licas": { | |
| 562 | "c ore_node1" : { | |
| 563 | "core": "v pr_shard1_ replica1", | |
| 564 | "base_url" : "http:// IP /solr", | |
| 565 | "node_name ": " IP _solr", | |
| 566 | "state": " active", | |
| 567 | "leader": "true" | |
| 568 | } | |
| 569 | } | |
| 570 | }, | |
| 571 | "shard 2": { | |
| 572 | "ran ge": "8000 0000-7ffff fff", | |
| 573 | "sta te": "acti ve", | |
| 574 | "rep licas": { | |
| 575 | "c ore_node1" : { | |
| 576 | "core": "v pr_shard2_ replica1", | |
| 577 | "base_url" : "http:// IP /solr", | |
| 578 | "node_name ": " IP _solr", | |
| 579 | "state": " active", | |
| 580 | "leader": "true" | |
| 581 | } | |
| 582 | } | |
| 583 | } | |
| 584 | } | |
| 585 | ||
| 586 | The retu rn value w ould be: | |
| 587 | ||
| 588 | [ 'http:// IP /solr', | |
| 589 | 'http: //', | |
| 590 | 'http' , | |
| 591 | ' IP ', | |
| 592 | ' PORT ', | |
| 593 | '/solr ', | |
| 594 | index: 0, | |
| 595 | input: 'ht tp:// IP /solr' ] | |
| 596 | ||
| 597 | */ | |
| 598 | static _ findFirstR eadyNodeUr l(logger, shards) { | |
| 599 | logger .debug('so lr-smart-c lient._fin dFirstRead yNodeUrl() %j', shar ds); | |
| 600 | ||
| 601 | // Go to: https: //regex101 .com/#java script and enter thi s regex to explore.. . | |
| 602 | // Thi s regex ma tches urls of the fo rms with o r without the protoc ol: | |
| 603 | // http://127 .0.0.1: PORT /solr | |
| 604 | let ur lRegex = n ew RegExp( /^((http[s ]?):\/\/)? (\S+):([0- 9]{1,5})(\ S+)/); | |
| 605 | ||
| 606 | // Cre ate an arr ay with al l of the s olr node e ntries in all of the shards th at | |
| 607 | // are active, l eaders, an d with a b ase_url t hat matche s the expe cted patte rn | |
| 608 | let no deList = _ .flatten(_ .map(shard s, shardIn fo => { | |
| 609 | retu rn _.filte r(shardInf o.replicas , node => { | |
| 610 | re turn node. state === 'active' & & node.lea der === 't rue' && ur lRegex.tes t(node.bas e_url); | |
| 611 | }); | |
| 612 | })); | |
| 613 | ||
| 614 | if (_. isEmpty(no deList)) { | |
| 615 | logg er.warn('s olr-smart- client._fi ndFirstRea dyNodeUrl( ) no nodes were foun d in a val id state w ith valid info'); | |
| 616 | retu rn; | |
| 617 | } | |
| 618 | ||
| 619 | return urlRegex. exec(_.fir st(nodeLis t).base_ur l); | |
| 620 | } | |
| 621 | } | |
| 622 | ||
| 623 | /* ******* ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** *** */ | |
| 624 | /* Factory Fu nctions */ | |
| 625 | /* ******* ********** ********** ********** ********** ********** ********** ********** ********** ********** ********** *** */ | |
| 626 | ||
| 627 | /* | |
| 628 | This funct ion create s a stand- alone (i.e . not a ch ild) insta nce of Sol rSmartClie nt. | |
| 629 | ||
| 630 | config - t he connect ion and co nfiguratio n properti es | |
| 631 | agent - HT TP Agent w hich is us ed for poo ling socke ts used in HTTP(s) c lient requ ests | |
| 632 | Th is paramet er is opti onal | |
| 633 | ||
| 634 | For full d ocumentati on on the properties in 'confi g', see th e comments in the So lrSmartCli ent constr uctor | |
| 635 | */ | |
| 636 | function c reateClien t(logger, config, ag ent) { | |
| 637 | logger.d ebug('solr -smart-cli ent.create Client() c onfig: %j' , config); | |
| 638 | ||
| 639 | let solr SmartClien t = new So lrSmartCli ent(logger , config, agent); | |
| 640 | solrSmar tClient.st art(); | |
| 641 | ||
| 642 | return s olrSmartCl ient; | |
| 643 | } | |
| 644 | ||
| 645 | ||
| 646 | exports.So lrSmartCli ent = Solr SmartClien t; | |
| 647 | exports.cr eateClient = createC lient; |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.