git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: caae9f24829761fee3a39f00d7c55a8143825a70

Files: caae9f24829761fee3a39f00d7c55a8143825a70 / actor.js

4307 bytesRaw
1const Message = require('primea-message')
2const CapsManager = require('./capsManager.js')
3const Inbox = require('./inbox.js')
4
5module.exports = class Actor {
6 /**
7 * the Kernel manages the varous message passing functions and provides
8 * an interface for the containers to use
9 * @param {Object} opts
10 * @param {Object} opts.id - the UUID of the Kernel
11 * @param {Object} opts.state - the state of the container
12 * @param {Object} opts.hypervisor - the instance of the hypervisor
13 * @param {Object} opts.container - the container constuctor and argments
14 */
15 constructor (opts) {
16 this.state = opts.state.value
17 this.code = opts.state.value.code
18 this.treeNode = opts.state.node
19 this.hypervisor = opts.hypervisor
20 this.id = opts.id
21 this.container = new opts.container.Constructor(this, opts.container.args)
22 this.inbox = new Inbox({
23 actor: this,
24 hypervisor: opts.hypervisor
25 })
26
27 this.ticks = 0
28 this.containerState = 'idle'
29
30 this.caps = new CapsManager(opts.state.caps)
31 }
32
33 /**
34 * Mints a new capabilitly with a given tag
35 * @param {*} tag - a tag which can be used to identify caps
36 * @return {Object}
37 */
38 mintCap (tag = 0) {
39 return {
40 destId: this.id,
41 tag: tag
42 }
43 }
44
45 /**
46 * adds a message to this containers message queue
47 * @param {string} portName
48 * @param {object} message
49 */
50 queue (message) {
51 this.inbox.queue(message)
52 this._startMessageLoop()
53 }
54
55 /**
56 * runs the creation routine for the actor
57 * @param {object} message
58 * @returns {Promise}
59 */
60 async create (message) {
61 await this.message(message, 'onCreation')
62 this._startMessageLoop()
63 }
64
65 // waits for the next message
66 async _startMessageLoop () {
67 // this ensure we only every have one loop running at a time
68 if (this.containerState !== 'running') {
69 this.containerState = 'running'
70 while (1) {
71 const message = await this.inbox.getNextMessage()
72 if (!message) break
73
74 // if the message we recived had more ticks then we currently have then
75 // update it
76 if (message._fromTicks > this.ticks) {
77 this.ticks = message._fromTicks
78 this.hypervisor.scheduler.update(this)
79 }
80 // run the next message
81 await this.message(message)
82 }
83
84 this.containerState = 'idle'
85 this.container.onIdle()
86 }
87 }
88
89 /**
90 * Runs the shutdown routine for the actor
91 */
92 shutdown () {
93 this.hypervisor.scheduler.done(this.id)
94 }
95
96 /**
97 * Runs the startup routine for the actor
98 */
99 startup () {
100 return this.container.onStartup()
101 }
102
103 /**
104 * run the Actor with a given message
105 * @param {object} message - the message to run
106 * @param {String} method - which method to run
107 * @returns {Promise}
108 */
109 async message (message, method = 'onMessage') {
110 const responseCap = message.responseCap
111 delete message.responseCap
112
113 let result
114 try {
115 result = await this.container[method](message)
116 } catch (e) {
117 console.log(e)
118 result = {
119 exception: true,
120 exceptionError: e
121 }
122 }
123
124 if (responseCap) {
125 this.send(responseCap, new Message({
126 data: result
127 }))
128 }
129 this.caps.clist.clear()
130 }
131
132 /**
133 * updates the number of ticks that the container has run
134 * @param {Number} count - the number of ticks to add
135 */
136 incrementTicks (count) {
137 this.ticks += count
138 this.hypervisor.scheduler.update(this)
139 }
140
141 /**
142 * creates an actor
143 * @param {Integer} type - the type id for the container
144 * @param {Object} message - an intial [message](https://github.com/primea/js-primea-message) to send newly created actor
145 */
146 createActor (type, message) {
147 const id = this._generateNextId()
148 return this.hypervisor.createActor(type, message, id)
149 }
150
151 _generateNextId () {
152 const id = {
153 nonce: this.state.nonce,
154 parent: this.id
155 }
156
157 this.state.nonce++
158 return id
159 }
160
161 /**
162 * sends a message to a given port
163 * @param {Object} portRef - the port
164 * @param {Message} message - the message
165 */
166 send (cap, message) {
167 message._fromTicks = this.ticks
168 message._fromId = this.id
169 message.tag = cap.tag
170
171 return this.hypervisor.send(cap, message)
172 }
173}
174

Built with git-ssb-web