-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnetRunner.js
176 lines (168 loc) · 6.2 KB
/
netRunner.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
"use strict";
/*
* net runner is the worker process which implements spheronets in a distributed model
* it uses mongoUtils to get pending spherons, activate them and propogate the resultant signals across output ports / connections to other spherons
*
* ?Should net runner also deal with task completion (i.e. tickNow - tick@impulse > mutateTimeout => outputSignal)?
* ?Should net runner also deal with mutation?
* ?Should net runner also deal with scoring?
*
* ?How do we define a global tick? - direct from the db
*/
var mongoUtils = require('./mongoUtils.js');
var spheron = require('./spheron.js');
var UdpUtils = require('./udpUtils')
var udpUtils = new UdpUtils()
//var thisTick = -1
//Just so we don't throw an error if we hear a UDP broadcast.
udpUtils.on('message',function(thisMessage){
console.log('got message: ' + JSON.stringify(thisMessage))
})
var netRunner = {
init: function(callback){
mongoUtils.init(function(){
mongoUtils.dropDb()
mongoUtils.initTick(function(){
console.log('got back from init - loading network:')
mongoUtils.loadSpheronet('spheronet' ,function(){
console.log('we have loaded the spheronet')
//console.log('generating some offspring - finding a valid spheronetId first.')
mongoUtils.generateOffspring([0],0,100,function(){
callback()
})
})
})
})
},
loadNextPendingSpheron: function(callback){
console.log('loading next pending spheron')
mongoUtils.getNextPendingSpheron(function(nextPendingSpheron){
if(!nextPendingSpheron.value){
console.log('we had an error getting our next spheron - maybe we should do something else:')
callback(null)
} else {
console.log('next Spheron to process is: ' + JSON.stringify(nextPendingSpheron))
callback(nextPendingSpheron.value)
}
})
},
activateAndPersist: function(thisSpheronData, callback){
console.log('activating and persisting: ' + JSON.stringify(thisSpheronData))
var thisSpheron = new spheron(thisSpheronData.io)
var v = {}
v.io = thisSpheron.activate()
console.log('we finished activating: ' + JSON.stringify(v))
/*
* The Spheron currently returns data back as port:value - however, we need to store the data as port.val:val
*/
for(var thisKey in v.io){
console.log('this key: ' + thisKey)
var finalVal = v.io[thisKey]
v.io[thisKey] = {}
v.io[thisKey].val = finalVal
}
mongoUtils.updateSpheron(thisSpheronData.spheronId, thisSpheronData.spheronetId, v, function(){
console.log('persisted new value')
callback()
})
},
propagate: function(thisSpheronData, callback){
console.log('propagating')
var thisPorts = []
for(var thisPort in thisSpheronData.io){
if(thisSpheronData.io[thisPort].type == "output"){
//TODO: find any connections
thisPorts.push(thisPort)
}
}
this.propagateIterator(thisSpheronData, thisPorts, 0, function(){
callback()
})
},
propagateIterator: function(thisSpheronData, thisPorts, idx, callback){
var that = this
if(thisPorts[idx]){
//TODO: Find a connection by fromId fromPort
mongoUtils.findConnectionByInputId(thisSpheronData.spheronId, thisPorts[idx], thisSpheronData.spheronetId, function(thisConnection){
if(thisConnection){
console.log("found a connection: " + JSON.stringify(thisConnection) + 'propogating the value: ' + thisSpheronData.io[thisPorts[idx]].val + ' to connected spherons.')
//process.exit()
var v = {
io: {}
}
v.io[thisConnection.inputId] = {}
v.io[thisConnection.inputId].val = thisSpheronData.io[thisPorts[idx]].val
v.state = 'pending'
console.log('update message: ' + JSON.stringify(v))
mongoUtils.getTick(function(thisTickMsg){
console.log('this tick: ' + JSON.stringify(thisTickMsg))
v.stateTickStamp = thisTickMsg +1
mongoUtils.updateSpheron(thisConnection.toId, thisSpheronData.spheronetId, v, function(){
console.log('spheron updated')
//TODO: set the downstream spherons input to the outputValue and their state to pending and their pendtickstate????
//However, out connection object should reference spherons by their spheronId - which means we should set this during
//data ingestion...
idx +=1
that.propagateIterator(thisSpheronData, thisPorts, idx, callback)
})
})
} else {
idx +=1
that.propagateIterator(thisSpheronData, thisPorts, idx, callback)
}
})
} else {
callback()
}
},
setState: function(thisSpheronData, newState, callback){
console.log('updating spheron state')
mongoUtils.updateSpheron(thisSpheronData.spheronId, thisSpheronData.spheronetId, {state: newState}, function(){
callback()
})
},
runSpheron: function(thisSpheronData, callback){
var that = this
this.activateAndPersist(thisSpheronData, function(){
that.propagate(thisSpheronData, function(){
that.setState(thisSpheronData, "idle", function(){
console.log('finished running spheron')
callback()
})
})
})
},
run: function(){
netRunner.loadNextPendingSpheron(function(nextPendingSpheron){
if(nextPendingSpheron){
console.log('we got back from loading the next spheron with: ' + JSON.stringify(nextPendingSpheron))
netRunner.runSpheron(nextPendingSpheron, function(){
console.log('done processing this spheron - lets ask for some more work...')
setTimeout(function(){
netRunner.run()
},1)
})
} else {
//TODO: Implement housekeeping / generational / evolution mechanism storing system state in db to prevent chatter - or instead use a UDP datagram strategy??
/*
* First client that gets here should toggle a parameter in the db.
* Second client should just go into a stand-off strategy?
* First client looks for:
* problemDomainIds (i.e. problems) where all spherons are idle and currentSystemTick - startTick > timeout as defined in the individual spheronets metadata...
* If we find one of those then thats a signal to run health against the population and evolve...
*/
//Increment tick
console.log('Incrementing system tick')
mongoUtils.incrementTick(function(thisTick){
udpUtils.sendMessage("{tick:" + thisTick + "}")
setTimeout(function(){
netRunner.run()
},1)
})
}
})
}
}
netRunner.init(function(){
netRunner.run()
})