@brown-ds/distribution 0.2.16 → 0.2.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,50 +30,80 @@ By default, all regular tests are run. Use the options below to run different se
30
30
 
31
31
  ## Usage
32
32
 
33
- To import the library, be it in a JavaScript file or on the interactive console, run:
33
+ To try out the distribution library inside an interactive Node.js session, run:
34
+
35
+ ```sh
36
+ $ node
37
+ ```
38
+
39
+ Then, load the distribution library:
34
40
 
35
41
  ```js
36
- let distribution = require("@brown-ds/distribution");
42
+ > let distribution = require("@brown-ds/distribution")();
43
+ > distribution.node.start(console.log);
37
44
  ```
38
45
 
39
46
  Now you have access to the full distribution library. You can start off by serializing some values.
40
47
 
41
48
  ```js
42
- let s = distribution.util.serialize(1); // '{"type":"number","value":"1"}'
43
- let n = distribution.util.deserialize(s); // 1
49
+ > s = distribution.util.serialize(1); // '{"type":"number","value":"1"}'
50
+ > n = distribution.util.deserialize(s); // 1
44
51
  ```
45
52
 
46
53
  You can inspect information about the current node (for example its `sid`) by running:
47
54
 
48
55
  ```js
49
- distribution.local.status.get('sid', console.log); // 8cf1b
56
+ > distribution.local.status.get('sid', console.log); // null 8cf1b (null here is the error value; meaning there is no error)
50
57
  ```
51
58
 
52
59
  You can also store and retrieve values from the local memory:
53
60
 
54
61
  ```js
55
- distribution.local.mem.put({name: 'nikos'}, 'key', console.log); // {name: 'nikos'}
56
- distribution.local.mem.get('key', console.log); // {name: 'nikos'}
62
+ > distribution.local.mem.put({name: 'nikos'}, 'key', console.log); // null {name: 'nikos'} (again, null is the error value)
63
+ > distribution.local.mem.get('key', console.log); // null {name: 'nikos'}
64
+
65
+ > distribution.local.mem.get('wrong-key', console.log); // Error('Key not found') undefined
57
66
  ```
58
67
 
59
68
  You can also spawn a new node:
60
69
 
61
70
  ```js
62
- let node = { ip: '127.0.0.1', port: 8080 };
63
- distribution.local.status.spawn(node, console.log);
71
+ > node = { ip: '127.0.0.1', port: 8080 };
72
+ > distribution.local.status.spawn(node, console.log);
64
73
  ```
65
74
 
66
75
  Using the `distribution.all` set of services will allow you to act
67
76
  on the full set of nodes created as if they were a single one.
68
77
 
69
78
  ```js
70
- distribution.all.status.get('sid', console.log); // { '8cf1b': '8cf1b', '8cf1c': '8cf1c' }
79
+ > distribution.all.status.get('sid', console.log); // {} { '8cf1b': '8cf1b', '8cf1c': '8cf1c' } (now, errors are per-node and form an object)
71
80
  ```
72
81
 
73
82
  You can also send messages to other nodes:
74
83
 
75
84
  ```js
76
- distribution.all.comm.send(['sid'], {node: node, service: 'status', method: 'get'}, console.log); // 8cf1c
85
+ > distribution.local.comm.send(['sid'], {node: node, service: 'status', method: 'get'}, console.log); // null 8cf1c
86
+ ```
87
+
88
+ Most methods in the distribution library are asynchronous and take a callback as their last argument.
89
+ This callback is called when the method completes, with the first argument being an error (if any) and the second argument being the result.
90
+ If you wanted to run this same sequence of commands in a script, you could do something like this (note the nested callbacks):
91
+
92
+ ```js
93
+ let distribution = require("@brown-ds/distribution")();
94
+ // Now we're only doing a few of the things we did above
95
+ distribution.node.start(() => {
96
+ // This will run only after the node has started
97
+ node = { ip: '127.0.0.1', port: 8080 };
98
+ distribution.local.status.spawn(node, () => {
99
+ // This will run only after the new node has been spawned
100
+ distribution.all.status.get('sid', (e, v) => {
101
+ // This will run only after we communicated with all nodes and got their sids
102
+ console.log(v); // { '8cf1b': '8cf1b', '8cf1c': '8cf1c' }
103
+ distribution.local.status.stop(console.log);
104
+ });
105
+ });
106
+ });
77
107
  ```
78
108
 
79
109
  # Results and Reflections
@@ -6,5 +6,5 @@ Do NOT edit this file directly. Use it as a black box.
6
6
 
7
7
  If you notice any issues with using this file, please contact the TAs.
8
8
  */
9
- const http=require('node:http'),url=require('node:url'),log=require('../util/lo'+'g.js'),args=require('yargs')['argv'];function setNodeConfig(){let _0x41c15b,_0x2ce115,_0x1f9a29;typeof args['ip']==='string'&&(_0x41c15b=args['ip']);typeof args['port']==='string'&&(_0x2ce115=parseInt(args['port']));if(typeof args['config']==='string'){const {ip:_0x44fcbd,port:_0x335446,onStart:_0x16a4f5}=globalThis['distributi'+'on']['util']['deserializ'+'e'](args['config']);typeof _0x44fcbd==='string'&&(_0x41c15b=_0x44fcbd),typeof _0x335446==='number'&&(_0x2ce115=_0x335446),typeof _0x16a4f5==='function'&&(_0x1f9a29=_0x16a4f5);}return _0x41c15b=_0x41c15b||'127.0.0.1',_0x2ce115=_0x2ce115||0x16c7+-0xb*-0x293+-0x1*0x2e46,{'ip':_0x41c15b,'port':_0x2ce115,'onStart':_0x1f9a29};}function validate(_0x35101b){if(_0x35101b['length']===-0x1bc8+0x15f0+0x58*0x11)throw new Error('No\x20body');return JSON['parse'](_0x35101b);}function start(_0x2edead){const _0x3eca42=http['createServ'+'er']((_0x1144bd,_0x651cbe)=>{if(_0x1144bd['method']!=='PUT'){_0x651cbe['end'](globalThis['distributi'+'on']['util']['serialize'](new Error('Method\x20not'+'\x20allowed!')));return;}const [,_0x4ddf2c,_0x3e5e05,_0x56a5d5]=url['parse'](_0x1144bd['url'])['pathname']['split']('/');log('[server]\x20g'+'ot\x20request'+'\x20'+_0x4ddf2c+'\x20'+_0x3e5e05+':'+_0x56a5d5+'\x20from\x20'+_0x1144bd['socket']['remoteAddr'+'ess']);const _0x57b4da=[];_0x1144bd['on']('data',_0x533dcf=>{_0x57b4da['push'](_0x533dcf);}),_0x1144bd['on']('end',()=>{let _0x3f49c4;try{_0x3f49c4=validate(Buffer['concat'](_0x57b4da)['toString']());}catch(_0x2e25d3){_0x651cbe['end'](globalThis['distributi'+'on']['util']['serialize']([_0x2e25d3]));return;}const _0x479c5d=globalThis['distributi'+'on']['util']['deserializ'+'e'](_0x3f49c4);!Array['isArray'](_0x479c5d)&&_0x651cbe['end'](globalThis['distributi'+'on']['util']['serialize']([new Error('Invalid\x20ar'+'gument\x20typ'+'e,\x20expecte'+'d\x20array,\x20g'+'ot\x20'+typeof _0x479c5d)]));const _0x41ed9f=_0x3e5e05;globalThis['distributi'+'on']['local']['routes']['get']({'service':_0x3e5e05,'gid':_0x4ddf2c},(_0x544747,_0x10a68a)=>{if(_0x544747){_0x651cbe['end'](globalThis['distributi'+'on']['util']['serialize']([_0x544747,null]));return;}if(!_0x10a68a[_0x56a5d5]){_0x651cbe['end'](globalThis['distributi'+'on']['util']['serialize']([new Error('Method\x20'+_0x56a5d5+('\x20not\x20found'+'\x20in\x20servic'+'e\x20')+_0x41ed9f),null]));return;}log('[server]\x20\x20'+'Calling\x20se'+'rvice:\x20'+_0x41ed9f+':'+_0x56a5d5+('\x20with\x20args'+':\x20')+JSON['stringify'](_0x479c5d));_0x479c5d['length']===0x1f2e*-0x1+0x1020+0xf0f&&_0x10a68a[_0x56a5d5]['length']===-0x1342+-0x1*-0x2072+-0xd2d&&_0x479c5d['push'](undefined);const _0x273bc1=_0x10a68a[_0x56a5d5]['bind'](_0x10a68a),_0x3746ab=globalThis['distributi'+'on']['util']['normalize'](_0x273bc1,_0x479c5d);try{_0x273bc1(..._0x3746ab,(_0x310183,_0x1473b2)=>_0x651cbe['end'](globalThis['distributi'+'on']['util']['serialize']([_0x310183,_0x1473b2])));}catch(_0x463d82){_0x651cbe['end'](globalThis['distributi'+'on']['util']['serialize']([_0x463d82,null]));}});});}),_0x3e09d7=globalThis['distributi'+'on']['node']['config'];_0x3eca42['listen'](_0x3e09d7['port'],_0x3e09d7['ip'],()=>{log('Server\x20run'+'ning\x20at\x20ht'+'tp://'+_0x3e09d7['ip']+':'+_0x3e09d7['port']+'/'),globalThis['distributi'+'on']['node']['server']=_0x3eca42,_0x2edead();}),_0x3eca42['on']('error',_0x56cfe6=>{log('Server\x20err'+'or:\x20'+_0x56cfe6);throw _0x56cfe6;});}module['exports']={'start':start,'config':setNodeConfig()};
9
+ const http=require('node:http'),url=require('node:url'),log=require('../util/lo'+'g.js'),yargs=require('yargs/yarg'+'s');function setNodeConfig(){const _0x58e6f7=yargs(process['argv'])['help'](![])['version'](![])['parse']();let _0x30c324,_0x1cbc77,_0x15f349;typeof _0x58e6f7['ip']==='string'&&(_0x30c324=_0x58e6f7['ip']);(typeof _0x58e6f7['port']==='string'||typeof _0x58e6f7['port']==='number')&&(_0x1cbc77=parseInt(String(_0x58e6f7['port']),-0x8*0x17b+0x67f+-0x563*-0x1));(_0x58e6f7['help']===!![]||_0x58e6f7['h']===!![])&&(console['log']('Node\x20usage'+':'),console['log']('\x20\x20--ip\x20<ip'+'\x20address>\x20'+'\x20\x20\x20\x20\x20The\x20i'+'p\x20address\x20'+'to\x20bind\x20th'+'e\x20node\x20to'),console['log']('\x20\x20--port\x20<'+'port>\x20\x20\x20\x20\x20'+'\x20\x20\x20\x20\x20The\x20p'+'ort\x20to\x20bin'+'d\x20the\x20node'+'\x20to'),console['log']('\x20\x20--config'+'\x20<config>\x20'+'\x20\x20\x20\x20\x20The\x20s'+'erialized\x20'+'config\x20str'+'ing'),process['exit'](0x3bd+-0x55*0x19+0x490));if(typeof _0x58e6f7['config']==='string'){const {ip:_0x28ffcf,port:_0x4a05a5,onStart:_0x478f55}=globalThis['distributi'+'on']['util']['deserializ'+'e'](_0x58e6f7['config']);typeof _0x28ffcf==='string'&&(_0x30c324=_0x28ffcf),typeof _0x4a05a5==='number'&&(_0x1cbc77=_0x4a05a5),typeof _0x478f55==='function'&&(_0x15f349=_0x478f55);}return _0x30c324=_0x30c324||'127.0.0.1',_0x1cbc77=_0x1cbc77||0x2348+0x124a*0x1+0x208*-0x18,{'ip':_0x30c324,'port':_0x1cbc77,'onStart':_0x15f349};}function validate(_0x1f5634){if(_0x1f5634['length']===-0x1e+0xe20+-0xe02)throw new Error('No\x20body');return JSON['parse'](_0x1f5634);}function start(_0x5918b8){const _0x793bdb=http['createServ'+'er']((_0x8bf185,_0x393546)=>{if(_0x8bf185['method']!=='PUT'){_0x393546['end'](globalThis['distributi'+'on']['util']['serialize'](new Error('Method\x20not'+'\x20allowed!')));return;}const [,_0x234b17,_0x3db925,_0x3d0e39]=url['parse'](_0x8bf185['url'])['pathname']['split']('/');log('[server]\x20g'+'ot\x20request'+'\x20'+_0x234b17+'\x20'+_0x3db925+':'+_0x3d0e39+'\x20from\x20'+_0x8bf185['socket']['remoteAddr'+'ess']);const _0x5abbe0=[];_0x8bf185['on']('data',_0x67902d=>{_0x5abbe0['push'](_0x67902d);}),_0x8bf185['on']('end',()=>{let _0x4f9ed0;try{_0x4f9ed0=validate(Buffer['concat'](_0x5abbe0)['toString']());}catch(_0x4fefe6){_0x393546['end'](globalThis['distributi'+'on']['util']['serialize']([_0x4fefe6]));return;}const _0x4dc797=globalThis['distributi'+'on']['util']['deserializ'+'e'](_0x4f9ed0);!Array['isArray'](_0x4dc797)&&_0x393546['end'](globalThis['distributi'+'on']['util']['serialize']([new Error('Invalid\x20ar'+'gument\x20typ'+'e,\x20expecte'+'d\x20array,\x20g'+'ot\x20'+typeof _0x4dc797)]));const _0x2fa308=_0x3db925;globalThis['distributi'+'on']['local']['routes']['get']({'service':_0x3db925,'gid':_0x234b17},(_0x1719ed,_0x4c34c0)=>{if(_0x1719ed){_0x393546['end'](globalThis['distributi'+'on']['util']['serialize']([_0x1719ed,null]));return;}if(!_0x4c34c0[_0x3d0e39]){_0x393546['end'](globalThis['distributi'+'on']['util']['serialize']([new Error('Method\x20'+_0x3d0e39+('\x20not\x20found'+'\x20in\x20servic'+'e\x20')+_0x2fa308),null]));return;}log('[server]\x20\x20'+'Calling\x20se'+'rvice:\x20'+_0x2fa308+':'+_0x3d0e39+('\x20with\x20args'+':\x20')+JSON['stringify'](_0x4dc797));_0x4dc797['length']===0x9*0x83+-0x2*0x1129+0x1db8&&_0x4c34c0[_0x3d0e39]['length']===-0x8*0x1f4+-0x11*-0x2b+0xcc8&&_0x4dc797['push'](undefined);const _0x2d0c56=_0x4c34c0[_0x3d0e39]['bind'](_0x4c34c0),_0x2ebe52=globalThis['distributi'+'on']['util']['normalize'](_0x2d0c56,_0x4dc797);try{_0x2d0c56(..._0x2ebe52,(_0x504677,_0x517e7b)=>_0x393546['end'](globalThis['distributi'+'on']['util']['serialize']([_0x504677,_0x517e7b])));}catch(_0x4ac8ed){_0x393546['end'](globalThis['distributi'+'on']['util']['serialize']([_0x4ac8ed,null]));}});});}),_0x28efe7=globalThis['distributi'+'on']['node']['config'];_0x793bdb['once']('listening',()=>{log('Server\x20run'+'ning\x20at\x20ht'+'tp://'+_0x28efe7['ip']+':'+_0x28efe7['port']+'/'),globalThis['distributi'+'on']['node']['server']=_0x793bdb,_0x5918b8(null);}),_0x793bdb['once']('error',_0x18fdd6=>{log('Server\x20err'+'or:\x20'+_0x18fdd6),_0x5918b8(_0x18fdd6);}),_0x793bdb['listen'](_0x28efe7['port'],_0x28efe7['ip']);}module['exports']={'start':start,'config':setNodeConfig()};
10
10
  /* eslint-enable */
@@ -6,5 +6,5 @@ Do NOT edit this file directly. Use it as a black box.
6
6
 
7
7
  If you notice any issues with using this file, please contact the TAs.
8
8
  */
9
- const log=require('../util/lo'+'g'),counts=0x2*0x5f7+-0xd2a*-0x1+-0x1918;function get(_0x1d680b,_0x4be35a){if(_0x1d680b in globalThis['distributi'+'on']['node']['config']){_0x4be35a(null,globalThis['distributi'+'on']['node']['config'][_0x1d680b]);return;}if(_0x1d680b==='sid'){_0x4be35a(null,globalThis['distributi'+'on']['util']['id']['getSID'](globalThis['distributi'+'on']['node']['config']));return;}if(_0x1d680b==='nid'){_0x4be35a(null,globalThis['distributi'+'on']['util']['id']['getNID'](globalThis['distributi'+'on']['node']['config']));return;}if(_0x1d680b==='counts'){_0x4be35a(null,counts);return;}if(_0x1d680b==='heapTotal'){_0x4be35a(null,process['memoryUsag'+'e']()['heapTotal']);return;}if(_0x1d680b==='heapUsed'){_0x4be35a(null,process['memoryUsag'+'e']()['heapUsed']);return;}_0x4be35a(new Error('Status\x20key'+'\x20not\x20found'));};const fs=require('fs'),path=require('path'),proc=require('node:child'+'_process');function getDistribution(){let _0x5455b3=path['join'](process['cwd'](),'config.js');if(fs['existsSync'](_0x5455b3))return _0x5455b3;try{const _0x441f08=proc['execSync']('git\x20rev-pa'+'rse\x20--show'+'-toplevel',{'encoding':'utf8'})['trim']();_0x5455b3=path['join'](_0x441f08,'config.js');if(fs['existsSync'](_0x5455b3))return _0x5455b3;}catch(_0x99b481){throw new Error('Not\x20in\x20a\x20G'+'it\x20reposit'+'ory\x20or\x20git'+'\x20command\x20f'+'ailed.');}_0x5455b3=path['join'](__dirname,'../../','config.js');if(fs['existsSync'](_0x5455b3))return _0x5455b3;_0x5455b3=path['join'](__dirname,'../../','distributi'+'on.js');if(fs['existsSync'](_0x5455b3))return _0x5455b3;throw new Error('Failed\x20to\x20'+'find\x20proje'+'ct\x20root.');}function createOnStart(_0x2d7911,_0x4c59b1){const _0x5a5dbe='\x0a\x20\x20\x20\x20let\x20o'+'nStart\x20=\x20'+_0x2d7911['toString']()+(';\x0a\x20\x20\x20\x20let\x20'+'callbackRP'+'C\x20=\x20')+globalThis['distributi'+'on']['util']['wire']['createRPC'](globalThis['distributi'+'on']['util']['wire']['toAsync'](_0x4c59b1))['toString']()+(';\x0a\x20\x20\x20\x20try\x20'+'{\x0a\x20\x20\x20\x20\x20\x20on'+'Start();\x0a\x20'+'\x20\x20\x20\x20\x20callb'+'ackRPC(nul'+'l,\x20global.'+'distributi'+'on.node.co'+'nfig,\x20()\x20='+'>\x20{});\x0a\x20\x20\x20'+'\x20}\x20catch(e'+')\x20{\x0a\x20\x20\x20\x20\x20\x20'+'callbackRP'+'C(e,\x20null,'+'\x20()\x20=>\x20{})'+';\x0a\x20\x20\x20\x20}\x0a\x20\x20');return new Function(_0x5a5dbe);}function spawn(_0x4f0991,_0x1b0bd2){const _0x46f8bb=_0x4f0991;_0x46f8bb['onStart']=_0x46f8bb['onStart']||function(){};if(!_0x46f8bb['port']||!_0x46f8bb['ip']){_0x1b0bd2(new Error('Port\x20and\x20I'+'P\x20are\x20requ'+'ired\x20in\x20th'+'e\x20configur'+'ation'));return;}log('[status.sp'+'awn]\x20Spawn'+'ing\x20node\x20w'+'ith\x20config'+'uration:\x20'+JSON['stringify'](_0x46f8bb));const _0x3a74a8=(_0x4222ef,_0x5dcaf9)=>{if(_0x4222ef){_0x1b0bd2(_0x4222ef);return;}globalThis['distributi'+'on']['local']['groups']['add']('all',_0x5dcaf9,()=>{_0x1b0bd2(_0x4222ef,_0x5dcaf9);});};_0x46f8bb['onStart']=createOnStart(_0x46f8bb['onStart'],_0x3a74a8);const _0xc572dd=getDistribution(),_0x2b3e41=proc['spawn']('node',[_0xc572dd,'--config',globalThis['distributi'+'on']['util']['serialize'](_0x46f8bb)],{'detached':!![],'stdio':'inherit'});_0x2b3e41;}function stop(_0x3c79f9){return log('[status.st'+'op]\x20Shutti'+'ng\x20down\x20no'+'de'),globalThis['distributi'+'on']['node']['server']['close'](),process['nextTick'](()=>process['exit'](0x3*-0x43+-0x1b*0x115+0x1e00)),_0x3c79f9(null,globalThis['distributi'+'on']['node']['config']);}module['exports']={'get':get,'spawn':spawn,'stop':stop};
9
+ const log=require('../util/lo'+'g'),counts=-0x99+0x1f7*-0x4+0x1b1*0x5;function get(_0x24a032,_0x280b34){if(_0x24a032 in globalThis['distributi'+'on']['node']['config']){_0x280b34(null,globalThis['distributi'+'on']['node']['config'][_0x24a032]);return;}if(_0x24a032==='sid'){_0x280b34(null,globalThis['distributi'+'on']['util']['id']['getSID'](globalThis['distributi'+'on']['node']['config']));return;}if(_0x24a032==='nid'){_0x280b34(null,globalThis['distributi'+'on']['util']['id']['getNID'](globalThis['distributi'+'on']['node']['config']));return;}if(_0x24a032==='counts'){_0x280b34(null,counts);return;}if(_0x24a032==='heapTotal'){_0x280b34(null,process['memoryUsag'+'e']()['heapTotal']);return;}if(_0x24a032==='heapUsed'){_0x280b34(null,process['memoryUsag'+'e']()['heapUsed']);return;}_0x280b34(new Error('Status\x20key'+'\x20not\x20found'));};const fs=require('fs'),path=require('path'),proc=require('node:child'+'_process');function getDistribution(){let _0x196f40=path['join'](process['cwd'](),'config.js');if(fs['existsSync'](_0x196f40))return _0x196f40;try{const _0x1f749c=proc['execSync']('git\x20rev-pa'+'rse\x20--show'+'-toplevel',{'encoding':'utf8'})['trim']();_0x196f40=path['join'](_0x1f749c,'config.js');if(fs['existsSync'](_0x196f40))return _0x196f40;}catch(_0x1cfd88){throw new Error('Not\x20in\x20a\x20G'+'it\x20reposit'+'ory\x20or\x20git'+'\x20command\x20f'+'ailed.');}_0x196f40=path['join'](__dirname,'../../','config.js');if(fs['existsSync'](_0x196f40))return _0x196f40;_0x196f40=path['join'](__dirname,'../../','distributi'+'on.js');if(fs['existsSync'](_0x196f40))return _0x196f40;throw new Error('Failed\x20to\x20'+'find\x20proje'+'ct\x20root.');}function createOnStart(_0x3c32bc,_0x36aa1b){const _0x52b808='\x0a\x20\x20\x20\x20retur'+'n\x20function'+'(e)\x20{\x0a\x20\x20\x20\x20'+'\x20\x20let\x20onSt'+'art\x20=\x20'+_0x3c32bc['toString']()+(';\x0a\x20\x20\x20\x20\x20\x20le'+'t\x20callback'+'RPC\x20=\x20')+globalThis['distributi'+'on']['util']['wire']['createRPC'](globalThis['distributi'+'on']['util']['wire']['toAsync'](_0x36aa1b))['toString']()+(';\x0a\x20\x20\x20\x20\x20\x20if'+'\x20(e)\x20{\x0a\x20\x20\x20'+'\x20\x20\x20\x20\x20callb'+'ackRPC(e,\x20'+'null,\x20()\x20='+'>\x20{});\x0a\x20\x20\x20'+'\x20\x20\x20\x20\x20retur'+'n;\x0a\x20\x20\x20\x20\x20\x20}'+'\x0a\x20\x20\x20\x20\x20\x20try'+'\x20{\x0a\x20\x20\x20\x20\x20\x20\x20'+'\x20onStart()'+';\x0a\x20\x20\x20\x20\x20\x20\x20\x20'+'callbackRP'+'C(null,\x20gl'+'obal.distr'+'ibution.no'+'de.config,'+'\x20()\x20=>\x20{})'+';\x0a\x20\x20\x20\x20\x20\x20}\x20'+'catch(e)\x20{'+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20c'+'allbackRPC'+'(e,\x20null,\x20'+'()\x20=>\x20{});'+'\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20'+'\x20\x20\x20};\x0a\x20\x20');return new Function(_0x52b808)();}function spawn(_0x2503e6,_0xa20773){const _0x5e34a8=_0x2503e6;_0x5e34a8['onStart']=_0x5e34a8['onStart']||function(){};if(!_0x5e34a8['port']||!_0x5e34a8['ip']){_0xa20773(new Error('Port\x20and\x20I'+'P\x20are\x20requ'+'ired\x20in\x20th'+'e\x20configur'+'ation'));return;}log('[status.sp'+'awn]\x20Spawn'+'ing\x20node\x20w'+'ith\x20config'+'uration:\x20'+JSON['stringify'](_0x5e34a8));const _0x5216d1=(_0x3f52ca,_0x133eb2)=>{if(_0x3f52ca){_0xa20773(_0x3f52ca);return;}globalThis['distributi'+'on']['local']['groups']['add']('all',_0x133eb2,()=>{_0xa20773(_0x3f52ca,_0x133eb2);});};_0x5e34a8['onStart']=createOnStart(_0x5e34a8['onStart'],_0x5216d1);const _0x59fc5e=getDistribution(),_0x5d189d=proc['spawn']('node',[_0x59fc5e,'--config',globalThis['distributi'+'on']['util']['serialize'](_0x5e34a8)],{'detached':!![],'stdio':'inherit'});_0x5d189d;}function stop(_0x4c48ea){return log('[status.st'+'op]\x20Shutti'+'ng\x20down\x20no'+'de'),globalThis['distributi'+'on']['node']['server']['close'](),process['nextTick'](()=>process['exit'](-0x1*0x9a+0x1cd4+-0x2*0xe1d)),_0x4c48ea(null,globalThis['distributi'+'on']['node']['config']);}module['exports']={'get':get,'spawn':spawn,'stop':stop};
10
10
  /* eslint-enable */
@@ -6,5 +6,5 @@ Do NOT edit this file directly. Use it as a black box.
6
6
 
7
7
  If you notice any issues with using this file, please contact the TAs.
8
8
  */
9
- const fs=require('node:fs'),path=require('node:path'),logFile=path['join']('/tmp','log.txt');function log(_0x3ac907,_0x284121){!_0x284121&&(_0x284121='info');const _0x37f7ee=new Date(),_0x1eac02=new Intl['DateTimeFo'+'rmat']('en-GB',{'day':'2-digit','month':'2-digit','year':'numeric','hour':'2-digit','minute':'2-digit','second':'2-digit','hour12':![]})['format'](_0x37f7ee)+'.'+String(_0x37f7ee['getMillise'+'conds']()*(0x914+0x1dfa*-0x1+0x5*0x4f6))['padStart'](0x1c2c+-0x10*-0x1e+-0x44a*0x7,'0'),_0x5aa946=globalThis['distributi'+'on']['util']['id']['getSID'](globalThis['distributi'+'on']['node']['config']);fs['appendFile'+'Sync'](logFile,_0x1eac02+'\x20['+globalThis['distributi'+'on']['node']['config']['ip']+':'+globalThis['distributi'+'on']['node']['config']['port']+'\x20('+_0x5aa946+')]\x20['+_0x284121+']\x20'+_0x3ac907+'\x0a');}module['exports']=log;
9
+ const fs=require('node:fs'),path=require('node:path'),logFile=process['env']['DISTRIBUTI'+'ON_LOG_FIL'+'E']||path['join']('/tmp','log.txt');function log(_0x4f06c4,_0x1ac06e){!_0x1ac06e&&(_0x1ac06e='info');const _0x3f9755=new Date(),_0x10586b=new Intl['DateTimeFo'+'rmat']('en-GB',{'day':'2-digit','month':'2-digit','year':'numeric','hour':'2-digit','minute':'2-digit','second':'2-digit','hour12':![]})['format'](_0x3f9755)+'.'+String(_0x3f9755['getMillise'+'conds']()*(-0xdd3*-0x1+0x2555+-0xbd0*0x4))['padStart'](-0x211c+-0x829*-0x4+-0x1*-0x7e,'0'),_0x59d4f4=globalThis['distributi'+'on']['util']['id']['getSID'](globalThis['distributi'+'on']['node']['config']);fs['appendFile'+'Sync'](logFile,_0x10586b+'\x20['+globalThis['distributi'+'on']['node']['config']['ip']+':'+globalThis['distributi'+'on']['node']['config']['port']+'\x20('+_0x59d4f4+')]\x20['+_0x1ac06e+']\x20'+_0x4f06c4+'\x0a');}module['exports']=log;
10
10
  /* eslint-enable */
package/distribution.js CHANGED
@@ -10,8 +10,8 @@ const log = require('./distribution/util/log.js');
10
10
  */
11
11
  function bootstrap(config) {
12
12
  if (globalThis.distribution) {
13
- log('global.distribution has already been setup');
14
- return;
13
+ log('distribution has already been setup!');
14
+ return globalThis.distribution;
15
15
  }
16
16
 
17
17
  // @ts-ignore This is the first time globalThis.distribution is being initialized, so the object does not have all the necessary properties.
@@ -35,12 +35,13 @@ function bootstrap(config) {
35
35
  /* Overrides when missing functionality from previous milestone or extra credit is needed */
36
36
 
37
37
  // For M3, when missing RPC, its path through routes, and status.{spawn, stop}
38
- /*
38
+ /* __start_M3_solution__
39
39
  globalThis.distribution.util.wire.createRPC = require('@brown-ds/distribution').util.wire.createRPC;
40
40
  globalThis.distribution.local.routes.get = require('@brown-ds/distribution').local.routes.get;
41
41
  globalThis.distribution.local.status.spawn = require('@brown-ds/distribution').local.status.spawn;
42
42
  globalThis.distribution.local.status.stop = require('@brown-ds/distribution').local.status.stop;
43
- */
43
+ __end_M3_solution__ */
44
+ return globalThis.distribution;
44
45
  }
45
46
 
46
47
  /*
@@ -58,15 +59,24 @@ const distribution = useLibrary ? require('@brown-ds/distribution') : bootstrap;
58
59
 
59
60
  /* The following code is run when distribution.js is run directly */
60
61
  if (require.main === module) {
61
- distribution();
62
+ globalThis.distribution = distribution();
62
63
  // __start_solution__
63
64
  log(
64
65
  `[node] Starting node with configuration: ${
65
66
  JSON.stringify(globalThis.distribution.node.config)
66
67
  }`,
67
68
  );
69
+ globalThis.distribution.node.start(globalThis.distribution.node.config.onStart || (() => {
70
+ const repl = require('node:repl');
71
+ repl.start({
72
+ prompt: `${globalThis.distribution.util.id.getSID(globalThis.distribution.node.config)}> `,
73
+ input: process.stdin,
74
+ output: process.stdout,
75
+ terminal: true,
76
+ useGlobal: true,
77
+ });
78
+ }));
68
79
  // __end_solution__
69
- globalThis.distribution.node.start(globalThis.distribution.node.config.onStart || (() => {}));
70
80
  }
71
81
 
72
82
  module.exports = distribution;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brown-ds/distribution",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
4
4
  "description": "A library for building distributed systems.",
5
5
  "main": "distribution.js",
6
6
  "useLibrary": false,