Skip to content

Commit 39aa362

Browse files
Engine.run now returns almanac in addition to events
1 parent 1e0c404 commit 39aa362

7 files changed

+76
-21
lines changed

Diff for: docs/engine.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ engine.removeOperator('startsWithLetter');
139139

140140

141141

142-
### engine.run([Object facts], [Object options]) -> Promise (Events)
142+
### engine.run([Object facts], [Object options]) -> Promise ({ events: Events, almanac: Almanac})
143143

144144
Runs the rules engine. Returns a promise which resolves when all rules have been run.
145145

@@ -153,10 +153,12 @@ engine.run({ userId: 1 })
153153
// returns rule events that were triggered
154154
engine
155155
.run({ userId: 1 })
156-
.then(function(events) {
157-
console.log(events)
156+
.then(function(results) {
157+
console.log(results.events)
158+
// almanac available via results.almanac to interact with as defined in Almanac docs
158159
})
159160
```
161+
Link to the [Almanac documentation](./almanac.md)
160162

161163
### engine.stop() -> Engine
162164

Diff for: examples/01-hello-world.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ let facts = { displayMessage: true }
5353
// run the engine
5454
engine
5555
.run(facts)
56-
.then(triggeredEvents => { // engine returns a list of events with truthy conditions
57-
triggeredEvents.map(event => console.log(event.params.data.green))
56+
.then(results => { // engine returns an object with a list of events with truthy conditions
57+
results.events.map(event => console.log(event.params.data.green))
5858
})
5959
.catch(console.log)
6060

Diff for: examples/02-nested-boolean-logic.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ let facts = {
6464
// run the engine
6565
engine
6666
.run(facts)
67-
.then(events => { // run() return events with truthy conditions
68-
events.map(event => console.log(event.params.message.red))
67+
.then(results => { // run() return and object containing events with truthy conditions
68+
results.events.map(event => console.log(event.params.message.red))
6969
})
7070
.catch(console.log)
7171

Diff for: examples/03-dynamic-facts.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ engine.addFact('account-information', function (params, almanac) {
7171
let facts = { accountId: 'lincoln' }
7272
engine
7373
.run(facts)
74-
.then(events => {
75-
if (!events.length) return
76-
console.log(facts.accountId + ' is a ' + events.map(event => event.params.message))
74+
.then(results => {
75+
if (!results.events.length) return
76+
console.log(facts.accountId + ' is a ' + results.events.map(event => event.params.message))
7777
})
7878
.catch(err => console.log(err.stack))
7979

Diff for: examples/07-rule-chaining.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
/*
44
* This is an advanced example demonstrating rules that passed based off the
5-
* results of other rules
5+
* results of other rules by adding runtime facts. It also demonstrates
6+
* accessing the runtime facts after engine execution.
67
*
78
* Usage:
89
* node ./examples/07-rule-chaining.js
@@ -83,17 +84,35 @@ engine
8384
facts = { accountId: 'washington', drinksOrangeJuice: true, enjoysVodka: true, isSociable: true }
8485
engine
8586
.run(facts) // first run, using washington's facts
87+
.then((results) => {
88+
// access whether washington is a screwdriverAficionado,
89+
// which was determined at runtime via the rules `drinkRules`
90+
return results.almanac.factValue('screwdriverAficionado')
91+
})
92+
.then(isScrewdriverAficionado => {
93+
console.log(`${facts.accountId} ${isScrewdriverAficionado ? 'IS'.green : 'IS NOT'.red} a screwdriver aficionado`)
94+
})
8695
.then(() => {
8796
facts = { accountId: 'jefferson', drinksOrangeJuice: true, enjoysVodka: false, isSociable: true }
8897
return engine.run(facts) // second run, using jefferson's facts; facts & evaluation are independent of the first run
8998
})
99+
.then((results) => {
100+
// access whether jefferson is a screwdriverAficionado,
101+
// which was determined at runtime via the rules `drinkRules`
102+
return results.almanac.factValue('screwdriverAficionado')
103+
})
104+
.then(isScrewdriverAficionado => {
105+
console.log(`${facts.accountId} ${isScrewdriverAficionado ? 'IS'.green : 'IS NOT'.red} a screwdriver aficionado`)
106+
})
90107
.catch(console.log)
91108

92109
/*
93110
* OUTPUT:
94111
*
95112
* washington DID meet conditions for the drinks-screwdrivers rule.
96113
* washington DID meet conditions for the invite-to-screwdriver-social rule.
114+
* washington IS a screwdriver aficionado
97115
* jefferson did NOT meet conditions for the drinks-screwdrivers rule.
98116
* jefferson did NOT meet conditions for the invite-to-screwdriver-social rule.
117+
* jefferson IS NOT a screwdriver aficionado
99118
*/

Diff for: src/engine.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,12 @@ class Engine extends EventEmitter {
227227
cursor.then(() => {
228228
this.status = FINISHED
229229
debug(`engine::run completed`)
230-
resolve(almanac.factValue('success-events'))
230+
return almanac.factValue('success-events')
231+
}).then(events => {
232+
resolve({
233+
events,
234+
almanac
235+
})
231236
}).catch(reject)
232237
})
233238
}

Diff for: test/engine-run.test.js

+38-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ describe('Engine: run', () => {
1313
sandbox.restore()
1414
})
1515

16-
let event = { type: 'generic' }
1716
let condition21 = {
1817
any: [{
1918
fact: 'age',
@@ -33,9 +32,9 @@ describe('Engine: run', () => {
3332
beforeEach(() => {
3433
eventSpy = sandbox.spy()
3534
engine = engineFactory()
36-
rule = factories.rule({ conditions: condition21, event })
35+
rule = factories.rule({ conditions: condition21, event: { type: 'generic1' } })
3736
engine.addRule(rule)
38-
rule2 = factories.rule({ conditions: condition75, event })
37+
rule2 = factories.rule({ conditions: condition75, event: { type: 'generic2' } })
3938
engine.addRule(rule2)
4039
engine.on('success', eventSpy)
4140
})
@@ -65,22 +64,52 @@ describe('Engine: run', () => {
6564
describe('returns', () => {
6665
it('activated events', () => {
6766
return engine.run({ age: 30 }).then(results => {
68-
expect(results.length).to.equal(1)
69-
expect(results).to.deep.include(rule.event)
67+
expect(results.events.length).to.equal(1)
68+
expect(results.events).to.deep.include(rule.event)
7069
})
7170
})
7271

7372
it('multiple activated events', () => {
7473
return engine.run({ age: 90 }).then(results => {
75-
expect(results.length).to.equal(2)
76-
expect(results).to.deep.include(rule.event)
77-
expect(results).to.deep.include(rule2.event)
74+
expect(results.events.length).to.equal(2)
75+
expect(results.events).to.deep.include(rule.event)
76+
expect(results.events).to.deep.include(rule2.event)
7877
})
7978
})
8079

8180
it('does not include unactived triggers', () => {
8281
return engine.run({ age: 10 }).then(results => {
83-
expect(results.length).to.equal(0)
82+
expect(results.events.length).to.equal(0)
83+
})
84+
})
85+
86+
it('includes the almanac', () => {
87+
return engine.run({ age: 10 }).then(results => {
88+
// expect(results.almanac).assert.instanceOf
89+
return results.almanac.factValue('age')
90+
}).then(ageFact => expect(ageFact).to.equal(10))
91+
})
92+
})
93+
94+
describe('facts updated during run', () => {
95+
beforeEach(() => {
96+
engine.on('success', (event, almanac, ruleResult) => {
97+
console.log(ruleResult)
98+
// Assign unique runtime facts per event
99+
almanac.addRuntimeFact(`runtime-fact-${event.type}`, ruleResult.conditions.any[0].value)
100+
})
101+
})
102+
103+
it('returns an almanac with runtime facts added', () => {
104+
return engine.run({ age: 90 }).then(results => {
105+
console.log(results)
106+
return Promise.all([
107+
results.almanac.factValue('runtime-fact-generic1'),
108+
results.almanac.factValue('runtime-fact-generic2')
109+
])
110+
}).then(promiseValues => {
111+
expect(promiseValues[0]).to.equal(21)
112+
expect(promiseValues[1]).to.equal(75)
84113
})
85114
})
86115
})

0 commit comments

Comments
 (0)