Simple Integration
Defining actor
1const { AbstractActor } = require('@bluepjs/vm')
2
3/**
4 Demo Actor is a simple object, with `counter` state
5 When Demo Actor object is created - it starts 5 secons interval function incrementing counter state by one on every tick.
6 Demo Actor has two methods:
7 - reset - to reset `counter` state to zero
8 - set(counter) - to set `counter` state to `counter` input
9 On every interval tick Demo Counter emits `tick` event with `counter` state output
10*/
11class DemoActor extends AbstractActor {
12 /**
13 Static method provide information about actor for IDE
14 overrides static AbstractActor::metadata()
15 */
16 static metadata () {
17 return {
18 code: 'demo',
19 name: 'Demo Actor',
20 state: {
21 counter: {
22 code: 'counter',
23 name: 'Counter',
24 type: 'basic/number'
25 }
26 },
27 methods: {
28 reset: {
29 code: 'reset',
30 name: 'Reset'
31 },
32 set: {
33 code: 'set',
34 name: 'Set',
35 inputs: {
36 counter: {
37 code: 'counter',
38 name: 'Counter',
39 type: 'basic/number'
40 }
41 }
42 }
43 },
44 events: {
45 tick: {
46 code: 'tick',
47 event: 'tick',
48 name: 'Tick',
49 outputs: {
50 counter: {
51 code: 'counter',
52 name: 'Counter',
53 type: 'basic/number'
54 }
55 }
56 }
57 }
58 }
59 }
60
61 /**
62 Constructor
63 overrides AbstractActor::constructor(id)
64 @param id - unique actor id. if not exists - autogenerated with uuid.v4
65 */
66 constructor (id) {
67 super(id)
68 this.reset()
69 setInterval(() => {
70 this._tick++
71 this.emit('tick', { counter: this._tick })
72 }, 5000)
73 }
74
75 /**
76 Actor state getter
77 overrides AbstractActor::state(code)
78 @param code - if exists returns only state[code] field. otherwise return full state
79 */
80 state (code) {
81 if (code === 'counter') {
82 return this._tick
83 }
84 return { counter: this._tick }
85 }
86
87 /**
88 Demo Actor reset methed
89 resets counter to zero
90 */
91 reset () {
92 this._tick = 0
93 }
94
95 /**
96 Actor method function
97 overrides AbstractActor::method(method, inputs)
98 @param method - method code
99 @param inputs - method inputs object
100 */
101 async method (method, inputs) {
102 if (this._vm && this._vm._debug) {
103 this._vm.console().log('DemoActor::method', method, inputs)
104 }
105 if (method === 'reset') {
106 this._tick = 0
107 }
108 if (method === 'set' && inputs && typeof inputs.counter === 'number') {
109 this._tick = inputs.counter
110 }
111 }
112}
113
114module.exports = DemoActor
Actor metadata
contains actor description for IDE.
Java Script doesn’t supports multi-inheritance, so if App (Module) Actors already has inheritance chain - it may be hard (or even impossible) for developer to extend AbstractActor
class. In such situation - AbstractActor
interface should be implemented. @bluepjs checks “AbstractActor inheritance” by checking existance of methods.
But at simple case - actors can be directly extended from AbstractActor
what may help developers managing code.
Let’s see all file first, and describe it by parts after:
const { AbstractActor } = require('@bluepjs/vm')
class DemoActor extends AbstractActor {
Actor define single variable counter
at state
:
state: {
counter: {
code: 'counter',
name: 'Counter',
type: 'basic/number'
}
},
For this variable in js code _tick
property is initialized:
this._tick = 0
and returned at state(code)
method:
state (code) {
if (code === 'counter') {
return this._tick
}
return { counter: this._tick }
}
To make actor “live” simple 5sec timer is initialized at constructor, incrementing _tick
and firing tick
event:
setInterval(() => {
this._tick++
this.emit('tick', { counter: this._tick })
}, 5000)
tick
event also described at metadata having one output:
events: {
tick: {
code: 'tick',
event: 'tick',
name: 'Tick',
outputs: {
counter: {
code: 'counter',
name: 'Counter',
type: 'basic/number'
}
}
}
}
Actor’s methods set
and reset
also described in metadata:
methods: {
reset: {
code: 'reset',
name: 'Reset'
},
set: {
code: 'set',
name: 'Set',
inputs: {
counter: {
code: 'counter',
name: 'Counter',
type: 'basic/number'
}
}
}
},
and realized in method(method, inputs)
method:
if (method === 'reset') {
this._tick = 0
}
if (method === 'set' && inputs && typeof inputs.counter === 'number') {
this._tick = inputs.counter
}
Connecting actor
const DemoActor = require('./src/actor')
// actor ID should be unique
// library functions and events currently are "actor-id-dependend"
// sample library configured for used id
const demoActor = new DemoActor('90df7b49-7f94-4ac7-9bec-3193f20908b9')
vm.M('actor').addActor(demoActor)
Blueprints
After created and registered actor - it will be accessible for Blueprints scripting:
There are 3 Blueprints for demonstration:
1st Bleuprint named Log actor state get’s demo actor state variable counter
, and print it to console like Actor counter is: {counter}.
2nd Blueprint is a bit more “complex” - it takes demo actor counter
state, and if it is greater or equal to 5 - call actor’s method reset
.
3rd Blueprint is cron event script, running every 5 seconds. It calls previous blueprints.
Results
Results can be seen both on example project frontend and backend: